Beispiel #1
0
def split_edges_prior_to_central_dilation(G='G_standard.pkl', 
                                          edges=[3],
                                          savename='G_standard_split.pkl',cf=0.8):
    """Splits specific edges in two end and one central parts, in order to
    prepare them for central dilation / constriction. 
    WARNING: For newly added edges the source is always the smaller
             vertex index and the target the higher vertex index. This needs to
	     be considered in post-processing (e.g. flow direction, position of RBCs)
    INPUT: G: VascularGraph
           edges: Edges to be split
           savename: Name of VascularGraph with split-edges to be saved to
                     disk.
           cf: Center fraction. E.g. cf=2/3 would split the edge into 1/6,
             4/6, 1/6. HOWEVER, the resulting splitting position depends on the number
             of available points and the spacing between the points.
    OUTPUT: None, VascularGraph written to disk.
    """

    savename2=savename
    edges2=edges
    G = vgm.read_pkl(G)
    G.es(edges2)['split'] = [True for e in edges]
    G.add_points(1.)
    while len(G.es(split_ne=None)) > 0:
        eindex = G.es(split_ne=None).indices[0]
        dfactor = 1.
        vi, ei, dilated_ei = G.central_dilation(eindex, dfactor, cf)
        G.es[ei]['split'] = [None for e in ei]
    del G.es['split']
    stdout.write("\rDilation Step \n")
    vgm.write_pkl(G, savename)
Beispiel #2
0
def split_and_steady_state_noRBCs(G='G_standard',edges=[3],fdilation=[1.0],cf=0.8):
    """Test effect of central dilation at a bifurcation of equal-flow daughter
    vessels.
    WARNING: For newly added edges the source is always the smaller
             vertex index and the target the higher vertex index. This needs to
	     be considered in post-processing (e.g. flow direction, position of RBCs)
    INPUT: G: Input Graph as pkl-file (name without the ending .pkl)
           edges: list of edges which are dilated
           fdilation: list of factors by which the edge diameter is changed
           cf: Center fraction. E.g. cf=2/3 would split the edge into 1/6,
             4/6, 1/6. HOWEVER, the resulting splitting position depends on the number
             of available points and the spacing between the points.
    OUTPUT: None, results written to disk.
    """
    filename=G+'.pkl'
    savename='G_split.pkl'
    G = vgm.read_pkl(filename)
    G.add_points(1.)

    G.es['dfactor'] = [None for e in G.es]
    G.es[edges]['dfactor'] = fdilation

    while len(G.es(dfactor_ne=None)) > 0:
        eindex = G.es(dfactor_ne=None).indices[0]
        dfactor = G.es[eindex]['dfactor']
        vi, ei, dilated_ei = G.central_dilation(eindex, dfactor, cf)
        G.es[ei]['dfactor'] = [None for e in ei]
    vgm.write_pkl(G, savename)

    LSd = vgm.LinearSystem(G)

    LSd.solve(method='direct')
Beispiel #3
0
    def evolve(self):
        """ The flow field is recomputed for changing vessel diameters over time. The changing vessel
        diameters have been provided as input in _init_ (diameterOverTime). 
        OUTPUT: None - G is modified in place.
                sampledict.pkl: which saves the pressure for all vertices over time and
                    flow, diameter and RBC velocity for all edges over time.
        """
        G = self._G
        diameterOverTime = self._diameterOverTime
        flow_time_edges=[]
        diameter_time_edges=[]
        v_time_edges=[]
        pressure_time_edges=[]

        #First iteration for initial diameter distribution
        self.solve('iterative2')
        flow_time_edges.append(G.es['flow'])
        diameter_time_edges.append(G.es['diameter'])
        v_time_edges.append(G.es['v'])
        pressure_time_edges.append(G.vs['pressure'])

        for timeStep in range(self._timeSteps):
            edgeSequence = diameterOverTime[timeStep][0]
            G.es[edgeSequence]['diameter'] = diameterOverTime[timeStep][1]
            self.update(esequence=edgeSequence)
            self.solve('iterative2')
            flow_time_edges.append(G.es['flow'])
            diameter_time_edges.append(G.es['diameter'])
            v_time_edges.append(G.es['v'])
            pressure_time_edges.append(G.vs['pressure'])
            vgm.write_pkl(G,'G_'+str(timeStep)+'.pkl')

        flow_edges_time = np.transpose(flow_time_edges)
        diameter_edges_time = np.transpose(diameter_time_edges)
        v_edges_time = np.transpose(v_time_edges)
        pressure_edges_time = np.transpose(pressure_time_edges)

        #Write Output
        sampledict={}
        sampledict['flow']=flow_edges_time
        sampledict['diameter']=diameter_edges_time
        sampledict['v']=v_edges_time
        sampledict['pressure']=pressure_edges_time
        g_output.write_pkl(sampledict, 'sampledict.pkl')

        #Convert 'pBC' from default Units to mmHg
        pBCneNone=G.vs(pBC_ne=None)
        pBCneNone['pBC']=np.array(pBCneNone['pBC'])*(1/self._scalingFactor)
        if len(pBCneNone) > 0:
            if self._verbose:
                print('INFO: Pressure boundary conditions changed from default Units --> mmHg')
Beispiel #4
0
                r.append(np.array([x[0], coord1, coord2]))
            elif case == 2:
                r.append(np.array([coord1, y[0], coord2]))
            elif case == 3:
                r.append(np.array([coord1, coord2, z[0]]))

    valuesGridList = []
    for j in valuesGrid:
        for k in j:
            valuesGridList.append(k)

    planeG = vgm.VascularGraph(len(r))
    planeG.vs['r'] = r
    planeG.vs[attribute] = valuesGridList
    vgm.write_vtp(planeG, filename + '.vtp', False)
    vgm.write_pkl(planeG, filename + '.pkl')

    return grid_d1, grid_d2, valuesGrid, case


#------------------------------------------------------------------------------
def make_axis_labels(minVal, maxVal, factor=1, considerLimits=1):
    """ Creates the labels for an axis. based on the min and max value provided.
    INPUT: minVal: minimum Value of the data
            maxVal: maximum Value of the date
            factor: factor between the actual values and the strings provided 
                (e.g factor = 0.001 --> value 1000 --> string '1.0')
            considerLimits: bool if the labels should be trimmed at the lower/upper bound
    OUTPUT: labels,labelsString: list with the location of the labels and the according strings
            limits: lower and upper limit for the axis
    """
def add_to_db(G, rootVertices, dThreshold, dbDirectory, 
              esr=True, eMin=1, **kwargs):
    """Adds specific vascular trees of a given VascularGraph to a database.
    Performs advanced tree extraction checking for multiple roots and taking 
    only those vertices 'closest' to the provided rootVertices.
    Several information properties are also added to the tree:
    distanceToBorder - the minimal distance of the tree's attachment vertex to
                       the srXTM sample border.
    sampleName - the name of the srXTM sample from which the tree is extracted.
    avZOffset - the distance in z-direction between the attachment vertex and
                the vertex with minimal cortical depth.  
    INPUT: G: VascularGraph.
           rootVertices: The root vertices of the vascular tree to be added.
           dThreshold: The diameter threshold below or equal to which edges are
                       to be ignored (required for tree extraction).
           dbDirectory: The directory of the database as string. If this 
                        directory does not exist, it is created.
           esr: Enforce that all trees have a single root only? (Boolean.)             
           eMin: The minimum number of edges that a tree needs to consist of, in
                 order to be admitted to the database.
           **kwargs:
           vtpDir: The name of the directory in which to save a paraview
                   vtp-file representation of the tree.
           amDir: The name of the directory in which to save an amira am-file
                  representation of the tree.
           sampleName: The name of the srXTM sample from which the tree is
                       taken. (Added to the tree's dictionary.)            
    OUTPUT: None (pickled VascularGraphs written to disk.)                        
    """
    # Create database directory, if nonexistant:
    if not os.path.exists(dbDirectory):
        os.mkdir(dbDirectory)
    
    # Determine number of vascular trees already present in the database:
    dbCount = len(glob.glob1(dbDirectory, '*.pkl'))
    
    # Loop through the rootVertices, extract the corresponding trees and add
    # them to the database:

    discardedTreeCount = 0
    for i, vertex in enumerate(rootVertices):
        vascularTree = vascular_tree_subgraph(G, vertex, dThreshold, esr)
        # Reject tree, if it consists of less than eMin edges:
        if vascularTree.ecount() < eMin:
            discardedTreeCount += 1
            continue

        # Add sample name to the tree's dictionary:
        if kwargs.has_key('sampleName'):
            vascularTree['sampleName'] = kwargs['sampleName']

        # Add the distance attachmentVertex - sample border to the tree's dict:
        shape = vascularTree.shape()
        av = vascularTree.vs[vascularTree['attachmentVertex']]['r'][:2]
        if shape == 'cylinder':
            radius, center = G.radius_and_center()
            vascularTree['distanceToBorder'] = np.linalg.norm(av - center)
        elif shape == 'cuboid':
            minXY = np.min(G.vs['r'], 0)[:2]
            maxXY = np.max(G.vs['r'], 0)[:2]
            vascularTree['distanceToBorder'] = np.min([np.min(av - minXY), np.min(maxXY - av)])

       # Align order zero element with z-axis:    
       # strahler.modified_strahler_order(vascularTree, 0.99)
       # TreeEl = strahler.assign_elements(vascularTree)
       # av = vascularTree['attachmentVertex']
       # avElms = []
       # edgeIndices = []
       # for elm in xrange(TreeEl.vcount()):
       #     if av in TreeEl.vs[elm]['vertices']:
       #         avElms.append((TreeEl.vs[elm]['order'], TreeEl.vs[elm]['edges']))
       # edgeIndices = sorted(avElms, reverse=True)[0][1]
       # points = np.concatenate([[vascularTree.vs[e.source]['r'], 
       #                           vascularTree.vs[e.target]['r']] 
       #                           for e in vascularTree.es[edgeIndices]]) # just node points            
       # z = points[:,2]
       # orderOfIndices = np.argsort(z) # increasing z values
       # direction1 = vgm.g_math.pca(points[orderOfIndices])
       # if np.rad2deg(np.arccos(np.dot(direction1, np.array([0,0,1]))/np.linalg.norm(direction1))) > 90:
       #     direction1 = -direction1
       # direction2 = [0.,0.,1.]
       # vgm.rotate_using_two_vectors(vascularTree, direction1, direction2)

        # Add z_{attachmentVertex} - z_{minimum} to the tree's dict:
        vascularTree['avZOffset'] = vascularTree.vs[vascularTree['attachmentVertex']]['r'][2] - \
                                    np.min(vascularTree.vs['r'], 0)[2]

        # Add vascularTree to database:
        vgm.write_pkl(vascularTree, 
                      os.path.join(dbDirectory, str(dbCount + i - discardedTreeCount) + '.pkl'))
        
        # Write vtp and / or am files if required: 
        for kw, ke, fn in zip(['vtpDir', 'amDir'], ['.vtp', '.am'], 
                              [vgm.write_vtp, vgm.write_amira_mesh_ascii]):
            if kwargs.has_key(kw):
                if not os.path.exists(kwargs[kw]):
                    os.mkdir(kwargs[kw])
                fn(vascularTree, os.path.join(kwargs[kw], str(dbCount + i - discardedTreeCount) + ke))
