Continue to Site

Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations KootK on being selected by the Eng-Tips community for having the most helpful posts in the forums last week. Way to Go!

Python Scripting - Automatic XY report generation 1

Status
Not open for further replies.

MegaStructures

Structural
Sep 26, 2019
366
Hello,

For my research I have to create the same XY plot with different data a painful number of times. I am trying to use an Abaqus macro to make my life easier, which seems to work great until I try to use it on a file that I did not create the macro in. I see when opening the .rpy file in a text editor that the macro is defining the name of the .odb file as the name of the file that was open when I made the program. How can I make this file name be the name of whichever .odb file I currently have open?

Also Abaqus seems to add in the part name when calculating U2 and RF2, which will again cause me some more headache (part name doesn't stay consistent across .cae/.odb files. Any way to change that behavior?



def XY_Plots():
import section
import regionToolset
import displayGroupMdbToolset as dgm
import part
import material
import assembly
import step
import interaction
import load
import mesh
import optimization
import job
import sketch
import visualization
import xyPlot
import displayGroupOdbToolset as dgo
import connectorBehavior
session.linkedViewportCommands.setValues(_highlightLinkedViewports=False)
odb = session.odbs['Model1.odb']
session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
nodeSets=('Loading Node', ))
xy1 = session.xyDataObjects['U:U2 PI: Packer End Connection 1-2 N: 12']
xy2 = session.xyDataObjects['RF:RF2 PI: Packer End Connection 1-2 N: 12']
xy3 = combine(-xy1, -2*xy2)
xy3.setValues(
sourceDescription='combine ( -"U:U2 PI: Packer End Connection 1-2 N: 12",-2*"RF:RF2 PI: Packer End Connection 1-2 N: 12" )')
tmpName = xy3.name
session.xyDataObjects.changeKey(tmpName, 'XYData-1')
x0 = session.xyDataObjects['XYData-1']
session.writeXYReport(fileName='abaqus.rpt', xyData=(x0, ))

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Replies continue below

Recommended for you

Thanks FEA. I'm not sure I follow the code in that post, but let me try

#Define open .obd as current
session.linkedViewportCommands.setValues[session.currentViewportName]
odb = currentViewport.displayedObject
odbFileNameFull = odbFile.path
odbFileName = os.path.split(odbFileNameFull)[1]
odbPath = os.path.split(odbFileNameFull)[0]

#create XY plot
session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
nodeSets=('Loading Node', ))
xy1 = session.xyDataObjects['U:U2 PI: Packer End Connection 1-2 N: 12']
xy2 = session.xyDataObjects['RF:RF2 PI: Packer End Connection 1-2 N: 12']
xy3 = combine(-xy1, -2*xy2)
xy3.setValues(
sourceDescription='combine ( -"U:U2 PI: Packer End Connection 1-2 N: 12",-2*"RF:RF2 PI: Packer End Connection 1-2 N: 12" )')
tmpName = xy3.name
session.xyDataObjects.changeKey(tmpName, 'XYData-1')
x0 = session.xyDataObjects['XYData-1']

#Export Report
session.writeXYReport(fileName='abaqus.rpt', xyData=(x0, ))

[ul]
[li]I would have guessed there would have been a simpler command for opening the current .odb file maybe something like odb = CurrentOdb[/li]
[li]is odbFileNameFull = odbFile.path a placeholder? Or is this the correct line of code[/li]
[li]I'm not sure why I have to split the path and file name?[/li]
[li]Ay idea how I remove the part name from the U and RF2 variables when I create them? Every part I check has a different part name[/li]
[/ul]

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
When you already have opened the odb manually and just want to automate the rest, then you only need this to identify the opened odb:

vps = session.viewports[session.currentViewportName]
odbName = vps.displayedObject.name
odb = session.odbs[odbName]
 
Like, so?

