Can I export a skeleton as a csv file?

Can I export a skeleton as a csv file?

menghui6WUWM
Contributor Contributor
910 Views
5 Replies
Message 1 of 6

Can I export a skeleton as a csv file?

menghui6WUWM
Contributor
Contributor

Inside Maya, I have an animated skeleton, which contains motion data.

Can I export this skeleton as a csv file, so that once I open this csv file inside Excel, it shows me the numerical data with columns of skeleton names ?  

 

I am in a project, the deadline is almost there, plz help me !!  Orz~ 

0 Likes
Accepted solutions (2)
911 Views
5 Replies
Replies (5)
Message 2 of 6

Kahylan
Advisor
Advisor

Hi!

 

What you want to do is possible in python using the csv library.

This code can certainly be optimized, but it does what you want:

import maya.cmds as mc
import csv


def exportToCSV(start = None, end= None,path = None, multiFile = False):
    if path == None:
        path = mc.file(q= True, sn = True)
        path = path[:-3]
    if start== None:
        start = mc.playbackOptions(q= True, min= True)
    if end== None:
        end = mc.playbackOptions(q= True, max= True)
        
    sel = mc.ls(sl= True, l= True)
    dict = getAttributes(objs = sel)

    if dict != {} and multiFile == False:
        getValuesForExportSF(dict= dict, start = start, end= end, path = path)
    elif dict != {} and multiFile == True:
        getValuesForExportMF(dict= dict, start = start, end= end, path= path)
    else:
        mc.error("No animated attributes found")
        

def getValuesForExportSF(dict= None, start = None,end= None, path = None):
    fieldNames= []
    rows= []

    for k in dict:
        for v in dict[k]:
            fieldNames.append("{0}.{1}".format(k,v))
            
    for f in range(int(start),int(end)):
        temp = []
        for n in fieldNames:
            temp.append(mc.getAttr(n, t= f))
        rows.append(temp)    
        
    writeCSV(path = path,fieldNames = fieldNames,rows = rows)   


def getValuesForExportMF(dict= None, start = None,end= None, path = None):
    for k in dict:
        fieldNames= []
        rows= []
        
        
        for v in dict[k]:
            fieldNames.append(v)
                
        for f in range(int(start),int(end)):
            temp = []
            for n in fieldNames:
                temp.append(mc.getAttr("{0}.{1}".format(k,n), t= f))
            rows.append(temp)
        kS = k.split("|")
        kS = kS[1:]
        k= kS.pop(0)
        k= "_"+k
        
        for e in kS:
            k= k +"_"+ e
        pathN= path + k    
        writeCSV(path = pathN,fieldNames = fieldNames,rows = rows)  
    
            
def getAttributes(objs = None):
    attrDict = {}
    relatvies = []
    for o in objs:
        rel = mc.listRelatives(o, ad = True, f= True) or []
        rel.append(o)
        relatvies = relatvies + rel
    
    for r in relatvies:
        tempList = []
        attrList = mc.listAttr(r, s=True) or []
        for attr in attrList:
            try:
                kf = mc.keyframe("{0}.{1}".format(r, attr), n= True, q= True)
                if kf != None:
                    tempList.append(attr)
            except:
                pass 
        if tempList != []:
            attrDict[r] = tempList
            
    return attrDict     
   
def writeCSV(path = None,fieldNames = None,rows = None):
    
    path= path + ".csv"     
    with open(path,'w') as f:
        writer = csv.writer(f)
        writer.writerow(fieldNames)
        writer.writerows(rows)

exportToCSV(start = None, end= None,path = None, multiFile = False)

Just select the top level node of your skeleton and run this script from a python tab, it will store the csv file in the same folder as your scene file.

 

Now a problem here, is that you have way too much data in one file. you have the nodes that have animation, for each node you have multiple attributes and all of them have a row of values for each frame in your set timerange from start to end. for a full skeleton, this is barely humanly readable. So I built in the possibility to have a file for each node.

import maya.cmds as mc
import csv


def exportToCSV(start = None, end= None,path = None, multiFile = False):
    if path == None:
        path = mc.file(q= True, sn = True)
        path = path[:-3]
    if start== None:
        start = mc.playbackOptions(q= True, min= True)
    if end== None:
        end = mc.playbackOptions(q= True, max= True)
        
    sel = mc.ls(sl= True, l= True)
    dict = getAttributes(objs = sel)

    if dict != {} and multiFile == False:
        getValuesForExportSF(dict= dict, start = start, end= end, path = path)
    elif dict != {} and multiFile == True:
        getValuesForExportMF(dict= dict, start = start, end= end, path= path)
    else:
        mc.error("No animated attributes found")
        

def getValuesForExportSF(dict= None, start = None,end= None, path = None):
    fieldNames= []
    rows= []

    for k in dict:
        for v in dict[k]:
            fieldNames.append("{0}.{1}".format(k,v))
            
    for f in range(int(start),int(end)):
        temp = []
        for n in fieldNames:
            temp.append(mc.getAttr(n, t= f))
        rows.append(temp)    
        
    writeCSV(path = path,fieldNames = fieldNames,rows = rows)   


def getValuesForExportMF(dict= None, start = None,end= None, path = None):
    for k in dict:
        fieldNames= []
        rows= []
        
        
        for v in dict[k]:
            fieldNames.append(v)
                
        for f in range(int(start),int(end)):
            temp = []
            for n in fieldNames:
                temp.append(mc.getAttr("{0}.{1}".format(k,n), t= f))
            rows.append(temp)
        kS = k.split("|")
        kS = kS[1:]
        k= kS.pop(0)
        k= "_"+k
        
        for e in kS:
            k= k +"_"+ e
        pathN= path + k    
        writeCSV(path = pathN,fieldNames = fieldNames,rows = rows)  
    
            