Beispiel #6
0
    def solve(self,
              method,
              precision=None,
              maxIterations=1e4,
              limiter=0.5,
              **kwargs):
        """Solve for pressure, flow, hematocrit and conductance by iterating
        over linear and rheological analysis. Stop when either the desired
        accuracy has been achieved or the maximum number of iterations have
        been performed.
        INPUT: method: This can be either 'direct' or 'iterative'
               precision: Desired precision, measured in the maximum amount by
                          which the pressure may change from one iteration
                          level to the next. If the maximum change is below
                          threshold, the iteration is aborted.
               maxIterations: The maximum number of iterations to perform.
               limiter: Limits change from one iteration level to the next, if
                        > 1.0, at limiter == 1.0 the change is unmodified.
               **kwargs
               precisionLS: The accuracy to which the ls is to be solved. If
                            not supplied, machine accuracy will be used. (This
                            only applies to the iterative solver)
        OUTPUT: None, the vascular graph is modified in-place.
        """
        G = self._G
        P = self._P
        invivo = self._invivo
        if precision is None: precision = self._eps
        iterationCount = 0
        maxPDiff = 1e200
        filename = 'iter_' + str(iterationCount) + '.vtp'
        g_output.write_vtp(G, filename, False)
        filenames = [filename]

        convergenceHistory = []
        while iterationCount < maxIterations and maxPDiff > precision:
            stdout.write("\rITERATION %g \n" % iterationCount)
            self._rheological_analysis(None, False, limiter=0.5)
            maxPDiff, meanPDiff, medianPDiff = self._linear_analysis(
                method, **kwargs)
            #maxPDiff=self._maxPDiff
            #meanPDiff=self._meanPDiff
            #medianPDiff=self._medianPDiff
            log.info('Iteration %i of %i' %
                     (iterationCount + 1, maxIterations))
            log.info('maximum pressure change: %.2e' % maxPDiff)
            log.info('mean pressure change: %.2e' % meanPDiff)
            log.info('median pressure change: %.2e\n' % medianPDiff)
            convergenceHistory.append((maxPDiff, meanPDiff, medianPDiff))
            iterationCount += 1
            G.es['htt'] = [
                P.discharge_to_tube_hematocrit(e['htd'], e['diameter'], invivo)
                for e in G.es
            ]
            vrbc = P.rbc_volume(self._species)
            G.es['nMax'] = [
                np.pi * e['diameter']**2 / 4 * e['length'] / vrbc for e in G.es
            ]
            G.es['minDist'] = [e['length'] / e['nMax'] for e in G.es]
            G.es['nRBC'] = [
                e['htt'] * e['length'] / e['minDist'] for e in G.es
            ]
            filename = 'iter_' + str(iterationCount) + '.vtp'
            g_output.write_vtp(G, filename, False)
            filenames.append(filename)
        if iterationCount >= maxIterations:
            stdout.write("\rMaximum number of iterations reached\n")
        elif maxPDiff <= precision:
            stdout.write("\rPrecision limit is reached\n")
        self.integrity_check()
        G.es['htt'] = [
            P.discharge_to_tube_hematocrit(e['htd'], e['diameter'], invivo)
            for e in G.es
        ]
        vrbc = P.rbc_volume(self._species)
        G.es['nMax'] = [
            np.pi * e['diameter']**2 / 4 * e['length'] / vrbc for e in G.es
        ]
        G.es['minDist'] = [e['length'] / e['nMax'] for e in G.es]
        G.es['nRBC'] = [e['htt'] * e['length'] / e['minDist'] for e in G.es]
        G.es['v'] = [
            4 * e['flow'] *
            P.velocity_factor(e['diameter'], invivo, tube_ht=e['htt']) /
            (np.pi * e['diameter']**2) if e['htt'] > 0 else 4 * e['flow'] /
            (np.pi * e['diameter']**2) for e in G.es
        ]

        for v in G.vs:
            v['pressure'] = v['pressure'] / vgm.units.scaling_factor_du(
                'mmHg', G['defaultUnits'])
        filename = 'iter_final.vtp'
        g_output.write_vtp(G, filename, False)
        filenames.append(filename)
        g_output.write_pvd_time_series('sequence.pvd', filenames)
        vgm.write_pkl(G, 'G_final.pkl')

        stdout.flush()
        return convergenceHistory
        return G
Beispiel #7
0
    def solve(self, method, precision=None, maxIterations=1e4, limiter=0.5,
              **kwargs):
        """Solve for pressure, flow, hematocrit and conductance by iterating
        over linear and rheological analysis. Stop when either the desired
        accuracy has been achieved or the maximum number of iterations have
        been performed.
        INPUT: method: This can be either 'direct' or 'iterative'
               precision: Desired precision, measured in the maximum amount by
                          which the pressure may change from one iteration
                          level to the next. If the maximum change is below
                          threshold, the iteration is aborted.
               maxIterations: The maximum number of iterations to perform.
               limiter: Limits change from one iteration level to the next, if
                        > 1.0, at limiter == 1.0 the change is unmodified.
               **kwargs
               precisionLS: The accuracy to which the ls is to be solved. If
                            not supplied, machine accuracy will be used. (This
                            only applies to the iterative solver)
        OUTPUT: None, the vascular graph is modified in-place.
        """
        G = self._G
        P = self._P
	invivo=self._invivo
        if precision is None: precision = self._eps
        iterationCount = 0
        maxPDiff = 1e200
        filename = 'iter_'+str(iterationCount)+'.vtp'
        g_output.write_vtp(G, filename, False)
        filenames = [filename]

        convergenceHistory = []
        while iterationCount < maxIterations and maxPDiff > precision:
            stdout.write("\rITERATION %g \n" %iterationCount)
            self._rheological_analysis(None, False, limiter=0.5)
            maxPDiff, meanPDiff, medianPDiff = self._linear_analysis(method, **kwargs)
	    #maxPDiff=self._maxPDiff
	    #meanPDiff=self._meanPDiff
	    #medianPDiff=self._medianPDiff
            log.info('Iteration %i of %i' % (iterationCount+1, maxIterations))
            log.info('maximum pressure change: %.2e' % maxPDiff)
            log.info('mean pressure change: %.2e' % meanPDiff)
            log.info('median pressure change: %.2e\n' % medianPDiff)
            convergenceHistory.append((maxPDiff, meanPDiff, medianPDiff))
            iterationCount += 1
            G.es['htt'] = [P.discharge_to_tube_hematocrit(e['htd'], e['diameter'],invivo)
                           for e in G.es]
            vrbc = P.rbc_volume(self._species)
            G.es['nMax'] = [np.pi * e['diameter']**2 / 4 * e['length'] / vrbc
                            for e in G.es]
            G.es['minDist'] = [e['length'] / e['nMax'] for e in G.es]
            G.es['nRBC'] =[e['htt']*e['length']/e['minDist'] for e in G.es]
            filename = 'iter_'+str(iterationCount)+'.vtp'
            g_output.write_vtp(G, filename, False)
            filenames.append(filename)
        if iterationCount >= maxIterations:
            stdout.write("\rMaximum number of iterations reached\n")
        elif maxPDiff <= precision :
            stdout.write("\rPrecision limit is reached\n")
        self.integrity_check()
        G.es['htt'] = [P.discharge_to_tube_hematocrit(e['htd'], e['diameter'],invivo)
                       for e in G.es]
        vrbc = P.rbc_volume(self._species)
        G.es['nMax'] = [np.pi * e['diameter']**2 / 4 * e['length'] / vrbc
                        for e in G.es]
        G.es['minDist'] = [e['length'] / e['nMax'] for e in G.es]
	G.es['nRBC'] =[e['htt']*e['length']/e['minDist'] for e in G.es]
	G.es['v']=[4 * e['flow'] * P.velocity_factor(e['diameter'], invivo, tube_ht=e['htt']) /
                     (np.pi * e['diameter']**2) if e['htt'] > 0 else
                     4 * e['flow'] / (np.pi * e['diameter']**2)
                     for e in G.es]

        for v in G.vs:
            v['pressure']=v['pressure']/vgm.units.scaling_factor_du('mmHg',G['defaultUnits'])
        filename = 'iter_final.vtp'
        g_output.write_vtp(G, filename, False)
        filenames.append(filename)
        g_output.write_pvd_time_series('sequence.pvd', filenames)
        vgm.write_pkl(G, 'G_final.pkl')

	stdout.flush()
        return convergenceHistory
        return G
Beispiel #8
0
def split_and_evolve_to_steady_state(G='G_standard',edges=[3],fdilation=[1.0],
			   time=4.0e3, ht0=0.4, Greference=None,
                           plotPrms=[0., 4.0e3, 5e1, True],
                           samplePrms=[0., 4.0e3, 2, True],cf=0.8,**kwargs):
    """Test effect of central dilation at a bifurcation of equal-flow daughter
    vessels.
    WARNING: For newly added edges the source is always the smaller
             vertex index and the target the higher vertex index. This needs to
	     be considered in post-processing (e.g. flow direction, position of RBCs)
    INPUT: G: Input Graph as pkl-file (name without the ending .pkl)
  	   edges: list of edges which are dilated
	   fdilation: list of factors by which the edge diameter is changed
	   time: time periode which is evolved
           ht0: initial tube hematocrit value throughout the VascularGraph
                (this is ignored if Greference is defined)
           Greference: VascularGraph from which the initial RBC distribution is
                       to be taken. (If set to None, RBCs will be distributed
                       randomly, respecting the ht0 value supplied) The indices od edges
		       and vertices as well as the direction must exactly the same. Otherwise
		       there will be differences in the positions of RBCs
           plotPrms: plot parameters of RBC position plots (start, stop, step,
                     overwrite)
           samplePrms: sample parameters (start, stop, step, overwrite)
           cf: Center fraction. E.g. cf=2/3 would split the edge into 1/6,
             4/6, 1/6. HOWEVER, the resulting splitting position depends on the number
             of available points and the spacing between the points.
           **kwargs:
               httBC: tube hematocrit boundary condition at inflow
               SampleDetailed:Boolean whether every step should be samplede(True) or
                              if the sampling is done by the given samplePrms(False)
    OUTPUT: None, results written to disk.
    """

    SampleDetailed=False
    if 'SampleDetailed' in kwargs.keys():
        SampleDetailed=kwargs['SampleDetailed']

    filename=G+'.pkl'
    savename='G_split.pkl'
    G = vgm.read_pkl(filename)
    if kwargs.has_key('httBC'):
        for vi in G['av']:
            for ei in G.adjacent(vi):
                    G.es[ei]['httBC']=kwargs['httBC']
    G.add_points(1.)

    G.es['dfactor'] = [None for e in G.es]
    G.es[edges]['dfactor'] = fdilation

    while len(G.es(dfactor_ne=None)) > 0:
        eindex = G.es(dfactor_ne=None).indices[0]
        dfactor = G.es[eindex]['dfactor']
        vi, ei, dilated_ei = G.central_dilation(eindex, dfactor, cf)
        G.es[ei]['dfactor'] = [None for e in ei]
    vgm.write_pkl(G, savename)

    if Greference is not None:
        Gr = vgm.read_pkl(Greference)
        G.es['rRBC'] = copy.deepcopy(Gr.es['rRBC'])
        LSd = vgm.LinearSystemHtd(G, dThreshold=10.0, ht0='current')
    else:    
        LSd = vgm.LinearSystemHtd(G, dThreshold=10.0, ht0=ht0)

    if SampleDetailed:
        LSd.evolve(time=time, method='direct', plotPrms=plotPrms,
               samplePrms=samplePrms,SampleDetailed=True)
    else:
        LSd.evolve(time=time, method='direct', plotPrms=plotPrms,
               samplePrms=samplePrms) 