#Define open .obd as current
[highlight #FCE94F]vps = session.viewports[session.currentViewportName]
odbName = vps.displayedObject.name
odb = session.odbs[odbName]
[/highlight]

#create XY plot
session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
nodeSets=('Loading Node', ))
xy1 = session.xyDataObjects['U:U2 PI: Packer End Connection 1-2 N: 12']
xy2 = session.xyDataObjects['RF:RF2 PI: Packer End Connection 1-2 N: 12']
xy3 = combine(-xy1, -2*xy2)
xy3.setValues(
sourceDescription='combine ( -"U:U2 PI: Packer End Connection 1-2 N: 12",-2*"RF:RF2 PI: Packer End Connection 1-2 N: 12" )')
tmpName = xy3.name
session.xyDataObjects.changeKey(tmpName, 'XYData-1')
x0 = session.xyDataObjects['XYData-1']

#Export Report
session.writeXYReport(fileName='abaqus.rpt', xyData=(x0, ))

Are you able to help me remove the part name from the U and RF variables?

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Yes, but you have to explain more details.

You've mentioned that you want to do this process with multiple odbs. Is Abaqus/CAE closed between those operations or does it stay open and you just open&close the odbs?
Is it always that you open the odb manually and then run the script?


So for example your manual work is this?
- start Abaqus/CAE
- open odb
- run script
- close odb
- open odb
- run script
- close odb
:
- close Abaqus/CAE
 
Think I'm getting closer, but still no luck, the macro only works for the model I created it in

def Rename():
import section
import regionToolset
import displayGroupMdbToolset as dgm
import part
import material
import assembly
import step
import interaction
import load
import mesh
import optimization
import job
import sketch
import visualization
import xyPlot
import displayGroupOdbToolset as dgo
import connectorBehavior
#Commented out naming lines
#session.linkedViewportCommands.setValues(_highlightLinkedViewports=False)
#odb = session.odbs['C:/Temp/CornerMaterial_TET.odb']

#Name current file
[highlight #FCE94F]vps = session.viewports[session.currentViewportName]
odbName = vps.displayedObject.name
odb = session.odbs[odbName][/highlight]
#XY data from field variables
session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
nodeSets=('Loading Node', ))
#Rename field variables
[highlight #FCE94F]session.xyDataObjects.changeKey(fromName='RF:RF2 PI: PART-1-1 N: 142',
toName='RF:RF2')
session.xyDataObjects.changeKey(fromName='U:U2 PI: PART-1-1 N: 142',
toName='U:U2')
xy1 = session.xyDataObjects['U:U2']
xy2 = session.xyDataObjects['RF:RF2']
xy3 = combine(-xy1, -2*xy2)[/highlight]
#Create XY plot
xy3.setValues(sourceDescription='combine ( -"U:U2",-2*"RF:RF2" )')
tmpName = xy3.name
session.xyDataObjects.changeKey(tmpName, 'XYData-1')
x0 = session.xyDataObjects['XYData-1']
#Write report
session.writeXYReport(fileName='abaqus.rpt', xyData=(x0, ))

I see that renaming the field variables doesn't help, because the code still contains: (fromName='RF:RF2 PI: [highlight #EF2929]PART-1-1[/highlight]

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Mustaine:

I posted before I saw your response.

Mustaine said:
Is Abaqus/CAE closed between those operations or does it stay open and you just open&close the odbs?

Abaqus stays open and I open a new odbs

Mustaine said:
Is it always that you open the odb manually and then run the script?

Yes, I'm manually opening the odb and running the script. I just want to have a one click operation to create XY data, create a combined XY graph, and then export a report to CSV to incorporate in a LatEx document

Mustaine said:
So for example your manual work is this?
- start Abaqus/CAE
- open odb
- run script
- close odb
- open odb
- run script
- close odb
:
- close Abaqus/CAE

Exactly, you got it!

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Ok, your node set is one node and you extract RF2 and U2 from the field output of that node. When this process happens, these two xy data will become part of the session data of that A/CAE session. That means it is not part of the odb, but the CAE session. You could close the odb and still work with the curves. But they are gone when you close A/CAE. It also means, that you will get additional data every time you do that with a new odb in the active session.


To be independent of the partname you can do this: You extract the two curves and then query the current session data.
The xy session data are Python dictionaries. Generate a list with the keys and then use them to access the data, identify and rename them.

Code:
session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF', 
    NODAL, ((COMPONENT, 'RF1'), )), ('U', NODAL, ((COMPONENT, 'U1'), )), ), 
    nodeSets=("whatever", ))

