Example #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)
Example #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')
def generate_db():
    """Generates a database of vascular trees, both arterial and venous.
    INPUT: None
    OUTPUT: Arterial and venous tree database written to disk.
    Note that this function uses hardcoded directories and filenames!
    """

    ### START INPUT -------------------------------------------------------
    dataDir = pjoin(basedir, 'Data/2010/srXTM_processed')
    outDir = pjoin(basedir, 'Data/2010/vascularTrees')
    vtpDir = pjoin(basedir, 'Data/2010/vascularTrees/vtp')
    amDir = pjoin(basedir, 'Data/2010/vascularTrees/am')
    fileEnding = '_rr.pkl'
    parallel = False
    ### END INPUT ---------------------------------------------------------
    
    if not os.path.exists(outDir):
        os.mkdir(outDir)
    sampleDirs = glob.glob1(dataDir, '*')
    sampleDirs = [sd for sd in sampleDirs if os.path.isdir(os.path.join(dataDir, sd))]
    
    Processes = []
    for sd in sampleDirs:
        print(sd)
        G = vgm.read_pkl(os.path.join(dataDir, sd, sd+fileEnding))
        vertices = []
        if ('av' in G.attributes()) and ('vv' in G.attributes()):
            vertices.append(G['av'])
            vertices.append(G['vv'])
        else:
            for vtype in ['arteries', 'veins']:
                coords = vgm.read_landmarks(os.path.join(dataDir, sd, vtype+'_'+sd))
                vs = vgm.vertices_from_coordinates(G, coords)
                if max(vs[1]) > 0.0:
                    print('WARNING: landmark file %s faulty!' % vtype+'_'+sd)
                vertices.append(vs[0])
        if parallel:       
            P1 = mp.Process(target=add_to_db, args=(G, vertices[0], 7., os.path.join(outDir, 'arteryDB')), 
                            kwargs={'sampleName':sd, 'vtpDir':vtpDir+'_artery','amDir':amDir+'_artery'})
            P2 = mp.Process(target=add_to_db, args=(G, vertices[1], 7., os.path.join(outDir, 'veinDB')), 
                            kwargs={'sampleName':sd, 'vtpDir':vtpDir+'_vein','amDir':amDir+'_vein'})
            P1.start()
            P2.start()
            P1.join()
            P2.join()
        else:                         
            add_to_db(G, vertices[0], 7., os.path.join(outDir, 'arteryDB'),
                      sampleName=sd, vtpDir=vtpDir+'_artery',amDir=amDir+'_artery')
            add_to_db(G, vertices[1], 7., os.path.join(outDir, 'veinDB'),
                      sampleName=sd, vtpDir=vtpDir+'_vein', amDir=amDir+'_vein')
def export(input_dir, output_dir):
    """Exports pickled iGraph files to GraphML format.
    INPUT: input_dir: The directory where the pickled iGraph files reside.
           output_dir: The directory in which to store the GraphML files.
    OUTPUT: GraphML files written to disk.
    """
    files = glob.glob1(input_dir, '*.pkl')
    if os.path.isdir(output_dir):
        ans = raw_input('Directory %s exists. Overwrite files? [y/n]:  ' % output_dir)
        if ans[0] == 'y':
            gml_files = glob.glob(os.path.join(output_dir, '*'))
            map(os.remove, gml_files)
        else:
            return
    else:
        os.mkdir(output_dir)

    for f in files:
        outname = f[:-4] + '.graphml'
        G = vgm.read_pkl(os.path.join(input_dir,f))
        # Delete unnecessary vertex properties:
        v_attributes = G.vs.attribute_names() 
        for va in v_attributes:
            if va not in ['r']:
                del G.vs[va]
        # Delete unnecessary edge properties:
        e_attributes = G.es.attribute_names() 
        for ea in e_attributes:
            if ea not in ['diameter', 'diameters', 'length', 'lengths', 'points']:
                del G.es[ea]

        # Delete unnecessary graph properties:
        g_attributes = G.attributes()
        for ga in g_attributes:
            if ga not in ['attachmentVertex', 'sampleName', 'distanceToBorder', 'defaultUnits', 'avZOffset']:
                del G[ga]

        vgm.write_graphml(G, os.path.join(output_dir, outname))
def extend_from_db(G, attachmentVertices, dbDirectory):
    """Extends a VascularGraph at given attachment vertices with vascular trees
    chosen randomly from a tree database.
    INPUT: G: VascularGraph
           attachmentVertices: Vertices at which the vascular trees are to be
                               attached.
           dbDirectory: The directory of the database as string.
    OUTPUT: None (G is modified in-place.)                           
    """
    # Get names of database files:
    dbFiles = glob.glob1(dbDirectory, '*.pkl')
    # Determine number of vascular trees present in the database:
    dbCount = len(dbFiles)
    
    # At each attachment vertex, extend the VascularGraph with a vascular tree
    # from the database:
    Gtrees = vgm.VascularGraph(0)
    treeno = 1
    G.vs['degree']=G.degree()
    for vertex in attachmentVertices:
        #print('Tree %i of %i' % (treeno, len(attachmentVertices))); treeno += 1
        i = np.random.random_integers(0,dbCount-1,1)[0]
        vascularTree = vgm.read_pkl(os.path.join(dbDirectory, dbFiles[i]))
        offset = G.vs[vertex]['r'] - \
                 vascularTree.vs[vascularTree['attachmentVertex']]['r']
        vgm.shift(vascularTree, offset)
        Gtrees.disjoint_union_attribute_preserving(vascularTree, 'omit')
        #G.union_attribute_preserving(vascularTree)
    if G.vs['apv'][vertex] == 1:
        kindAttr='pa'
    elif G.vs['vpv'][vertex] == 1:
        kindAttr='pv'
    else:
        kindAttr='n'
    stdout.flush()
    G.union_attribute_preserving(Gtrees, 'omit',kind=kindAttr)
Example #6
0
def write_statistics(database, outfile, vType, minVcount=1):
    """Traverses the vessel database, assigns modified strahler orders to each
    vascular tree and groups segments of the same order into elements. Writes 
    the statistics based on each tree's elements to an excel file.
    INPUT: database: The path to the vessel database.
           outfile: The name of the output file containing the vessel 
                    statistics.
           vType: The type of trees. This can be either 'a' (arterial) or 'v'
                  (venous).
           minVcount: The minimum number of vertices in a tree to be considered
                      in the statistics. 
    OUTPUT: None (file written to disk).                
    """
    
    lengthDB = [[] for i in xrange(25)]
    vcountDB = []
    ## Prepare excel file for writing:
    #font0 = xlwt.Font()
    #font0.name = 'Times New Roman'
    #font0.colour_index = 2
    #font0.bold = True
    #style0 = xlwt.XFStyle()
    #style0.font = font0

    #font1 = xlwt.Font()
    #font1.name = 'Times New Roman'
    #font1.colour_index = 0
    #font1.bold = True
    #style1 = xlwt.XFStyle()
    #style1.font = font1

    #wb = xlwt.Workbook()

    # Loop over trees in database and write statistics to file:
    trees = [(int(os.path.basename(t)[:-4]), t) for t in 
             glob.glob(os.path.join(database, '*.pkl'))]
    trees = [t[1] for t in sorted(trees)]
    tenPercSteps = np.round(np.linspace(1, 10, 10) * len(trees) / 10.)
    percentages = np.linspace(10, 100, 10)
    print('Writing database...')
    treeCount = 0
    for i, tree in enumerate(trees):
        print(tree)
        # Read and process tree data:
        G = vgm.read_pkl(tree)
        vcountDB.append(G.vcount())
        if (i+1) in tenPercSteps:
            print('%i percent completed' % int(percentages[np.setmember1d(tenPercSteps, [i+1])][0]))
        if G.vcount() < minVcount:
            continue
#-------------------------------------------------------------
        # Delete order 2 vertices and add length and conductance 
        # (initially None for the new, joined edges). Rename the attachment
        # vertex (vertex indexing changes while order 2 vertices are removed):
        avr = G.vs[G['attachmentVertex']]['r']
        G.delete_order_two_vertices()    
        G.es['length'] = [sum(e['lengths']) for e in G.es]
        vgm.add_conductance(G, vType)
        # Delete selfloops:
        G.delete_selfloops()
        KDT = kdtree.KDTree(G.vs['r'])
        G['attachmentVertex'] = int(KDT.query(avr)[1])
#-------------------------------------------------------------

        strahler.modified_strahler_order(G, 0.99)
        Gel = strahler.assign_elements(G)
        maxOrder = max(Gel.vs['order'])
        cl = 0 # current line

        # Write tree ID, sample ID, vcount, ecount:
        ws = wb.add_sheet('Tree' + str(treeCount))
        treeCount = treeCount + 1
        ws.write(cl, 0, 'Tree ID', style0)
        ws.write(cl, 1, int(string.strip(os.path.basename(tree), '.pkl')))
        cl = cl + 1
        ws.write(cl, 0, 'Sample ID', style0)
        ws.write(cl, 1, G['sampleName'])
        cl = cl + 1        
        ws.write(cl, 0, 'Vertices', style0)
        ws.write(cl, 1, G.vcount())
        cl = cl + 1
        ws.write(cl, 0, 'Edges', style0)
        ws.write(cl, 1, G.ecount())
        cl = cl + 1
        ws.write(cl, 0, 'Dist to border', style0)
        ws.write(cl, 1, G['distanceToBorder'])
        cl = cl + 1
        ws.write(cl, 0, 'Root offset', style0)
        ws.write(cl, 1, G['avZOffset'])        
        cl = cl + 3
        
        # Write 'order' header:
        ws.write(cl, 0, 'Order', style0)
        for order in range(maxOrder + 1):
            ws.write(cl, order+1, order, style0)
        cl = cl + 1
        
        # Write element frequency 'N':
        ws.write(cl, 0, 'N', style1)
        for order in range(maxOrder + 1):
            ws.write(cl, order+1, len(Gel.vs(order_eq=order)))
        cl = cl + 1    
        
        # Write 'segments per element':
        # Note that this is the total number of elements of an order divided by
        # the total number of segments in that order (i.e. not on an element-by-
        # element basis).
        ws.write(cl, 0, 'SpE', style1)
        for order in range(maxOrder + 1):
            numElements = len(Gel.vs(order_eq=order))
            numSegments = sum([len(v['edges']) for v in Gel.vs(order_eq=order)])
            ws.write(cl, order+1, numSegments / numElements)
        cl = cl + 1

        # Write element 'length' and 'diameter':
        for eProperty in ['length', 'diameter']:
            ws.write(cl, 0, eProperty + ' (mean) [micron]', style1)
            ws.write(cl+1, 0, eProperty + ' (std) [micron]', style1)
            for order in range(maxOrder + 1):
                data = []
                for element in Gel.vs(order_eq=order):
                    if eProperty == 'length':
                        # Length of element is sum of segment-lengths:
                        data.append(sum(G.es[element['edges']][eProperty]))
                    else:
                        # Diameter of element is mean of segment-diameters:
                        data.append(np.mean(G.es[element['edges']][eProperty]))
                ws.write(cl, order+1, np.mean(data))
                ws.write(cl+1, order+1, np.std(data))
                if eProperty == 'length':
                    lengthDB[order].append(np.mean(data))
            cl = cl + 2
            
         
        # Add some additional whitespace:
        cl = cl + 2
         
        # Compute connectivity matrix and branching angles: 
        cm =  dict(zip(range(maxOrder + 1), 
                       [dict(zip(range(maxOrder + 1), 
                                 [[] for o in range(maxOrder + 1)]))
                         for o in range(maxOrder + 1)]))
        ba =  dict(zip(range(maxOrder + 1), 
                       [dict(zip(range(maxOrder + 1), 
                                 [[] for o in range(maxOrder + 1)]))
                         for o in range(maxOrder + 1)]))                         
        # Loop over the elements of G, which are the vertices of Gel:                                         
        for elm in Gel.vs:
            order = elm['order']
            orderCounter = dict(zip(range(maxOrder + 1), 
                                    [0 for o in range(maxOrder + 1)]))
            branchingAngle = dict(zip(range(maxOrder + 1), 
                                      [[] for o in range(maxOrder + 1)]))
                                      
            # Loop over neighboring elements:                        
            for nElm in Gel.vs(Gel.neighbors(elm.index)):
                # Find vertex common to both elements. 
                # Note that two elements can theoretically touch at more than 
                # one location, here only the first common vertex is considered.
                vertex = int(np.array(elm['vertices'])[np.setmember1d(elm['vertices'], nElm['vertices'])][0])
                # Find the edge that is part of the current element, adjacent,
                # and upstream to vertex. This ensures a 'natural', flow-based
                # choice of nElm-elm edge angle if the nElm edge connects to 
                # than one elm-edges.
                # Note that edges at equal mean pressures are not considered!
                edges = np.array(elm['edges'])[np.setmember1d(elm['edges'], G.adjacent(vertex))]
                pMax = G.vs[vertex]['pressure']
                edge = None
                for e in edges:
                    e = int(e) # Convert from numpy integer
                    meanP = np.mean(G.vs[G.es[e].tuple]['pressure'])
                    if meanP > pMax:
                        edge = e
                        pMax = meanP
                # Skip this element-junction if the current element does not 
                # contain upstream edges:        
                if edge is None:
                    continue       
                # Find the edge that is part of the neighboring element, 
                # adjacent, and downstream to vertex. This ensures a 'natural', 
                # flow-based choice of nElm-elm edge angle if the elm edge 
                # connects to more than one nElm-edges.
                # Note that edges at equal mean pressures are not considered!
                edges = np.array(nElm['edges'])[np.setmember1d(nElm['edges'], G.adjacent(vertex))]                                
                pMin = G.vs[vertex]['pressure']
                nEdge = None
                for e in edges:
                    e = int(e) # Convert from numpy integer
                    meanP = np.mean(G.vs[G.es[e].tuple]['pressure'])
                    if meanP < pMin:
                        nEdge = e
                        pMin = meanP
                # Skip this element-junction if the neighboring element does not 
                # contain downstream edges:        
                if nEdge is None:
                    continue                         

                # Increase the count of the connectivity matrix and compute the
                # branching angle:
                orderCounter[nElm['order']] += 1
                # A spherical region around the vertex is defined as the 
                # branching region. The radius of the sphere is equal to the 
                # maximum of the radii of the adjacent edges at the location of
                # the vertex.
                # The angle of an elements edge is then computed from the point
                # where the edge penetrates the sphere up to a distance of 
                # about twice the vessel diameter away from the point of 
                # penetration (unless of corse, the edge is shorter).
                # Radius of branching sphere:
                maxDiameter = 0
                for e in G.adjacent(vertex):
                    if G.es[e].source != vertex:
                        d = G.es[e]['diameters'][-1]
                    else:
                        d = G.es[e]['diameters'][0]
                    if d > maxDiameter:
                        maxDiameter = d
                radius = maxDiameter / 2.0
                # Vectors of the two branching edges:
                vectors = []
                for e in (edge, nEdge):
                    if G.es[e].source != vertex:
                        points = G.es[e]['points'][::-1]
                    else:
                        points = G.es[e]['points']
                    
                    startPoint = round(len(points) * 
                                       radius / G.es[e]['length'])
                    if startPoint > len(points)-1 or startPoint < 1:
                        startPoint = 1

                    # In order to determine the direction of a vessel leaving a
                    # bifurcation, we consider the points it comprises starting
                    # just outside the bifurcation (i.e. at maximum radius of  
                    # all vessels incident to the bifurcation) and ending two
                    # diameter lengths away from the bifurcation (angles 
                    # deviate least from the mean of angles determined from 1,
                    # 2, 3, 4 diameter lengths).
                    endPoint = min(len(points),
                                   round(len(points) * 
                                         (radius + 2.0 * G.es[e]['diameter']) /
                                         G.es[e]['length']))
                    endPoint = max(endPoint, startPoint+1)                     
                    points = points[startPoint-1:endPoint]
                    
                    vectors.append(vgm.average_path_direction(points))                           
                
                # The magnidudes of the vectors are one, hence the angle can
                # be computed without dividing by them. Note that an angle of 0
                # degrees means that both parent and child vessel are going in 
                # the same direction, whereas 180 degrees signifies opposite 
                # directions: 
                angle = np.pi - np.arccos(np.dot(vectors[0], vectors[1]))
                branchingAngle[nElm['order']].append(angle)          
     
            # Update the connectivity matrix and branching angle matrix with the
            # results of the current element:
            for nOrder in orderCounter.keys():
                cm[order][nOrder].append(orderCounter[nOrder])    
                ba[order][nOrder].extend(branchingAngle[nOrder])

        # Write connectivity matrix:        
        ws.write(cl, 0, 'Connectivity matrix', style1)
        cl = cl + 1
        ws.write(cl, 0, 'Order', style0)
        neo = [] # Number of elements of order o
        for j, order in enumerate(range(maxOrder + 1)):
            ws.write(cl, order+1, order, style0)
            ws.write(cl+j+1, 0, order, style0)
            neo.append(len(Gel.vs(order_eq=order)))
        cl = cl + 1                  
        for order in range(maxOrder + 1):
            for nOrder in range(order, maxOrder + 1):
            # Use the following line instead of the previous, if order zero
            # elements never connect to other order zero elements:
            # for nOrder in range(max(1, order), maxOrder + 1):
                if cm[order][nOrder] != []:
                    ws.write(order+cl, nOrder+1, sum(cm[order][nOrder]) / neo[nOrder])         
        # Equal spacing for all worksheets, irrespective of maximum order:
        cl = cl + 20
        #cl = cl + maxOrder + 3
        
        # Write branching angles:
        ws.write(cl, 0, 'Branching angles [deg]', style1)
        cl = cl + 1
        ws.write(cl, 0, 'Order', style0)
        neo = [] # Number of elements of order o
        for j, order in enumerate(range(maxOrder + 1)):
            ws.write(cl, order+1, order, style0)
            ws.write(cl+j+1, 0, order, style0)
            neo.append(len(Gel.vs(order_eq=order)))
        cl = cl + 1                  
        for order in range(maxOrder + 1):
            for nOrder in range(order, maxOrder + 1):
            # Use the following line instead of the previous, if order zero
            # elements never connect to other order zero elements:
            # for nOrder in range(max(1, order), maxOrder + 1):
                if ba[order][nOrder] != []:
                    ws.write(order+cl, nOrder+1, np.rad2deg(np.mean(ba[order][nOrder])))
        # Equal spacing for all worksheets, irrespective of maximum order:
        cl = cl + 20
        #cl = cl + maxOrder + 3
        
        # Compute irrigation / drainage volume:
        G.vs['z'] = [r[2] for r in G.vs['r']]
        zMin = np.min(G.vs['z'])
        zMax = np.max(G.vs['z'])
        cylinderLength = 200
        intervals = vgm.intervals(zMin, zMax, (zMax - zMin) / cylinderLength)
        pl = np.concatenate(G.es['points'], axis=0)
        z = pl[:,2]        
        
        if intervals == []:
            intervals = [[zMin, zMax]]
        volume = 0.0    
        for i, interval in enumerate(intervals):           
            points = pl[np.nonzero(map(all, zip(z>interval[0],
                                                z<interval[1])))[0], :] # use points
            points = np.array(zip(points[:,0], points[:,1]))
            #points = np.array(G.vs(z_ge=interval[0], z_le=interval[1])['r']) # use vertices
            
            if len(points) < 3:
                continue
            # Add slab volume: 
            com = np.mean(points, axis=0)
            hullpts = convex_hull.qhull(points)
            radius = np.mean([np.linalg.norm(com - hp) for hp in hullpts])
            volume += np.pi * radius**2 * cylinderLength           
                 
        ws.write(cl, 0, 'Irrigation / drainage volume [microL]', style1)
        cl = cl + 1
        ws.write(cl, 0, volume / 1e9) # Conversion micron**3 --> microL
        cl = cl + 3
        
    wb.save(outfile)
    
    #wb2 = xlwt.Workbook()
    #ws2 = wb2.add_sheet('Element Length')
    cl = 0
    maxOrder = 0
    maxN = []
    for order, ldb in enumerate(lengthDB):
        if len(ldb) > 0:
            maxOrder = order
        maxN.append(len(ldb))    
    for order in xrange(maxOrder + 1):
        ws2.write(0, order, order, style0)
        for i, l in enumerate(lengthDB[order]): 
            ws2.write(i+1, order, l, style1)
    wb2.save('elmLength_' + vType + '.xls')
Example #7
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) 
Example #8
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)