Beispiel #9
0
def path_between_a_and_v_for_vertexList(G,v,direction='out'):
    """Finds all posible paths from a given vertex that have a specific length.
    The paths can be directed or not directed, depending on the type of graph.
    INPUT: G: Vascular graph in iGraph format.
           v: Vertex List from which the search is to be started. 
           direction: Way to traverse a directed graph. Can be either 'out', 
                      'in', 'out' = from a to v and 'in' = from v to a
    OUTPUT: paths: The possible paths from v.
    """

    pathDict={}
    if direction == 'out':
        stopKind='v'
    else:
        stopKind='a'

    stopPaths=1e5
    stopPaths2=1e6
    indexHalf=np.floor(len(v)/9.)

    #for j in range(9):    
    for j in range(1):    
        pathDict={}
        print('ROUND')
        print(j)
        stdout.flush()
        if j == 9:
            indexStart=indexHalf*j
            indexEnd=len(v)
        else:
            indexStart=indexHalf*j
            indexEnd=indexHalf*(j+1)
        print(indexStart)
        print(indexEnd)
        #for i in v[int(indexStart):int(indexEnd)]:
        for i in v:
            print('')
            print(i)
            paths=[[i]]
            pathsEdges=[[]]
            boolContinue = 1
            newPaths = []
            newPathsEdges = []
            countLoop=0
            stdout.flush()
            while boolContinue:
                print(len(paths))
                stdout.flush()
                countDone=0
                countLoop += 1
                if countLoop > stopPaths:
                    print('Path length is getting too long')
                    break
                if len(paths) > stopPaths2:
                    print('Number of  Path is getting too large')
                    break
                for path,pathEdges in zip(paths,pathsEdges):
                    if G.neighbors(path[-1],type=direction) == []:
                        newPaths.append(path)
                        newPathsEdges.append(pathEdges)
                        countDone += 1
                    else:
                        for neighbor,adjacent in zip(G.neighbors(path[-1],type=direction),G.adjacent(path[-1],type=direction)):
                            if neighbor in path:
                                print('WARNING already in path')
                            if G.vs[neighbor]['kind'] == 'c':
                                newPaths.append(path + [neighbor])
                                newPathsEdges.append(pathEdges + [adjacent])
                            elif G.vs[neighbor]['kind'] == stopKind:
                                newPaths.append(path)
                                newPathsEdges.append(pathEdges)
                                countDone += 1
                            else:
                                pass
                paths = newPaths
                pathsEdges = newPathsEdges
                newPaths = []
                newPathsEdges = []
                if countDone == len(paths):
                    print('Add final vertex')
                    for path in paths:
                        if G.neighbors(path[-1],type=direction) == []:
                            newPaths.append(path)
                            newPathsEdges.append(pathEdges)
                        else:
                            for neighbor,adjacent in zip(G.neighbors(path[-1],type=direction),G.adjacent(path[-1],type=direction)):
                                newPaths.append(path + [neighbor])
                                newPathsEdges.append(pathEdges + [adjacent])
                    paths = newPaths
                    pathsEdges = newPathsEdges
                    boolContinue = 0
            if countLoop > stopPaths:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.0
            elif len(paths) > stopPaths2:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.5
            else:
                dictDummy={}
                dictDummy['vertices']=paths
                dictDummy['edges']=pathsEdges
                dictDummy['finished']=1.0
            pathDict[i]=dictDummy
        vgm.write_pkl(pathDict,'pathDict'+str(j+1)+'.pkl')