datalist = session.xyDataObjects.keys()

for x in datalist:
	if x.find('RF1')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='RF1')
	elif x.find('U1')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='U1')

Now you can always use those two known names further on.

The important thing is to delete all session xy data at the end of the script. Otherwise we will have 4 extracted curves (plus the old combined) in the second run and we would have trouble identifying and renaming the new data.

So add something like this at the end:
Code:
del session.xyDataObjects['RF1']
del session.xyDataObjects['U1']
del session.xyDataObjects['XYData-1']


Bonus Tipp:
When the odb-names are different, use those names in the report name, so you can easily see where the files are coming from.
You already have the odbName object, which contains the full path. Use print to check those things interactive when developing a script.
So
print odbName
will show something like this
D:/folder1/folder2/xname.odb
Use split to get rid of the unneeded stuff in that string.
>temp = odbName.split('/')[-1]
temp = xname.odb
>my_name = temp.split('.')[0]

Now you can use that when requesting the report:
>session.writeXYReport(fileName=my_name+'.rpt', xyData=(x0, ))
 
Mustaine3 thank you so much for your help. I'm sure you can see that I know very little about Python. I was hoping to mostly be able to use the macro recorder inside Abaqus. This code is very close! I've run it in multiple odb files. It creates XYData U1 and RF1, but fails when trying to combine the data into an XY plot

XY-Plot_Macro_hlzm7w.png


Code:
#Name current file

    vps = session.viewports[session.currentViewportName]
    odbName = vps.displayedObject.name
    odb = session.odbs[odbName]

    #XY data from field variables
    #session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF', 
        #NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ), 
        #nodeSets=('Loading Node', ))
    
#Rename field variables

    session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF', 
    NODAL, ((COMPONENT, 'RF1'), )), ('U', NODAL, ((COMPONENT, 'U1'), )), ), 
    nodeSets=("Loading Node", ))

    datalist = session.xyDataObjects.keys()

    for x in datalist:
        if x.find('RF1')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='RF1')
        elif x.find('U1')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='U1')
    
    #Create XY plot

    xy3 = combine(-U1, -2*RF1)
    xy3.setValues(sourceDescription='combine(-RF1, -2*U1)')
    tmpName = xy3.name
    session.xyDataObjects.changeKey(tmpName, 'XYData-1')
    x0 = session.xyDataObjects['XYData-1']
    
    #Write report
    
    print odbName

    temp = odbName.split('/')[-1]
    temp = xname.odb
    my_name = temp.split('.')[0]
  
    session.writeXYReport(fileName=my_name+'.rpt', xyData=(x0, ))
    
    del session.xyDataObjects['RF1']
    del session.xyDataObjects['U1']
    del session.xyDataObjects['XYData-1']

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Would it be easier if I called the odb file from the command line? Could I somehow set up the script to ask for a file name when I run it and then I wouldn't have the need for the "for x in datalist" section of the code

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
My examples were not intended to be the complete script. The intention was to show you how to do certain things and you apply that knowledge.
In your latest example you destroyed the code where you use the two curves and combine them to a new one.

Also the line "temp = xname.odb" should be removed. In my post this was supposed to be seen as output of a command.
 
Thanks Mustaine. Yea, I have no experience with Python. My theory was that since we named xy data objects they could then be combined the same way the .rpy file was combining the data before, but with new names.

I don’t suppose it would be easy to show how to combine U2 and RF2 would it? It seems like that’s the final missing piece

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Ok, I've figured out how to combine the plots! The very very last thing I haven't figured out is the report naming!

The error is "Global name 'x0' is not defined.

One major problem I'm having here is that I don't know how to show the output of print odbName, since I am editing the macro in idle (Python GUI) or Notepad++. The only way I know how to get interactive results is in the Python command line

edit: I figured out how to use the print odbName command using the Abaqus GUI command line!! Now the ONLY issue I have left is with the report file name!! :)