def getAttributes(objs = None):
    attrDict = {}
    relatvies = []
    for o in objs:
        rel = mc.listRelatives(o, ad = True, f= True) or []
        rel.append(o)
        relatvies = relatvies + rel
    
    for r in relatvies:
        tempList = []
        attrList = mc.listAttr(r, s=True) or []
        for attr in attrList:
            try:
                kf = mc.keyframe("{0}.{1}".format(r, attr), n= True, q= True)
                if kf != None:
                    tempList.append(attr)
            except:
                pass 
        if tempList != []:
            attrDict[r] = tempList
            
    return attrDict     
   
def writeCSV(path = None,fieldNames = None,rows = None):
    
    path= path + ".csv"     
    with open(path,'w') as f:
        writer = csv.writer(f)
        writer.writerow(fieldNames)
        writer.writerows(rows)

exportToCSV(start = None, end= None,path = None, multiFile = True)

 

You'll get a file per node which you can then set up as separate sheets in your excel file which is much more organsied.

 

I should mention that this code has one restriction, it ignores multi attributes with the formatting node.attr[0].subAttr.

This is because of compadibility issues between the results of listAttr() and the accepted spacial arguments for keyframes().

This could certainly be fixed with more time, but since these kinds of attributes are hardly ever keyed, I decided to ignore the for now.

 

I hope it helps!

 

Message 3 of 6

menghui6WUWM
Contributor
Contributor

Thanks man for your detailed explains, I will try them out once I back to studio.

Will let you know my updates, 

 

Cheers

0 Likes
Message 4 of 6

menghui6WUWM
Contributor
Contributor

Hey, I tried both codes, but both did not work. 

Once I put the second one into the python tab, two errors poped up.

Plz see video for reference.

0 Likes
Message 5 of 6

Kahylan
Advisor
Advisor
Accepted solution

Hmm. Thats weird, the code worked perfectly fine for me. Sadly I couldn't really read the error message in your video, would you mind posting the error message as text here?

 

Also could you maybe attach the scene you used to test it so I can try to reproduce the issue?

 

But the script seemed to run through fine on the first version of the script, did you check if there was a csv file on your drive where the scene is saved?

 

Also I realised that there were some issues in the script with the pathing I used. for a full skeleton the filename would tend to get too long. Also I didn't eliminate the namespaces before, which can lead to issues with file naming depending on the OS you are using. I tried to fix it. Let me know if this works:

import maya.cmds as mc
import csv


def exportToCSV(start = None, end= None,path = None, multiFile = False):
    if path == None:
        path = mc.file(q= True, sn = True)
        path = path[:-3]
    if start== None:
        start = mc.playbackOptions(q= True, min= True)
    if end== None:
        end = mc.playbackOptions(q= True, max= True)
        
    sel = mc.ls(sl= True, l= True)
    dict = getAttributes(objs = sel)

    if dict != {} and multiFile == False:
        getValuesForExportSF(dict= dict, start = start, end= end, path = path)
    elif dict != {} and multiFile == True:
        getValuesForExportMF(dict= dict, start = start, end= end, path= path)
    else:
        mc.error("No animated attributes found")
        

def getValuesForExportSF(dict= None, start = None,end= None, path = None):
    fieldNames= []
    rows= []

    for k in dict:
        for v in dict[k]:
            fieldNames.append("{0}.{1}".format(k,v))
            
    for f in range(int(start),int(end)):
        temp = []
        for n in fieldNames:
            temp.append(mc.getAttr(n, t= f))
        rows.append(temp)    
        
    writeCSV(path = path,fieldNames = fieldNames,rows = rows)   


def getValuesForExportMF(dict= None, start = None,end= None, path = None):
    for k in dict:
        fieldNames= []
        rows= []
        
        
        for v in dict[k]:
            fieldNames.append(v)
                
        for f in range(int(start),int(end)):
            temp = []
            for n in fieldNames:
                temp.append(mc.getAttr("{0}.{1}".format(k,n), t= f))
            rows.append(temp)
        kS = k.split("|")
        if len(kS) >1:
            kS = kS[1:]
            
        if kS != []:
            k= kS.pop(0)
            k= k= k.split(":")[-1]
            k= "_"+k
        
        
        for e in kS:
            e = e.split(":")[-1]
            k= k +"_"+ e
        pathN= path + k    
        writeCSV(path = pathN,fieldNames = fieldNames,rows = rows)  
    
            
def getAttributes(objs = None):
    attrDict = {}
    relatvies = []
    for o in objs:
        rel = mc.listRelatives(o, ad = True, pa= True) or []
        rel.append(o)
        relatvies = relatvies + rel
    
    for r in relatvies:
        tempList = []
        attrList = mc.listAttr(r, s=True) or []
        for attr in attrList:
            try:
                kf = mc.keyframe("{0}.{1}".format(r, attr), n= True, q= True)
                if kf != None:
                    tempList.append(attr)
            except:
                pass 
        if tempList != []:
            attrDict[r] = tempList
            
    return attrDict     
   
def writeCSV(path = None,fieldNames = None,rows = None):
    
    path= path + ".csv"     
    with open(path,'w') as f:
        writer = csv.writer(f)
        writer.writerow(fieldNames)
        writer.writerows(rows)

exportToCSV(start = None, end= None,path = None, multiFile = True)

 

 

Message 6 of 6

menghui6WUWM
Contributor
Contributor
Accepted solution

Hi luckily, it worked out! I saw many csv files exported into my project folder. But I am not sure if my professor allow us to use seperate csv or combine it into one csv file. But Really appreciated your help. Thank you very much~ 

0 Likes