def construct_cortical_network(G, gXtm, zLim=None, 
                               originXtm=None, insertXtm=False, invivo=True,BC=[60,10,0.2]):
    """Builds a VascularGraph that includes the pial vessels, penetrating
    arterioles and draining veins, as well as the capillary bed.
    INPUT: G: VascularGraph of the pial network. This should be created using
              the function construct_pial_network().
           gXTM: VascularGraph of srXTM data. This is implanted at location
                 originXtm of the cortical network.
           zLim: Limits of capillary grid in z-direction as tuple (zMin, zMax).
                 If not supplied, it will be determined from the artificial
                 network consisting of pial and penetrating vessels, as well as
                 the SRXTM sample.
           originXtm: The origin (x,y) of the cylindrical srXTM in the cortical
                      network, i.e. the location of its rotational axis. This
                      will be the network's center of mass, if not provided.
           sf: Scaling Factor by which to multiply vertex positions and
               diameters (e.g. to convert units of pixels to microns).
           epperc: Percentage of offshoots that should be en-passent. These are
                   chosen randomly.
           BC: list with pBC at inlet, pBC at outlet, inflow tube hematocrit 
    OUTPUT: G: VascularGraph.
    Note that this function relies on input from control.py
    """
    
    # Get settings from control file:
    basedir = control.basedir
    treeDB = control.treeDB

    eps = finfo(float).eps * 1e4

    # Add offshoots and remove parts with z<0:
    print('Adding offshoots (%i arterial and %i venous)...' % 
          (len(G['apv']), len(G['vpv'])))
    t0 = time.time()
    vcount = G.vcount()
    G.vs['apv']=[0]*G.vcount()
    G.vs['vpv']=[0]*G.vcount()
    for i in G['apv']:
        G.vs[i]['apv']=1
    for i in G['vpv']:
        G.vs[i]['vpv']=1

    x=[]
    y=[]
    for i in G.vs['r']:
        x.append(i[0])
        y.append(i[1])

    xMin=np.min(x)
    xMax=np.max(x)
    yMin=np.min(y)
    yMax=np.max(y)

    stdout.flush()
    print('CHECK DEGREE 1')
    print(max(G.degree()))

    #All deg1 vertices are in apv or vpv or they are in/outlets
    #add arterial penetratiing trees
    G.vs['degree'] = G.degree()
    print('Number of Components: Only pial')
    print(len(G.components()))
    print('Should be KEPT!')
    components=len(G.components())
    #extend_from_db(G, G['apv'], os.path.join(treeDB, 'arteryDB'))
    extend_from_db(G, G['apv'], os.path.join(treeDB, 'arteryDBmouse'))
    print('Number of Components: Artery trees added')
    print(len(G.components()))
    print('CHECK DEGREE 2')
    print(max(G.degree()))
    if len(G.components()) > components:
        print('ERROR')
        print('More components than expected')
    #Assign kind
    G.vs[range(vcount, G.vcount())]['kind'] = ['a' for v in xrange(vcount, G.vcount())]            
    G.vs['degree']=G.degree()
    vcount = G.vcount()
    #add venous penetrating trees
    #extend_from_db(G, G['vpv'], os.path.join(treeDB, 'veinDB'))
    extend_from_db(G, G['vpv'], os.path.join(treeDB, 'veinDBmouse'))
    print('Number of Components: Vein trees added')
    print(len(G.components()))
    print('CHECK DEGREE 3')
    print(max(G.degree()))
    if len(G.components()) > components:
        print('ERROR')
        print('More components than expected')
    #Assign kind
    G.vs[range(vcount, G.vcount())]['kind'] = ['v' for v in xrange(vcount, G.vcount())]           
    G.vs['degree']=G.degree()
    #adding trees lead to some new dead ends at the z=0 level, in contrast to the penetrating vessels their kind 
    #is either 'a' or 'v' but not 'pa' and not 'pv'
    #Remove capillaries (d < 7 mum) in pial vessels and penetrating vessels
    print(str(len(G.es(diameter_le=7)))+' Edges have a diameter which is smaller than 7mum and are therefor removed')
    G.delete_edges(G.es(diameter_le=7))
    G.vs['degree']=G.degree()
    print('Number of Components: Capillaries deleted')
    print(len(G.components())) 
    if len(G.components()) > components:
        print('ERROR')
        print('More components than expected')
        print(components)
        print(len(G.components()))
        for i in len(G.components()):
            print(len(G.components()[i]))
    #Remove vertices where z < 0 (would be abolve pial surface)
    G.vs['z'] = [r[2] for r in G.vs['r']]
    deleteList=G.vs(z_lt=0).indices
    print('Number of vertices where z<0')
    print(len(deleteList))
    deleteList.sort(reverse=True)
    for i in range(len(deleteList)):
        G.delete_vertices(deleteList[i])
    print('Number of components: z lt 0 deleted')
    print(len(G.components()))
    if len(G.components()) > components:
        print('ERROR')
        print('More components than expected')
    G.vs['degree']=G.degree()
    G.delete_vertices(G.vs(degree_eq=0))
    print('Number of components: degree 0 deleted')
    print(len(G.components()))
    if len(G.components()) > components:
        print('ERROR')
        print('More components than expected')
    #Delete len=0 edges
    G.es['length'] = [np.linalg.norm(G.vs[e.source]['r'] - G.vs[e.target]['r']) for e in G.es]
    G.delete_edges(G.es(length_eq=0).indices)
    print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
    G.vs['degree']=G.degree()

    #Delete double Edges
    doubleVertices=[]
    print('CHECK for doule Edges (Edges connecting two similar vertices)')
    #TODO could be changed that only really similiar edges are deleted (see preprocessing SRCTM)
    for i in range(G.vcount()):
        if len(G.neighbors(i)) != len(np.unique(G.neighbors(i))):
            print('')
            print(G.neighbors(i))
            print(np.unique(G.neighbors(i)))
            doubleVertices.append(i)
    print('Number of possible double Edges')
    print(len(doubleVertices))
    
    while len(doubleVertices) > 0:
        for i in doubleVertices:
            neighbors=[]
            print('')
            print(G.neighbors(i))
            print(G.adjacent(i)) 
            adjacents=G.adjacent(i)
            for k,j in enumerate(G.neighbors(i)):
                print('')
                print(k)
                if j in neighbors:
                    G.delete_edges(adjacents[k])
                else:
                    neighbors.append(j)
        
        doubleVertices=[]
        print('len double vertices')
        for i in range(G.vcount()):
            if len(G.neighbors(i)) != len(np.unique(G.neighbors(i))):
                doubleVertices.append(i)
        print(len(doubleVertices))

    #Assign nkind to vertex
    for i in range(G.vcount()):
        if G.vs['kind'][i]=='pa':
            G.vs[i]['nkind']=0
        elif G.vs['kind'][i]=='a':
            G.vs[i]['nkind']=2
        elif G.vs['kind'][i]=='pv':
            G.vs[i]['nkind']=1
        elif G.vs['kind'][i]=='v':
            G.vs[i]['nkind']=3

    vgm.write_pkl(G, 'stage1.pkl')
    vgm.write_pkl(G, 'stage1.vtp')
    print('number of capillaries')
    print(len(G.vs(kind_eq='c')))

    if not zLim is None:
        if max(G.vs['z']) > zLim[1]:
            print('Deleting all vessels below z=%.1f' % (zLim[1]))
            t0 = time.time()
            G.delete_vertices(G.vs(z_gt=zLim[1]))
            print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
            vgm.write_pkl(G, 'stage1b.pkl')

    stdout.flush()
    # Add capillary bed as honeycomb network:
    # Add volume and conductance before adding capillary grid
    print('Adding capillary grid...')
    #all vertices of the network containing the pial vessels and the
    numNCVertices = G.vcount()
    vcount=G.vcount()
    ecount=G.ecount()
    t0 = time.time()
    rMin = np.min(G.vs['r'], axis=0)
    rMax = np.max((np.max(G.vs['r'], axis=0), 
                   (np.max(gXtm.vs['r'], axis=0)-np.min(gXtm.vs['r'], axis=0))), axis=0)
    if not zLim is None:
        rMin[2] = zLim[0]
        rMax[2] = zLim[1]
    print(rMin)
    print(rMax)
    #honeycomb = capillary_bed.randomized_honeycomb(gXtm, (rMin[0], rMax[0]), (rMin[1], rMax[1]), (rMin[2], rMax[2]))
    honeycomb = capillary_bed.honeycomb((rMin[0], rMax[0]), (rMin[1], rMax[1]), (rMin[2], rMax[2]),60)
    print('CHECK DEGREE HONEYCOMB')
    print(max(honeycomb.degree()))
    print(honeycomb.es.attributes())
    print('Edges with 0 length in honeycomb')
    print(len(honeycomb.es(length_eq=0)))
    honeycomb.vs['degree']=honeycomb.degree()
    print('Degree 1 vertices in honeycomb')
    print(len(honeycomb.vs(degree_eq=1)))
    #Honeycomb network is moved such that it finishes at the same level as the pial+penetrating-network
    rMinHC= np.min(honeycomb.vs['r'], axis=0)
    offset=np.array([0.,0.,rMinHC[2]*(-1)])
    print('')
    print('Honeycomb Network is shifted in z-direction by')
    print(offset)
    print('such that zmin of Honeycomb Network = 0')
    vgm.shift(honeycomb,offset)
    print('number of capillaries')
    print(len(G.vs(kind_eq='c')))
    #honeycomb network and pial+penetrating network are put together
    G.disjoint_union_attribute_preserving(honeycomb, 'omit', False)
    print('number of capillaries')
    print(len(G.vs(kind_eq='c')))
    print(len(xrange(vcount, G.vcount())))
    G.vs[range(vcount, G.vcount())]['kind'] = ['c' for v in xrange(vcount, G.vcount())]
    G.vs[range(vcount, G.vcount())]['nkind'] = [5 for v in xrange(vcount, G.vcount())]
    G.vs['capGrid']=np.zeros(G.vcount())
    G.vs[range(vcount,G.vcount())]['capGrid'] = [1]*(G.vcount()-vcount)
    G.es['capGrid']=np.zeros(G.ecount())
    G.es[range(ecount,G.ecount())]['capGrid'] = [1]*(G.ecount()-ecount)
    print('number of capillaries')
    print(len(G.vs(kind_eq='c')))
    print('number of honeycomb vertices')
    print(honeycomb.vcount())
    vcount = G.vcount()
    print(G.es.attributes())
    print('Edges with length 0')
    print(len(G.es(length_eq=0)))
    #print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
    vgm.write_pkl(G, 'stage2.pkl')
    stdout.flush()
    # Connect offshoots to capillary grid to penetrating vessels:
    print('Connecting offshoots to capillary grid...')
    print('number of edges where lenght = 0')
    print(len(G.es(length_eq=0)))
    t0 = time.time()
    G.vs['degree'] = G.degree()
    G.vs['z'] = [r[2] for r in G.vs['r']]
    #vertices with only one adjacent edge 
    #cv edges of penetrating trees with dead end --> to be connected to capillary bed
    cv = G.vs(z_ge=0.0, degree_eq=1,capGrid_eq=0).indices
    print('Number of pials and trees')
    print(numNCVertices)
    print('in cv vertices')
    print(max(cv))
    #In and outlet of pial vessels should be preserved
    for i in G['vv']:
        if i in cv:
            cv.remove(i)
        else:
            print(G.vs[i]['r'])
    for i in G['av']:
        if i in cv:
            cv.remove(i)
        else:
            print(G.vs[i]['r'])

    print(len(G.es(length_eq=0)))
    #Capillary bed should not be attached to pial vessels
    for i in cv:
        if G.vs[i]['kind'] == 'pa':
            print('ERROR')
        if G.vs[i]['kind'] == 'pv':
            print('ERROR')
    Kdt = kdtree.KDTree(honeycomb.vs['r'], leafsize=10)
    print('Dead Ends to connect')
    print(len(cv))
    stdout.flush()
    posConnections=[]
    G.vs['degree']=G.degree()
    print('Are there degree=0 vertices')
    print(len(G.vs(degree_eq=0)))
    #Compute possible Connections for vertices. Maximum degree = 4
    G.vs['posConnections']=[3]*G.vcount()
    deg4=G.vs(degree_ge=4).indices
    G.vs[deg4]['posConnections']=[0]*len(deg4)
    deg3=G.vs(degree_eq=3).indices
    G.vs[deg3]['posConnections']=[1]*len(deg3)
    deg2=G.vs(degree_eq=2).indices
    G.vs[deg2]['posConnections']=[2]*len(deg2)
    print('posConnections assigned')
    stdout.flush()
    print('Possible number of connections')
    posConnections=np.sum(G.vs[numNCVertices:G.vcount()-1]['posConnections'])
    print(posConnections)
    stdout.flush()
    #Start connection process
    for v in cv:
        diameter = G.es[G.adjacent(v)[0]]['diameter']
        newVertexFound=0
        count= 1
        while newVertexFound != 1:
            #start with 5 possible nearest neighbors
            nearestN=Kdt.query(G.vs[v]['r'],k=10*count)
            for i in range((count-1)*10,count*10):
                newVertex=int(nearestN[1][i])
                if G.vs['posConnections'][newVertex+numNCVertices]  == 0:
                    print('No connection possible')
                else:
                   G.vs[newVertex+numNCVertices]['posConnections'] = int(np.round(G.vs[newVertex+numNCVertices]['posConnections'] - 1))
                   newVertexFound = 1
                   break
            count += 1
        print('CONNECTION FOUND')
        print(v)
        stdout.flush()
        nn = newVertex
        #Distance between analyzed endppoint and closest point in honeycomb network
	#Maximum length is set to 5 mum, TODO why is this done? why is not the acrual length used?
        #length = min(5., np.linalg.norm(G.vs[v]['r'] - G.vs[numNCVertices + nn]['r']))
        length = np.linalg.norm(G.vs[v]['r'] - G.vs[numNCVertices + nn]['r'])
        #inewEdges.append((v, numNCVertices+nn))
	#add edge between the points
        G.add_edges((v, numNCVertices + nn))
        G.es[G.ecount()-1]['diameter'] = diameter
        G.es[G.ecount()-1]['length'] = length
    print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
    G.vs['degree'] = G.degree()
    print('CHECK DEGREE 4')
    print(max(G.degree()))


    # Remove edges with length 0 and with degree 1:
    # Deg1 vertices of artificial capillary bed, should be located at the borders of the artificial capillary bed
    print('Number of edges where length is equal to 0')
    print(len(G.es(length_eq=0)))
    G.delete_edges(G.es(length_eq=0).indices)
    print('Number of degree 1 vertices')
    G.vs['degree']=G.degree()
    print(len(G.vs(degree_eq=1)))
    deg1=G.vs(degree_eq=1).indices
    G.vs['av']=[0]*G.vcount()
    G.vs['vv']=[0]*G.vcount()
    for i in G['av']:
        deg1.remove(i)
        G.vs[i]['av']=1
    for i in G['vv']:
        deg1.remove(i)
        G.vs[i]['vv']=1
    G.delete_vertices(deg1)
    G['av']=G.vs(av_eq=1).indices 
    G['vv']=G.vs(vv_eq=1).indices 
    print('Number of degree 1 vertices')
    G.vs['degree']=G.degree()
    print(len(G.vs(degree_eq=1)))
    deg1=G.vs(degree_eq=1).indices
    for i in G['av']:
        deg1.remove(i)
    for i in G['vv']:
        deg1.remove(i)
    G.delete_vertices(deg1)
    print('Number of degree 1 vertices')
    G.vs['degree']=G.degree()
    G['av']=G.vs(av_eq=1).indices 
    G['vv']=G.vs(vv_eq=1).indices 
    print('Number of degree 1 vertices')
    deg1=G.vs(degree_eq=1).indices
    print(len(G.vs(degree_eq=1)))
    for i in G['av']:
        deg1.remove(i)
    for i in G['vv']:
        deg1.remove(i)
    G.delete_vertices(deg1)
    print('Number of degree 1 vertices')
    G.vs['degree']=G.degree()
    G['av']=G.vs(av_eq=1).indices 
    G['vv']=G.vs(vv_eq=1).indices 
    print('Number of degree 1 vertices')
    deg1=G.vs(degree_eq=1).indices
    print(len(G.vs(degree_eq=1)))

    vgm.write_vtp(G, 'stage3.vtp', False)
    vgm.write_pkl(G, 'stage3.pkl')
    stdout.flush()

    # Set conductance of all vessels:
    print('Adding conductance...')
    t0 = time.time()
    aindices = G.vs(kind='pa').indices
    aindices.extend(G.vs(kind='a').indices)
    vindices = G.vs(kind='pv').indices
    vindices.extend(G.vs(kind='v').indices)
    cindices = G.vs(kind='c').indices
    vgm.add_conductance(G, 'a', invivo,edges=G.get_vertex_edges(aindices))
    vgm.add_conductance(G, 'v', invivo,edges=G.get_vertex_edges(vindices))
    vgm.add_conductance(G, 'a', invivo,edges=G.get_vertex_edges(cindices))
    print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
    stdout.flush()

    # Insert srXTM sample at originXtm:
    print('Embedding SRXTM...')
    t0 = time.time()
    if insertXtm:
        G = implant_srxtm.implant_srxtm(G, gXtm, originXtm)    
    print('...done. Time taken: %.1f min' % ((time.time()-t0)/60.))
    G['av']=G.vs(av_eq=1).indices
    G['vv']=G.vs(vv_eq=1).indices
    vgm.write_vtp(G, 'stage4.vtp', False)
    vgm.write_pkl(G, 'stage4.pkl')
    print('stage4 written')
    stdout.flush()
    
    # Delete obsolete graph properties:
    for vProperty in ['z', 'degree', 'nkind', 'epID', 'maxD']:
        if vProperty in G.vs.attribute_names():
            del G.vs[vProperty]
    for eProperty in ['diameter_orig', 'diameter_change', 'cost','depth']:
        if eProperty in G.es.attribute_names():
            del G.es[eProperty]
    for gPropery in ['attachmentVertex', 'sampleName', 'distanceToBorder',
                     'avZOffset']:
        if gPropery in G.attributes():
            del G[gPropery]
    
    # Add a numerical version of vessel kind to facilitate paraview display:
    nkind = {'pa':0, 'pv':1, 'a':2, 'v':3, 'c':4, 'n':5}
    for v in G.vs:
        v['nkind'] = nkind[v['kind']]
    G.vs['degree']=G.degree()
    print('CHECK DEGREE 7')
    print(max(G.vs['degree']))

    #1. If effective Diameter exists it is assigned as diameter
    if 'effDiam' in G.es.attribute_names():
        diamEff=G.es(effDiam_ne=None).indices
        print('effective diameter available')
        print(len(diamEff))
        for i in diamEff:
            G.es[i]['diameter']=G.es[i]['effDiam']

    #2. check if there are degree 0 vertices 
    G.vs['degree']=G.degree()
    deg0=G.vs(degree_eq=0).indices
    print('Degree 0 vertices?')
    print(len(deg0))
    G.delete_vertices(deg0)
    G.vs['degree']=G.degree()

    #Reassign av and vv and apv and vpv
    G['av']=G.vs(av_eq=1).indices
    G['vv']=G.vs(vv_eq=1).indices
    G['apv']=G.vs(apv_eq=1).indices
    G['vpv']=G.vs(vpv_eq=1).indices

    #Eliminate small diameters in capGrid
    diam0capGrid=G.es(diameter_lt=1.0,capGrid_eq=1.).indices
    G.es[diam0capGrid]['diameter']=[1]*len(diam0capGrid)

    #Recheck smalles diameter
    diam0=G.es(diameter_lt=1.0).indices
    if len(diam0) > 0:
        print('ERROR no small diameters should exist')

    #Recheck for loops at deadEnd vertices
    print('check for loops')
    G.es['length2'] = [np.linalg.norm(G.vs[e.source]['r'] -G.vs[e.target]['r']) for e in G.es]
    len0=G.es(length2_eq=0).indices
    print('Len0 Edges are deleted')
    print(len(len0))
    G['infoDeadEndLoops']=len(len0)
    for i in len0:
        e=G.es[i]
        if e.tuple[0] != e.tuple[1]:
            print('WARNING')
    
    G.delete_edges(len0)
    G.vs['degree']=G.degree()
    del(G.es['length2'])

    #Delete new deg1s
    print('Deleting the loops can lead to more degree 1 vertices')
    G.vs['degree']=G.degree()
    deg1=G.vs(degree_eq=1).indices
    print(len(deg1))
    while len(deg1) > len(G['av'])+len(G['vv']):
        print('')
        print(len(deg1))
        av=G.vs(av_eq=1).indices
        vv=G.vs(vv_eq=1).indices
        for i in av:
            if i in deg1:
                deg1.remove(i)
        print(len(deg1))
        for i in vv:
            if i in deg1:
                deg1.remove(i)
        print(len(deg1))
        G.delete_vertices(deg1)
        G.vs['degree']=G.degree()
        deg1=G.vs(degree_eq=1).indices
        stdout.flush()
    
    print('All newly created Dead Ends have ben elimanted')
    G.vs['degree']=G.degree()
    print(len(G.vs(degree_eq=1)))


    #Recheck the degrees of the graph
    G.vs['degree']=G.degree()
    deg1=G.vs(degree_eq=1).indices
    print('Degree 1 vertices')
    print(len(deg1))
    for i in deg1:
        if i not in G['av'] and i not in G['vv']:
            print('ERROR deg1 vertex not in av and neither in vv')

    #Recheck max and min degree
    print('min degree')
    print(min(G.degree()))
    if min(G.degree()) < 1:
        print('ERROR in min degree')
    if np.max(G.vs['degree']) > 4:
        print('ERROR in Maximum degree')
        print(np.max(G.vs['degree']))

    #Reassign av and vv and apv and vpv
    G['av']=G.vs(av_eq=1).indices
    G['vv']=G.vs(vv_eq=1).indices
    G['apv']=G.vs(apv_eq=1).indices
    G['vpv']=G.vs(vpv_eq=1).indices

    # 6. Diameter Srxtm vessels is adjusted such, that at least one RBC fits in
    #    every vessel
    if 'isSrxtm' in G.es.attribute_names():
        P=vgm.Physiology()
        vrbc=P.rbc_volume('mouse')
        G.es['minDist'] = [vrbc / (np.pi * e['diameter']**2 / 4) for e in G.es]
        maxMinDist=max(G.es['minDist'])
        countDiamChanged=0
        diamNew=[]
        edge=[]
        probEdges=G.es(length_lt=1*maxMinDist,isSrxtm_eq=1).indices
        count=0
        for i in probEdges:
            if 1*G.es['minDist'][i] > G.es['length'][i]:
                G.es[i]['diameter']=np.ceil(100*np.sqrt(4*2*vrbc/(np.pi*G.es['length'][i])))/100.
                countDiamChanged += 1
                diamNew.append(np.ceil(100*np.sqrt(4*2*vrbc/(np.pi*G.es['length'][i])))/100.)
                edge.append(i)
            count += 1
    
        print('vessel volume has been increased in')
        print(countDiamChanged)
        G.es['minDist'] = [vrbc / (np.pi * e['diameter']**2 / 4) for e in G.es]
        stdout.flush()
    
    # 7. Length is added to edges which do not have a length yet
    noLength=G.es(length_eq=None).indices
    print('Edges with no length')
    print(len(noLength))
    for i in noLength:
       e=G.es[i]
       G.es[i]['length']=np.linalg.norm(G.vs[e.source]['r']-G.vs[e.target]['r'])
    
    noLength=G.es(length_eq=None).indices
    print('Edges with no length')
    print(len(noLength))

    # 3. Assign pressure BCs
    print('Assign pressure BCs')
    for i in G['av']:
        G.vs[i]['pBC']=BC[0]
        print(G.vs[i]['pBC'])
    
    for i in G['vv']:
        G.vs[i]['pBC']=BC[1]
        print(G.vs[i]['pBC'])
    
    print('Pressure BCs assigned')

    # 4. Assign tube hematocrit boundary conditions
    print('assign inlet tube hematocrits')
    for i in G['av']:
        G.es[G.adjacent(i)[0]]['httBC']=BC[2]

    #Recheck BCs (pBC,rBC, httBC)
    for i in G['av']:
        print('')
        print(G.vs['pBC'][i])
        print(G.vs['rBC'][i])
        print(G.es[G.adjacent(i)]['httBC'])
        if G.vs['pBC'][i] == None and G.vs['rBC'][i] == None:
            print('ERROR in av boundary condition')
        if G.es[G.adjacent(i)]['httBC'] == None:
            print('ERROR in av boundary condition: httBC')
    
    for i in G['vv']:
        print('')
        print(G.vs['pBC'][i])
        print(G.vs['rBC'][i])
        if G.vs['pBC'][i] == None and G.vs['rBC'][i] == None:
            print('ERROR in vv boundary condition')
    
    stdout.flush()

    vgm.write_pkl(G, 'stage5.pkl')
    stdout.flush()
    return G
def construct_pial_network(sf=5, epperc=15, epmode='distributed'):
    """Builds a VascularGraph representing the pial network.
    INPUT: sf: Scaling Factor by which to multiply vertex positions and
               diameters (e.g. to convert units of pixels to microns).
           epperc: Percentage of offshoots that should be en-passent. These are
                   either chosen randomly or such, that the penetrating vessels
                   are distributed as homogeneously as possible.
           epmode: Mode by which en-passent vessels are chosen. This can be
                   either 'random' or 'distributed'
    OUTPUT: G: VascularGraph.
    Note that this function is specifically tuned to the csv files and would
    need to change if the csv files change. Moreover, it relies on input from 
    control.py
    """
    # Get settings from control file:
    basedir = control.basedir
    pialDB = control.pialDB
    av = control.av
    vv = control.vv

    # Read csv files and scale from mm to micron:
    G = vgm.read_csv(os.path.join(pialDB, 'vertices.csv'),
                     os.path.join(pialDB, 'edges.csv'))
    del G.vs['nkind']
    G.vs['r'] = [r * sf for r in G.vs['r']]
    G.es['diameter'] = [d * sf for d in G.es['diameter']]
    G.es['length'] = [np.linalg.norm(G.vs[e.source]['r'] - 
                                     G.vs[e.target]['r'])
                      for e in G.es]
    G.vs['isAv'] = [0] * G.vcount()
    G.vs['isVv'] = [0] * G.vcount()
    # add 'av' and 'vv' from control dict
    G.vs(av)['isAv'] = [1] * len(av)
    G.vs(vv)['isVv'] = [1] * len(vv)

    G.delete_selfloops()
    G.add_points(100)
    G.delete_order_two_vertices()
    minnp = 3

    if epmode == 'distributed':
        # Find arterial and venous components: 
        #Find clusters = group of connected nodes
        co = G.components(mode='weak')
        #all vertices belonging to arterlial network and venous network, respectively
        aComponent = []
        vComponent = []
        for c in co:
            #everything which is not in av => vComponent
            if any(map(lambda x: x in c, av)):
                aComponent.extend(c)
            else:
                vComponent.extend(c)

        G.vs['degree'] = G.degree()
        G.es['nPoints'] = [len(x) for x in G.es['points']]
        G.es['midpoint'] = [np.mean(G.vs[e.tuple]['r'], axis=0) for e in G.es]
        
        epVertices = []
        for component, avvv in zip((aComponent, vComponent), (av, vv)):
            #All edges belong to the component
            edges = G.get_vertex_edges(G.vs(component).indices, 'all', True)
	    #edges where nPoints >= minnp
            edges = G.es(edges, nPoints_ge=minnp).indices
            #vertices of the component with only one adjacent edge
            dovertices = G.vs(component, degree_eq=1).indices
            # Compute number of en-passent offshoots:
            nep = int(epperc / (100 - epperc) * (len(dovertices) - len(avvv)))
            rlist = G.vs(dovertices)['r']
            epEdges = []
            for i in xrange(nep):
                Kdt = kdtree.KDTree(rlist, leafsize=10)
                distances = [(Kdt.query(G.es[e]['midpoint'])[0], e) for e in edges]
		#edge which is farest away
                epEdge = sorted(distances, reverse=True)[0][1]
                edges.remove(epEdge)
                epEdges.append(epEdge)
                rlist.append(G.es[epEdge]['midpoint'])
            newVertices = range(G.vcount(), G.vcount()+len(epEdges))
            component.extend(newVertices)
            epVertices.extend(newVertices)
            for edge in epEdges:
                G.split_edge(edge, int(G.es[edge]['nPoints']/2.), False)
            G.delete_edges(epEdges)
	    #Prevent new vertices from belonging to in and outlet vertices
            G.vs(newVertices)['isVv']=[0]*len(newVertices)
            G.vs(newVertices)['isAv']=[0]*len(newVertices)
        del G.es['midpoint']

    elif epmode == 'random':
        # Compute number of en-passent offshoots:
        nep = epperc / (1 - epperc) * \
              (len(np.nonzero(np.array(G.degree()) == 1)[0]) - len(av) - len(vv))
        G.es['nPoints'] = [len(x) for x in G.es['points']]
        epEdges = np.random.permutation(G.es(nPoints_gt=minnp).indices)[:nep].tolist()
        epVertices = range(G.vcount(), G.vcount()+len(epEdges))
        for edge in epEdges:
            G.split_edge(edge, int(G.es[edge]['nPoints']/2.), False)
        G.delete_edges(epEdges)

        # Find arterial and venous components:
        co = G.components(mode='weak')
        aComponent = []
        vComponent = []
        for c in co:
            if any(map(lambda x: x in c, av)):
                aComponent.extend(c)
            else:
                vComponent.extend(c)

    G['av'] = G.vs(isAv_eq=1).indices
    G['vv'] = G.vs(isVv_eq=1).indices
    del G.vs['isAv']
    del G.vs['isVv']
    del G.es['nPoints']
    #all penetrating vessels
    pv = G.vs(_degree_eq=1).indices
    #if in or outflow -> remove from penetrating vessels
    for prop in ['av', 'vv']:
        for x in G[prop]:
            try:
                pv.remove(x)
            except:
                pass
    #add en passent penetrating vessels
    pv.extend(epVertices)
    G.vs['degree']=G.degree()
    remove=[]
    for i in pv:
        if G.vs['degree'][i] > 2:
            remove.append(i)

    print('Need to be removed')
    print(remove)
    for i in remove:
        pv.remove(i)

    #List of penetratiting arteries (apv) and venules (vpv)
    G['apv'] = [v for v in pv if v in aComponent]
    G['vpv'] = [v for v in pv if v not in aComponent]
    G.vs['degree'] = G.degree()

    #vertex characteristic pial arterty or pial venule
    G.vs[aComponent]['kind'] = ['pa' for v in aComponent]
    G.vs[vComponent]['kind'] = ['pv' for v in vComponent]
    G.vs['nkind'] = [0] * G.vcount()
    #0 = pial artery, 1 = pial venule, 2 = en passent penetrating
    G.vs[aComponent]['nkind'] = [0 for v in aComponent]
    G.vs[vComponent]['nkind'] = [1 for v in vComponent]
    G.vs[epVertices]['nkind'] = [2 for v in epVertices]
    
    # Set in- and outflow pressure boundary conditions.
    # Arterial pressure 60 mmHg, venous pressure 10 mmHg, according to a
    # Hypertesion paper by Harper and Bohlen 1984.
    G.vs[G['av'][0]]['pBC'] = 60 * vgm.scaling_factor_du('mmHg', G['defaultUnits'])
    for v in G['vv']:
        G.vs[v]['pBC'] = 10 * vgm.scaling_factor_du('mmHg', G['defaultUnits'])

    vgm.write_pkl(G,'pial.pkl')
    vgm.write_vtp(G,'pial.vtp',False)
    return G