Python:
def Eng_Tips():
    import section
    import regionToolset
    import displayGroupMdbToolset as dgm
    import part
    import material
    import assembly
    import step
    import interaction
    import load
    import mesh
    import optimization
    import job
    import sketch
    import visualization
    import xyPlot
    import displayGroupOdbToolset as dgo
    import connectorBehavior

    #Name current file
    
    vps = session.viewports[session.currentViewportName]
    odbName = vps.displayedObject.name
    odb = session.odbs[odbName]
    
    #Rename field variables
    
    session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF', 
    NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ), 
    nodeSets=('Loading Node', ))

    datalist = session.xyDataObjects.keys()

    for x in datalist:
        if x.find('RF2')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='RF2')
        elif x.find('U2')>-1:
		session.xyDataObjects.changeKey(fromName=x, toName='U2')
    
    #Create XY plot
   
    xy1 = session.xyDataObjects['U2']
    xy2 = session.xyDataObjects['RF2']
    xy3 = combine(-xy1, -2*xy2)
    xy3.setValues(sourceDescription='combine ( -"U2",-2*"RF2" )')
    tmpName = xy3.name
    session.xyDataObjects.changeKey(tmpName, 'XYData-1')
    
    #Write report
    
    print odbName

    temp = odbName.split('/')[-1]
    my_name = temp.split('.')[0]
  
    [highlight #FCE94F]session.writeXYReport(fileName=my_name+'.rpt', xyData=(x0, ))[/highlight]
    
    del session.xyDataObjects['RF2']
    del session.xyDataObjects['U2']
    del session.xyDataObjects['XYData-1']

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Wow I hadn't defined x0 hence the warning that x0 is undefined. Mustaine3 the code works and I cannot thank you enough for helping me!!

For anyone else that comes across this post and wants to achieve the same thing the complete code is posted below:

Python:
def Eng_Tips():
    import section
    import regionToolset
    import displayGroupMdbToolset as dgm
    import part
    import material
    import assembly
    import step
    import interaction
    import load
    import mesh
    import optimization
    import job
    import sketch
    import visualization
    import xyPlot
    import displayGroupOdbToolset as dgo
    import connectorBehavior
    #Commented out naming lines
        #session.linkedViewportCommands.setValues(_highlightLinkedViewports=False)
        #odb = session.odbs['C:/Temp/CornerMaterial_TET.odb']
    #Name current file
   
    vps = session.viewports[session.currentViewportName]
    odbName = vps.displayedObject.name
    odb = session.odbs[odbName]
   
    #XY data from field variables
    #session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
        #NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
        #nodeSets=('Loading Node', ))
    #Rename field variables
   
    session.xyDataListFromField(odb=odb, outputPosition=NODAL, variable=(('RF',
    NODAL, ((COMPONENT, 'RF2'), )), ('U', NODAL, ((COMPONENT, 'U2'), )), ),
    nodeSets=('Loading Node', ))
 
    datalist = session.xyDataObjects.keys()
 
    for x in datalist:
        if x.find('RF2')>-1:
                        session.xyDataObjects.changeKey(fromName=x, toName='RF2')
        elif x.find('U2')>-1:
                        session.xyDataObjects.changeKey(fromName=x, toName='U2')
   
    #Create XY plot
  
    
    xy1 = session.xyDataObjects['U2']
    xy2 = session.xyDataObjects['RF2']
    xy3 = combine(-xy1, -2*xy2)
    xy3.setValues(sourceDescription='combine ( -"U2",-2*"RF2" )')
    tmpName = xy3.name
    session.xyDataObjects.changeKey(tmpName, 'XYData-1')
   
    #Write report
   
    print odbName
 
    temp = odbName.split('/')[-1]
    my_name = temp.split('.')[0]
 
    x0 = session.xyDataObjects['XYData-1']
    session.writeXYReport(fileName=my_name+'.rpt', xyData=(x0, ))
   
    del session.xyDataObjects['RF2']
    del session.xyDataObjects['U2']
    del session.xyDataObjects['XYData-1']

“The most successful people in life are the ones who ask questions. They’re always learning. They’re always growing. They’re always pushing.” Robert Kiyosaki
 
Glad you've worked it out.

You can reduce the many import lines at the beginning to those three:

from abaqus import *
from abaqusConstants import *
from caeModules import *
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor