Names = trunkDat['name'].unique()
    mainTrunks = {}
    for name in mainTNames:
        mainTrunks['{0}'.format(name)] = trunkDat.query('name == "{0}"'.format(name))
        mainTrunks['{0}'.format(name)] = mainTrunks['{0}'.format(name)].sort_values('height')
    return(mainTrunks)

def refSegType(refs, segNames, heights, segTypes, refType):
    """Inputs are a list vector of references, a vector of names, heights, and a vector of types"""
    """returns indices of reference segments of refType"""
    
    #strip white space from series
    for i in range(len(segNames)):
        refs.iat[i] = refs.iat[i].replace(' ','')    #This doesn't seem to give the warning. 
        segNames.iat[i] = segNames.iat[i].replace(' ','')
        
        #refs.set_value(i, refs.iloc[i].replace(' ',''))  #These give depreciation of set_value warning
        #segNames.set_value(i, segNames.iloc[i].replace(' ',''))
        
       # refs.loc[i] = refs.iloc[i].replace(' ','')    #These give a set value to slice warning
       # segNames.loc[i] = segNames.iloc[i].replace(' ','')

    segTypes = segTypes.str.lower()
    
    #If ref is to a segment and the matching segment names corresponds to a type "t" 
    refTest = refs.str.contains('-')
    heightTest = heights.map(np.isreal)  
    refs2Segs = refs[[a and b for a, b in zip(refTest, heightTest)]]  #The ref is to a segment and there is a height recoded for the element in question               
    calcVec = pd.Series([False]*len(refs2Segs), index = refs2Segs.index)
    
    #segments that are also trunks
    segNames = segNames[segTypes == refType]
    
    for i in range(len(refs2Segs)):
        ref2test = refs2Segs.iloc[i]
        if any(ref2test == segNames):
            calcVec.iloc[i] = True

    return(calcVec[calcVec == True].index)

#Calculate values based on reference position and measurements
def calcPosition(refVals, calcVals, calcType, error = False, refName = None): #pass a vector of reference locations and position measures 
#This will calculate the x,y,z postition of any location given either cylindrical or polar coordinates. It also takes in calcType,
# the type of calculation needed, options are 'trunk','segment', or 'branch'

#For segments and trunks refVals is a vector = [refX,refY, refRadius], for branches it = [refX,refY, refRadius, refZ] 
#For segments and trunks calcVals is a vectory = [dist, azimuth, target radius, refType], for branches it is [dist, azimuth, slope]     

#refType is how the reference was taken, (reference 2 tartet), either p2p, p2f, f2p, or f2f. p = pith, f = face

#All units in meters!!

    RefX = refVals[0]
    RefY = refVals[1]
    RefRadius = refVals [2] 

    dist = calcVals[0]
    azi = calcVals[1] 
    
    #Change the distance according to the reference style (p2p, etc....)                                                                     
    if calcType == 'trunk' or calcType =='segment':
        targetRadius = calcVals[2]
        refType = calcVals[3]
        if refType == 'p2p':
            dist = dist
        elif refType == 'p2f':
            dist = dist + targetRadius
        elif refType == 'f2p':
            dist = dist + RefRadius
        elif refType == 'f2f':
            dist = dist + RefRadius + targetRadius
        else:
            dist = dist + RefRadius  #if nothing is given use face to pith
            error = True
            
        x = RefX + dist * np.sin(np.pi/180 * azi)
        y = RefY + dist * np.cos(np.pi/180 * azi)
        calcs = {'x':x,'y':y, 'error':error}                                    

    elif calcType == 'branchBase': #For branches
        RefZ = refVals[3]
        dist = RefRadius  # I input a distance of zero for all branch bases, so this will have to be just the reference radius
        
        x = RefX + dist * np.sin(np.pi/180 * azi)
        y = RefY + dist * np.cos(np.pi/180 * azi)
        z = RefZ
        calcs = {'x':x,'y':y,'z':z, 'error':error}
        
    elif calcType == 'branchTop': #For branches
        RefZ = refVals[3]
        #slope = calcVals[2]
        
        x = RefX + dist * np.sin(np.pi/180 * azi)
        y = RefY + dist * np.cos(np.pi/180 * azi)
        #z = RefZ + dist * np.tan(np.pi/180 * slope)

        calcs = {'x':x,'y':y,'error': error}    
    return (calcs)   

def calcCustRefs(custRefs):
    if len(custRefs) > 0:
        for i in range(len(custRefs['name'])):
            if custRefs['ref'][i] == 'G':
                refx = 0
                refy = 0
            else:
                refx = custRefs['ref x'][i]
                refy = custRefs['ref y'][i]
            refR = custRefs['ref diam'][i]/200.0 #convert to m from cm
            if refR > 3:  #units are likely in cm and need conversion to m
                refR = refR/100

            refType = custRefs['ref type'][i]
            azi = custRefs['azi'][i]
            dist = custRefs['dist'][i]
            radius = custRefs['diam'][i]/200.0
            if radius > 3:  #units are likely in cm and need conversion to m
               radius = radius/100
            refVals = [refx, refy, refR]
            calcVals = [dist, azi, radius, refType]
        
            calcs = calcPosition(refVals, calcVals, calcType = 'trunk', error = False)
            custRefs.loc[i,'x'] = calcs['x']
            custRefs.loc[i,'y'] = calcs['y']
            custRefs.loc[i,'radius'] = radius
    return(custRefs)

def midSegTopLocator(nodeRow, logFileName, error):
    """Brings in a series of segment rows with base and mid seg positions on the same segment for when there are supplemental measurements"""
    """Outputs the most distal row of the series of segments with the same name (many supplementals), a list of the indices in Proximal to distal order, and an errorcode"""
    prox2distIndices = []
    for i in range(len(nodeRow)):
        if i == 0:
            currentRow = nodeRow[nodeRow['position']=='base']
            if len(currentRow)==0:
                print('One of the segment {0} positions is not labelled "base"'.format(nodeRow['name'].iloc[0]))
                print2Log(logFileName,'One of the segment {0} positions is not labelled "base"'.format(nodeRow['name'].iloc[0]))
                error = True
            findHt = float(currentRow['top ht'])
            findDist = float(currentRow['top dist'])
            prox2distIndices.append(currentRow.index[0])
        else:
            sameHtAndDist = vectorBool(nodeRow['base ht']==findHt, nodeRow['base dist']==findDist,'and')
            currentRow = nodeRow[