Beispiel #12
0
def planePlots_paraview(G,edges,intersectionCoords,attribute,filename,interpMethod='linear',gridpoints=100):
    """ Interpolates values on a grid based on the intersection of edges with a plane.
    It outputs a .vtp and a .pkl file to be read into paraview. It returns the grid and the 
    interpolated values at those locations (those can be processed to produce a contour plot in matplotlib)
    INPUT: G: main Graph
           edges: edges which intersect with the plane of interst
           intersectionCoords: coordinates intersection points
           attribute: that should be plotted
           filename: filename (including path) of the .vtp  and .pkl file 
               which will be saved (without file type extension)
           interpMethod: the interpolation method of scipy.interpolate.griddata
               common choices: 'nearest','linear' (default),'cubic'
           gridpoints: number of gridpoints (default = 100)
    OUTPUT: .pkl and .vtp file is written
           grid_d1,grid_d2: grid values
           valuesGrid: interpolated attribute values for the grid
           case: integer to define if the normal vector is in x- (case=1),
               y- (case=2) or in z-direction (case=3)
    """

    values=G.es[edges][attribute]
    x=[]
    y=[]
    z=[]
    for coord in coords:
        x.append(coord[0])
        y.append(coord[1])
        z.append(coord[2])
    
    if len(np.unique(x)) < len(np.unique(y)) and len(np.unique(x)) < len(np.unique(z)):
        case=1
        d1Min=np.min(y)
        d1Max=np.max(y)
        d2Min=np.min(z)
        d2Max=np.max(z)
        d1=y
        d2=z
    elif len(np.unique(y)) < len(np.unique(x)) and len(np.unique(y)) < len(np.unique(z)):
        case=2
        d1Min=np.min(x)
        d1Max=np.max(x)
        d2Min=np.min(z)
        d2Max=np.max(z)
        d1=x
        d2=z
    elif len(np.unique(z)) < len(np.unique(y)) and len(np.unique(z)) < len(np.unique(x)):
        case=3
        d1Min=np.min(x)
        d1Max=np.max(x)
        d2Min=np.min(y)
        d2Max=np.max(y)
        d1=x
        d2=y

    grid_d1,grid_d2=np.mgrid[d1Min:d1Max:(d1Max-d1Min)/100,d2Min:d2Max:(d2Max-d2Min)/100]
    valuesGrid=griddata(zip(d1,d2),values,(grid_d1,grid_d2),method=interpMethod)
    
    r=[]
    for coord1 in np.arange(d1Min,d1Max,(d1Max-d1Min)/100):
        for coord2 in np.arange(d2Min,d2Max,(d2Max-d2Min)/100):
            if case == 1:
                r.append(np.array([x[0],coord1,coord2]))
            elif case == 2:
                r.append(np.array([coord1,y[0],coord2]))
            elif case == 3:
                r.append(np.array([coord1,coord2,z[0]]))
    
    valuesGridList=[]
    for j in valuesGrid:
        for k in j:
            valuesGridList.append(k)
    
    planeG=vgm.VascularGraph(len(r))
    planeG.vs['r']=r
    planeG.vs[attribute]=valuesGridList
    vgm.write_vtp(planeG,filename+'.vtp',False)
    vgm.write_pkl(planeG,filename+'.pkl')

    return grid_d1,grid_d2,valuesGrid,case
Beispiel #13
0
def path_between_a_and_v_for_vertexList(G,v,direction='out'):
    """Finds all posible paths from a given vertex that have a specific length.
    The paths can be directed or not directed, depending on the type of graph.
    INPUT: G: Vascular graph in iGraph format.
           v: Vertex List from which the search is to be started. 
           direction: Way to traverse a directed graph. Can be either 'out', 
                      'in', 'out' = from a to v and 'in' = from v to a
    OUTPUT: paths: The possible paths from v.
    """

    pathDict={}
    if direction == 'out':
        stopKind='v'
    else:
        stopKind='a'

    stopPaths=1e5
    stopPaths2=1e6
    indexHalf=np.floor(len(v)/9.)

    #for j in range(9):    
    for j in range(1):    
        pathDict={}
        print('ROUND')
        print(j)
        stdout.flush()
        if j == 9:
            indexStart=indexHalf*j
            indexEnd=len(v)
        else:
            indexStart=indexHalf*j
            indexEnd=indexHalf*(j+1)
        print(indexStart)
        print(indexEnd)
        #for i in v[int(indexStart):int(indexEnd)]:
        for i in v:
            print('')
            print(i)
            paths=[[i]]
            pathsEdges=[[]]
            boolContinue = 1
            newPaths = []
            newPathsEdges = []
            countLoop=0
            stdout.flush()
            while boolContinue:
                print(len(paths))
                stdout.flush()
                countDone=0
                countLoop += 1
                if countLoop > stopPaths:
                    print('Path length is getting too long')
                    break
                if len(paths) > stopPaths2:
                    print('Number of  Path is getting too large')
                    break
                for path,pathEdges in zip(paths,pathsEdges):
                    if G.neighbors(path[-1],type=direction) == []:
                        newPaths.append(path)
                        newPathsEdges.append(pathEdges)
                        countDone += 1
                    else:
                        for neighbor,adjacent in zip(G.neighbors(path[-1],type=direction),G.adjacent(path[-1],type=direction)):
                            if neighbor in path:
                                print('WARNING already in path')
                            if G.vs[neighbor]['kind'] == 'c':
                                newPaths.append(path + [neighbor])
                                newPathsEdges.append(pathEdges + [adjacent])
                            elif G.vs[neighbor]['kind'] == stopKind:
                                newPaths.append(path)
                                newPathsEdges.append(pathEdges)
                                countDone += 1
                            else:
                                pass
                paths = newPaths
                pathsEdges = newPathsEdges
                newPaths = []
                newPathsEdges = []
                if countDone == len(paths):
                    print('Add final vertex')
                    for path in paths:
                        if G.neighbors(path[-1],type=direction) == []:
                            newPaths.append(path)
                            newPathsEdges.append(pathEdges)
                        else:
                            for neighbor,adjacent in zip(G.neighbors(path[-1],type=direction),G.adjacent(path[-1],type=direction)):
                                newPaths.append(path + [neighbor])
                                newPathsEdges.append(pathEdges + [adjacent])
                    paths = newPaths
                    pathsEdges = newPathsEdges
                    boolContinue = 0
            if countLoop > stopPaths:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.0
            elif len(paths) > stopPaths2:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.5
            else:
                dictDummy={}
                dictDummy['vertices']=paths
                dictDummy['edges']=pathsEdges
                dictDummy['finished']=1.0
            pathDict[i]=dictDummy
        vgm.write_pkl(pathDict,'pathDict'+str(j+1)+'.pkl')
Beispiel #14
0
def path_between_a_and_v_for_vertexList_2(G,v,direction='out'):
    """Finds all posible paths from a given vertex that have a specific length.
    The paths can be directed or not directed, depending on the type of graph.
    INPUT: G: Vascular graph in iGraph format.
           v: Vertex List from which the search is to be started. 
           direction: Way to traverse a directed graph. Can be either 'out', 
                      'in', 'out' = from a to v and 'in' = from v to a
    OUTPUT: paths: The possible paths from v.
    """

    pathDict={}
    if direction == 'out':
        stopKind='v'
    else:
        stopKind='a'

    stopPaths=1e7
    stopPaths2=1e8
    indexHalf=np.floor(len(v)/9.)

    timeProbs=[]
    lengthsProbs=[]
    for j in range(9):    
        pathDict={}
        print('ROUND')
        print(j)
        stdout.flush()
        if j == 8:
            indexStart=indexHalf*j
            indexEnd=len(v)
        else:
            indexStart=indexHalf*j
            indexEnd=indexHalf*(j+1)
        for i in v[indexStart:indexEnd]:
            paths={}
            pathsEdges={}
            reconnection={}
            reconnected={}
            stopReached={}
            paths[0]=[i]
            pathsEdges[0]=[]
            reconnected[0]=0
            reconnection[0]=[]
            stopReached[0]=0
            boolContinue = 1
            countLoop=0
            countReconnected = 0
            stdout.flush()
            allVerts=[]
            boolInfo1=1
            boolInfo2=1
            boolInfo3=1
            boolInfo4=1
            tstart=ttime.time()
            tstep=ttime.time()
            while boolContinue:
                tdiff = tstep-tstart
                if tdiff > 43200:
                    print('stoppend because running longer than 14h')
                    timeProbs.append(i)
                    vgm.write_pkl(timeProbs,'timeProbs.pkl')
                    break
                else:
                    countDone=0
                    countLoop += 1
                    pathsCount=len(paths.keys())
                    if countLoop > 1e4 and boolInfo1 == 1:
                        print('Path length > 1e4')
                        boolInfo1 = 0
                    if countLoop > 1e5 and boolInfo2 == 1:
                        print('Path length > 1e5')
                        boolInfo2 = 0
                    if countLoop > 1e6 and boolInfo3 == 1:
                        print('Path length > 1e6')
                        boolInfo3 = 0
                    if countLoop > 5e6 and boolInfo4 == 1:
                        print('Path length > 5e6')
                        boolInfo4 = 0
                    if countLoop > stopPaths:
                        print('Path length is getting too long')
                        lengthsProbs.append([i,0])
                        break
                    if pathsCount - countReconnected > stopPaths2:
                        print('Number of  Path is getting too large')
                        lengthsProbs.append([i,1])
                        break
                    countReconnected = 0
                    for k in paths.keys():
                        if G.neighbors(paths[k][-1],type=direction) == [] or reconnected[k]== 1:
                            if G.neighbors(paths[k][-1],type=direction) == []:
                                countDone += 1
                            elif reconnected[k]== 1:
                                countReconnected += 1
                        else:
                            countNeighbor = 0
                            pathsOld=paths[k]
                            pathsEdgesOld=pathsEdges[k]
                            neighbors2=[]
                            adjacents2=[]
                            for neighbor,adjacent in zip(G.neighbors(paths[k][-1],type=direction),G.adjacent(paths[k][-1],type=direction)):
                                if neighbor not in neighbors2:
                                    neighbors2.append(neighbor)
                                    adjacents2.append(adjacent)
                            for neighbor,adjacent in zip(neighbors2,adjacents2):
                                if neighbor in paths[k]:
                                    print('WARNING already in path')
                                if G.vs[neighbor]['kind'] == 'c':
                                    if countNeighbor == 0:
                                        if neighbor in allVerts:
                                            for l in paths.keys():
                                                if neighbor in paths[l]:
                                                    reconnection[k] = [l,paths[l].index(neighbor)]
                                                    reconnected[k] = 1
                                                    countReconnected += 1
                                                    break
                                        else:
                                            reconnected[k] = 0
                                        paths[k]=pathsOld + [neighbor]
                                        pathsEdges[k]=pathsEdgesOld + [adjacent]
                                    else:
                                        if neighbor in allVerts:
                                            for l in paths.keys():
                                                if neighbor in paths[l]:
                                                    reconnection[pathsCount] = [l,paths[l].index(neighbor)]
                                                    reconnected[pathsCount] = 1
                                                    countReconnected += 1
                                                    break
                                        else:
                                            reconnected[pathsCount] = 0
                                        paths[pathsCount] = pathsOld + [neighbor]
                                        pathsEdges[pathsCount]=pathsEdgesOld + [adjacent]
                                        reconnected[pathsCount]=0
                                        stopReached[pathsCount]=0
                                        reconnection[pathsCount]=[]
                                        pathsCount = len(paths.keys())
                                    allVerts.append(neighbor)
                                elif G.vs[neighbor]['kind'] == stopKind:
                                    countDone += 1
                                    stopReached[k]=1
                                else:
                                    pass
                                countNeighbor = 1
                        allVerts = np.unique(allVerts)
                        allVerts = allVerts.tolist()
                    if countDone + countReconnected == pathsCount:
                        print('Add final vertex')
                        for k in paths.keys():
                            pathsOld=paths[k]
                            pathsEdgesOld=pathsEdges[k]
                            if reconnected[k] != 1:
                                if G.neighbors(paths[k][-1],type=direction) == []:
                                    pass
                                else:
                                    countNeighbor = 0
                                    neighbors2=[]
                                    adjacents2=[]
                                    for neighbor,adjacent in zip(G.neighbors(paths[k][-1],type=direction),G.adjacent(paths[k][-1],type=direction)):
                                        if neighbor not in neighbors2:
                                            neighbors2.append(neighbor)
                                            adjacents2.append(adjacent)
                                    for neighbor,adjacent in zip(neighbors2,adjacents2):
                                        if countNeighbor == 0:
                                            paths[k]=paths[k] + [neighbor]
                                            pathsEdges[k]=pathsEdges[k] + [adjacent]
                                        else:
                                           paths[pathsCount] = pathsOld + [neighbor]
                                           pathsEdges[pathsCount]=pathsEdgesOld + [adjacent]
                                           pathsCount = len(paths.keys())
                                           reconnected[pathsCount]=0
                                           stopReached[pathsCount]=0
                                           reconnection[pathsCount]=[]
                                        countNeighbor = 1
                        boolContinue = 0
                tstep=ttime.time()
            if countLoop > stopPaths:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.0
                dictDummy['reconnectionPath']=[]
                dictDummy['reconnectionPos']=[]
            elif len(paths) > stopPaths2:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.5
                dictDummy['reconnectionPath']=[]
                dictDummy['reconnectionPos']=[]
            else:
                dictDummy={}
                dictDummy['vertices']=paths
                dictDummy['edges']=pathsEdges
                reconnectedList=[] 
                reconnectionPath=[] 
                reconnectionPos=[]
                stopReachedList=[]
                keys = reconnected.keys()
                keys.sort()
                for k in keys:
                    reconnectedList.append(reconnected[k])
                    stopReachedList.append(stopReached[k])
                    if len(reconnection[k]) > 0:
                        reconnectionPath.append(reconnection[k][0])
                        reconnectionPos.append(reconnection[k][1])
                    else:
                        reconnectionPath.append(None)
                        reconnectionPos.append(None)
                dictDummy['reconnected']=reconnected
                dictDummy['stopReached']=stopReachedList
                dictDummy['reconnectionPath']=reconnectionPath
                dictDummy['reconnectionPos']=reconnectionPos
                dictDummy['finished']=[1]*len(keys)
            pathDict[i]=dictDummy
        vgm.write_pkl(pathDict,'pathDict'+str(j+1)+'.pkl')
Beispiel #15
0
def path_between_a_and_v_for_vertexList_2(G,v,direction='out'):
    """Finds all posible paths from a given vertex that have a specific length.
    The paths can be directed or not directed, depending on the type of graph.
    INPUT: G: Vascular graph in iGraph format.
           v: Vertex List from which the search is to be started. 
           direction: Way to traverse a directed graph. Can be either 'out', 
                      'in', 'out' = from a to v and 'in' = from v to a
    OUTPUT: paths: The possible paths from v.
    """

    pathDict={}
    if direction == 'out':
        stopKind='v'
    else:
        stopKind='a'

    stopPaths=1e7
    stopPaths2=1e8
    indexHalf=np.floor(len(v)/9.)

    timeProbs=[]
    lengthsProbs=[]
    for j in range(9):    
        pathDict={}
        print('ROUND')
        print(j)
        stdout.flush()
        if j == 8:
            indexStart=indexHalf*j
            indexEnd=len(v)
        else:
            indexStart=indexHalf*j
            indexEnd=indexHalf*(j+1)
        for i in v[indexStart:indexEnd]:
            paths={}
            pathsEdges={}
            reconnection={}
            reconnected={}
            stopReached={}
            paths[0]=[i]
            pathsEdges[0]=[]
            reconnected[0]=0
            reconnection[0]=[]
            stopReached[0]=0
            boolContinue = 1
            countLoop=0
            countReconnected = 0
            stdout.flush()
            allVerts=[]
            boolInfo1=1
            boolInfo2=1
            boolInfo3=1
            boolInfo4=1
            tstart=ttime.time()
            tstep=ttime.time()
            while boolContinue:
                tdiff = tstep-tstart
                if tdiff > 43200:
                    print('stoppend because running longer than 14h')
                    timeProbs.append(i)
                    vgm.write_pkl(timeProbs,'timeProbs.pkl')
                    break
                else:
                    countDone=0
                    countLoop += 1
                    pathsCount=len(paths.keys())
                    if countLoop > 1e4 and boolInfo1 == 1:
                        print('Path length > 1e4')
                        boolInfo1 = 0
                    if countLoop > 1e5 and boolInfo2 == 1:
                        print('Path length > 1e5')
                        boolInfo2 = 0
                    if countLoop > 1e6 and boolInfo3 == 1:
                        print('Path length > 1e6')
                        boolInfo3 = 0
                    if countLoop > 5e6 and boolInfo4 == 1:
                        print('Path length > 5e6')
                        boolInfo4 = 0
                    if countLoop > stopPaths:
                        print('Path length is getting too long')
                        lengthsProbs.append([i,0])
                        break
                    if pathsCount - countReconnected > stopPaths2:
                        print('Number of  Path is getting too large')
                        lengthsProbs.append([i,1])
                        break
                    countReconnected = 0
                    for k in paths.keys():
                        if G.neighbors(paths[k][-1],type=direction) == [] or reconnected[k]== 1:
                            if G.neighbors(paths[k][-1],type=direction) == []:
                                countDone += 1
                            elif reconnected[k]== 1:
                                countReconnected += 1
                        else:
                            countNeighbor = 0
                            pathsOld=paths[k]
                            pathsEdgesOld=pathsEdges[k]
                            neighbors2=[]
                            adjacents2=[]
                            for neighbor,adjacent in zip(G.neighbors(paths[k][-1],type=direction),G.adjacent(paths[k][-1],type=direction)):
                                if neighbor not in neighbors2:
                                    neighbors2.append(neighbor)
                                    adjacents2.append(adjacent)
                            for neighbor,adjacent in zip(neighbors2,adjacents2):
                                if neighbor in paths[k]:
                                    print('WARNING already in path')
                                if G.vs[neighbor]['kind'] == 'c':
                                    if countNeighbor == 0:
                                        if neighbor in allVerts:
                                            for l in paths.keys():
                                                if neighbor in paths[l]:
                                                    reconnection[k] = [l,paths[l].index(neighbor)]
                                                    reconnected[k] = 1
                                                    countReconnected += 1
                                                    break
                                        else:
                                            reconnected[k] = 0
                                        paths[k]=pathsOld + [neighbor]
                                        pathsEdges[k]=pathsEdgesOld + [adjacent]
                                    else:
                                        if neighbor in allVerts:
                                            for l in paths.keys():
                                                if neighbor in paths[l]:
                                                    reconnection[pathsCount] = [l,paths[l].index(neighbor)]
                                                    reconnected[pathsCount] = 1
                                                    countReconnected += 1
                                                    break
                                        else:
                                            reconnected[pathsCount] = 0
                                        paths[pathsCount] = pathsOld + [neighbor]
                                        pathsEdges[pathsCount]=pathsEdgesOld + [adjacent]
                                        reconnected[pathsCount]=0
                                        stopReached[pathsCount]=0
                                        reconnection[pathsCount]=[]
                                        pathsCount = len(paths.keys())
                                    allVerts.append(neighbor)
                                elif G.vs[neighbor]['kind'] == stopKind:
                                    countDone += 1
                                    stopReached[k]=1
                                else:
                                    pass
                                countNeighbor = 1
                        allVerts = np.unique(allVerts)
                        allVerts = allVerts.tolist()
                    if countDone + countReconnected == pathsCount:
                        print('Add final vertex')
                        for k in paths.keys():
                            pathsOld=paths[k]
                            pathsEdgesOld=pathsEdges[k]
                            if reconnected[k] != 1:
                                if G.neighbors(paths[k][-1],type=direction) == []:
                                    pass
                                else:
                                    countNeighbor = 0
                                    neighbors2=[]
                                    adjacents2=[]
                                    for neighbor,adjacent in zip(G.neighbors(paths[k][-1],type=direction),G.adjacent(paths[k][-1],type=direction)):
                                        if neighbor not in neighbors2:
                                            neighbors2.append(neighbor)
                                            adjacents2.append(adjacent)
                                    for neighbor,adjacent in zip(neighbors2,adjacents2):
                                        if countNeighbor == 0:
                                            paths[k]=paths[k] + [neighbor]
                                            pathsEdges[k]=pathsEdges[k] + [adjacent]
                                        else:
                                           paths[pathsCount] = pathsOld + [neighbor]
                                           pathsEdges[pathsCount]=pathsEdgesOld + [adjacent]
                                           pathsCount = len(paths.keys())
                                           reconnected[pathsCount]=0
                                           stopReached[pathsCount]=0
                                           reconnection[pathsCount]=[]
                                        countNeighbor = 1
                        boolContinue = 0
                tstep=ttime.time()
            if countLoop > stopPaths:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.0
                dictDummy['reconnectionPath']=[]
                dictDummy['reconnectionPos']=[]
            elif len(paths) > stopPaths2:
                dictDummy={}
                dictDummy['vertices']=[]
                dictDummy['edges']=[]
                dictDummy['finished']=0.5
                dictDummy['reconnectionPath']=[]
                dictDummy['reconnectionPos']=[]
            else:
                dictDummy={}
                dictDummy['vertices']=paths
                dictDummy['edges']=pathsEdges
                reconnectedList=[] 
                reconnectionPath=[] 
                reconnectionPos=[]
                stopReachedList=[]
                keys = reconnected.keys()
                keys.sort()
                for k in keys:
                    reconnectedList.append(reconnected[k])
                    stopReachedList.append(stopReached[k])
                    if len(reconnection[k]) > 0:
                        reconnectionPath.append(reconnection[k][0])
                        reconnectionPos.append(reconnection[k][1])
                    else:
                        reconnectionPath.append(None)
                        reconnectionPos.append(None)
                dictDummy['reconnected']=reconnected
                dictDummy['stopReached']=stopReachedList
                dictDummy['reconnectionPath']=reconnectionPath
                dictDummy['reconnectionPos']=reconnectionPos
                dictDummy['finished']=[1]*len(keys)
            pathDict[i]=dictDummy
        vgm.write_pkl(pathDict,'pathDict'+str(j+1)+'.pkl')
Beispiel #16
0
    def solve(self, method, **kwargs):
        """Solves the linear system A x = b for the vector of unknown pressures
        x, either using a direct solver or an iterative AMG solver. From the
        pressures, the flow field is computed.
        INPUT: method: This can be either 'direct' or 'iterative'
               **kwargs 
               precision: The accuracy to which the ls is to be solved. If not 
                          supplied, machine accuracy will be used.
               maxiter: The maximum number of iterations. The default value for
                        the iterative solver is 250.
        OUTPUT: None - G is modified in place.
        """
                
        b = self._b
        G = self._G
        htt2htd = self._P.tube_to_discharge_hematocrit
        
        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, b)
        elif method == 'iterative':
            if kwargs.has_key('precision'):
                eps = kwargs['precision']
            else:
                eps = self._eps
            if kwargs.has_key('maxiter'):
                maxiter = kwargs['maxiter']
            else:
                maxiter = 250
            AA = pyamg.smoothed_aggregation_solver(A, max_levels=10, max_coarse=500)
            x = abs(AA.solve(self._b, x0=None, tol=eps, accel='cg', cycle='V', maxiter=maxiter))
            # abs required, as (small) negative pressures may arise
        elif method == 'iterative2':
         # Set linear solver
             ml = rootnode_solver(A, smooth=('energy', {'degree':2}), strength='evolution' )
             M = ml.aspreconditioner(cycle='V')
             # Solve pressure system
             x,info = gmres(A, self._b, tol=self._eps, maxiter=50, M=M)
             if info != 0:
                 print('ERROR in Solving the Matrix')

        G.vs['pressure'] = x
        self._x = x
        conductance = self._conductance
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] -   \
                            G.vs[edge.target]['pressure']) *  \
                        conductance[i] for i, edge in enumerate(G.es)]
        for v in G.vs:
            v['pressure']=v['pressure']/vgm.units.scaling_factor_du('mmHg',G['defaultUnits'])
        if self._withRBC:
            for e in G.es:
                dischargeHt = min(htt2htd(e['htt'], e['diameter'], self._invivo), 1.0)
	        e['v']=dischargeHt/e['htt']*e['flow']/(0.25*np.pi*e['diameter']**2)
        else:
            for e in G.es:
	        e['v']=e['flow']/(0.25*np.pi*e['diameter']**2)
        
        #Convert 'pBC' from default Units to mmHg
        pBCneNone=G.vs(pBC_ne=None).indices
        if 'diamCalcEff' in G.es.attribute_names():
            del(G.es['diamCalcEff'])

        if 'effResistance' in G.es.attribute_names():
            del(G.es['effResistance'])

        if 'conductance' in G.es.attribute_names():
            del(G.es['conductance'])

        if 'resistance' in G.es.attribute_names():
            del(G.es['resistance'])

        G.vs[pBCneNone]['pBC']=np.array(G.vs[pBCneNone]['pBC'])*(1/vgm.units.scaling_factor_du('mmHg',G['defaultUnits']))

        vgm.write_pkl(G, 'G_final.pkl')
        vgm.write_vtp(G, 'G_final.vtp',False)

	#Write Output
	sampledict={}
        for eprop in ['flow', 'v']:
            if not eprop in sampledict.keys():
                sampledict[eprop] = []
            sampledict[eprop].append(G.es[eprop])
        for vprop in ['pressure']:
            if not vprop in sampledict.keys():
                sampledict[vprop] = []
            sampledict[vprop].append(G.vs[vprop])

	g_output.write_pkl(sampledict, 'sampledict.pkl')
Beispiel #17
0
def transient_dilation(G='G_standard',edges=[240, 243, 246, 249], 
                  fdilation=[1.1, 1.1, 0.9, 0.9], ttotal=900,ht0=0.4,
                  ttransient=[400, 100, 10], plotstep=2, samplestep=2,**kwargs):
    """Load VascularGraph from disk. Run RBC-transport simulation, where a
    vessel is dilated at some point during the simulation. The dilation occurs
    in several steps. Note that there are some hard-coded variables which need to be
    adjusted if use-case changes!
    INPUT: G: Input Graph as pkl-file (name without the ending .pkl) 
	   edges: List of edges to dilate
           fdilation: List of dilation-factors
           ttotal: total time
           ht0: initial tube hematocrit value throughout the VascularGraph
           ttransient: [tinitial, tduration, steps]= [start of the dilation, 
			time period till dilation is finished, number of steps
			for dilation]
           plotstep: timestep for plotting
	   samplestep: timestep for sampling
           **kwargs:
               httBC: tube hematocrit boundary condition at inflow
	       bigger: 0 = 2 Vessel network, 1= 2in2 Vessel network 2=Honeycomb
	       wholeBr: Boolean whether the whole Branch is dilated (TRUE) or only
		center of the Branch is dilated (FALSE)
    OUTPUT: None, pre- and post-dilation VascularGraph, sample-dictionary, and
            RBC-plots are written to disk.
    """

    filename=G+'.pkl'
    G = vgm.read_pkl(filename)
    if kwargs.has_key('httBC'):
        for vi in G['av']:
            for ei in G.adjacent(vi):
                    G.es[ei]['httBC']=kwargs['httBC']
        
    if kwargs.has_key('bigger'):
        NW=kwargs['bigger']
    else:
        NW=0
    

    if kwargs.has_key('wholeBr'):
        wholeBr=kwargs['wholeBr']
    else:
	wholeBr=False


    G.add_points(1.)
    dilatedList=[]
    
    G.es['dfactor'] = [None for e in G.es]
    G.es[edges]['dfactor'] = 1.0
    
    if wholeBr:
        dilatedList=edges
    else:
        while len(G.es(dfactor_ne=None)) > 0:
            eindex = G.es(dfactor_ne=None).indices[0]
            dfactor = G.es[eindex]['dfactor']
            vi, ei, dilated_ei = G.central_dilation(eindex, dfactor, 4/5.)
            G.es[ei]['dfactor'] = [None for e in ei]
   	    dilatedList.append(dilated_ei)
        for i in range(len(dilatedList)):
            dilatedList[i]=dilatedList[i]-(len(dilatedList)-i-1)
    
    Gd = copy.deepcopy(G)
    LSd = vgm.LinearSystemHtdWCyth(Gd, dThreshold=10.0, ht0=ht0)
    
    #Run simulation without dilation till tinitial is reached
    LSd.evolve(time=ttransient[0], method='direct', 
           plotPrms=[0, ttransient[0], plotstep],
           samplePrms=[0, ttransient[0], samplestep])

    
    #LSd._plot_sample_average('G_pre_dilation.vtp')
    #vgm.write_pkl(Gd, 'G_pre_dilation.pkl')

    tstep = ttransient[1] / ttransient[2]
    Gd.es['dfactor'] = [None for e in G.es]
    Gd.es[dilatedList]['dfactor'] = fdilation
    fsteps = [Gd.es[edge]['diameter'] * (fdil - 1) / ttransient[2]
              for edge, fdil in zip(dilatedList, fdilation)]
    for step in xrange(ttransient[2]):
        for edge, fstep in zip(dilatedList, fsteps):
            Gd.es[edge]['diameter'] += fstep
            stdout.write("\rEdge = %g \n" %edge)
            stdout.write("\rDiameter = %f \n" %Gd.es[edge]['diameter'])
	#START: Consider Change of minDist during dilation of vessel
        LSd._update_minDist_and_nMax(esequence=dilatedList)
	LSd._update_tube_hematocrit(esequence=dilatedList)
	#END: Consider Change of minDist during dilation of vessel
        LSd._update_nominal_and_specific_resistance(esequence=dilatedList)
        LSd._update_eff_resistance_and_LS()
        LSd.evolve(time=tstep, method='direct',
               plotPrms=(0.0, tstep, plotstep),
               samplePrms=(0.0, tstep, samplestep),init=False)
        filename2='G_transient_dilation_'+str(step)+'.vtp'
        LSd._plot_sample_average(filename2)
        vgm.write_pkl(Gd, 'G_transient_dilation_'+str(step)+'.pkl')
        stdout.write("\rDilation Step = %g \n" %step)
        #stdout.write("\rDiameter = %f \n" %Gd.es[342]['diameter'])


    
    tstep = ttotal - ttransient[0] - ttransient[1]
    LSd.evolve(time=tstep, method='direct',
               plotPrms=(0.0, tstep, plotstep),
               samplePrms=(0.0, tstep, samplestep),init=False)

    vgm.write_pkl(Gd, 'G_post_dilation.pkl')
    vgm.write_vtp(Gd, 'G_post_dilation.vtp', False)
Beispiel #18
0
    def solve(self, method, **kwargs):
        """Solves the linear system A x = b for the vector of unknown pressures
        x, either using a direct solver (obsolete) or an iterative GMRES solver. From the
        pressures, the flow field is computed.
        INPUT: method: This can be either 'direct' or 'iterative2'
        OUTPUT: None - G is modified in place.
                G_final.pkl & G_final.vtp: are save as output
                sampledict.pkl: is saved as output
        """
        b = self._b
        G = self._G
        htt2htd = self._P.tube_to_discharge_hematocrit

        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, b)
        elif method == 'iterative2':
            ml = rootnode_solver(A,
                                 smooth=('energy', {
                                     'degree': 2
                                 }),
                                 strength='evolution')
            M = ml.aspreconditioner(cycle='V')
            # Solve pressure system
            #x,info = gmres(A, self._b, tol=self._eps, maxiter=1000, M=M)
            x, info = gmres(A, self._b, tol=10 * self._eps, M=M)
            if info != 0:
                print('ERROR in Solving the Matrix')
                print(info)

        G.vs['pressure'] = x
        self._x = x
        conductance = self._conductance
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] - G.vs[edge.target]['pressure']) *  \
                        conductance[i] for i, edge in enumerate(G.es)]

        #Default Units - mmHg for pressure
        for v in G.vs:
            v['pressure'] = v['pressure'] / vgm.units.scaling_factor_du(
                'mmHg', G['defaultUnits'])

        if self._withRBC:
            G.es['v'] = [
                e['htd'] / e['htt'] * e['flow'] /
                (0.25 * np.pi * e['diameter']**2) for e in G.es
            ]
        else:
            G.es['v'] = [
                e['flow'] / (0.25 * np.pi * e['diameter']**2) for e in G.es
            ]

        #Convert 'pBC' from default Units to mmHg
        pBCneNone = G.vs(pBC_ne=None).indices
        G.vs[pBCneNone]['pBC'] = np.array(G.vs[pBCneNone]['pBC']) * (
            1 / vgm.units.scaling_factor_du('mmHg', G['defaultUnits']))

        vgm.write_pkl(G, 'G_final.pkl')
        vgm.write_vtp(G, 'G_final.vtp', False)

        #Write Output
        sampledict = {}
        for eprop in ['flow', 'v']:
            if not eprop in sampledict.keys():
                sampledict[eprop] = []
            sampledict[eprop].append(G.es[eprop])
        for vprop in ['pressure']:
            if not vprop in sampledict.keys():
                sampledict[vprop] = []
            sampledict[vprop].append(G.vs[vprop])

            g_output.write_pkl(sampledict, 'sampledict.pkl')