Results#
Some examples require external input files. Before you start, please follow the link in the Example Scripts section to download the zip file with model and result files.
Example 01 - Contour Model and Export#
The example code shows how to set the window to HyperView client (type="animation") and display a contour plot of Von Mises composite stress using the ResultDefinitionScalar class. Once the results are plotted, two new objects are created - instances of the ExportModelH3D class and CaptureImageTool class respectively. The exportH3D object is used to export an H3D file containing the displayed results and the captureImage object provides the method to capture a screenshot of the window.
1import hw
2import hw.hv as hv
3import os
4
5scriptDir = os.path.abspath(os.path.dirname(__file__))
6modelFile = os.path.join(scriptDir, "aerobox", "aerobox.fem")
7resultFile = os.path.join(scriptDir, "aerobox", "aerobox-LC1-2.op2")
8h3dFile = os.path.join(scriptDir, "demo_model_export.h3d")
9jpgFile = os.path.join(scriptDir, "demo_image_export.jpeg")
10
11ses = hw.Session()
12ses.new()
13win = ses.get(hw.Window)
14win.type = "animation"
15
16win.addModelAndResult(model=modelFile, result=resultFile)
17res = ses.get(hv.Result)
18resScalar = hv.ResultDefinitionScalar(
19 dataType="Composite Stress",
20 dataComponent="vonMises",
21 layer="Max"
22)
23res.plot(resScalar)
24
25exportH3D = hv.ExportModelH3D(
26 animation=True,
27 previewImage=False,
28 compressOutput=True,
29 compressionLoss=0.05,
30 file=h3dFile,
31)
32
33captureImage = hw.CaptureImageTool(
34 type="jpg",
35 width=3000,
36 height=2000,
37 file=jpgFile
38)
39
40animTool = hw.AnimationTool()
41animTool.currentFrame = 1
42
43hw.evalHWC("view orientation iso")
44exportH3D.export()
45captureImage.capture()
Figure 1. Output of ‘Contour Model and Export’
Example 02 - Macro with GUI#
The Macro with GUI example consists of two main functions - MyCustomGui() and postprocAuto().
MyCustomGui() generates a custom dialog using the Dialog class with the following widgets:
OpenFileEntryto specify the model fileOpenFileEntryto specify the result fileChooseDirEntryto specify the output directoryButtonto provide the close functionButtonto provide the run function
The widgets are organized into a vertical frame using the VFrame class. The example also includes code to automatically populate the file paths for demo purposes.
postprocAuto() provides the postprocessing logic. Two new objects are created at the start: capture for screenshot generation and exportH3D for H3D file export. This is followed by the definition of two dictionaries: resDict contains list of data components for four different data types and legDict contains legend settings for each of the four data types. These dictionaries are used in nested loops to generate a page per data type, each page containing four windows (layout=9), one window per data component.
1import hw
2import hw.hv as hv
3from hwx import gui
4import os
5
6def MyCustomGui():
7
8 # Method called on clicking 'Close'.
9 def onClose(event):
10 dialog.Hide()
11
12 def onRun(event):
13 dialog.Hide()
14 postprocAuto(modelFile.value, resultFile.value, folderSel.value)
15 gui.tellUser("Done!")
16
17 label1 = gui.Label(text="Model File")
18 modelFile = gui.OpenFileEntry(placeHolderText="Model File")
19 label2 = gui.Label(text="Result File")
20 resultFile = gui.OpenFileEntry(placeHolderText="Result File")
21 label3 = gui.Label(text="Screenshot Folder")
22 folderSel = gui.ChooseDirEntry(tooltip="Select output directory")
23
24 close = gui.Button("Close", command=onClose)
25 create = gui.Button("Run", command=onRun)
26
27 # Default file settings for quick demo purposes
28 if True:
29 src_path = os.path.dirname(os.path.abspath(__file__))
30 modelFile.value = os.path.join(src_path, "aerobox", "aerobox.fem").replace(
31 "\\", "/"
32 )
33 resultFile.value = os.path.join(
34 src_path, "aerobox", "aerobox-LC1-2.op2"
35 ).replace("\\", "/")
36 folderSel.value = os.path.join(src_path, "outDir").replace("\\", "/")
37
38 mainFrame = gui.VFrame(
39 (label1, 20, modelFile),
40 (label2, 20, resultFile),
41 (label3, 20, folderSel),
42 (create, close),
43 )
44
45 dialog = gui.Dialog(caption="Post Automation")
46 dialog.addChildren(mainFrame)
47 dialog.width = 400
48 dialog.height = 100
49 dialog.show()
50
51
52def postprocAuto(modelPath, resultPath, outDir):
53
54 # Create Session Pointer
55 ses = hw.Session()
56 # New
57 ses.new()
58
59 # Define Capture Image Tool
60 capture = hw.CaptureImageTool()
61 capture.type = "jpg"
62 capture.width = 1200
63 capture.height = 800
64
65 # Define H3D export
66 exportH3D = hv.ExportModelH3D(
67 animation=True, previewImage=False, compressOutput=True, compressionLoss=0.05
68 )
69
70 # Dictionary with dataType dependent result scalar settings
71 resDict = {
72 "Displacement": ["Mag", "X", "Y", "Z"],
73 "Composite Stress": ["vonMises", "P1 (major)", "P2 (mid)", "P3 (minor)"],
74 "Composite Strain": ["vonMises", "XX", "YY", "ZZ"],
75 "Stress": [
76 "vonMises",
77 "MaxShear",
78 "In-plane P1 (major)",
79 "In-plane P2 (minor)",
80 ],
81 }
82
83 # Dictionary with dataType dependent legend settings (precision, numerical format,
84 legDict = {
85 "Displacement": [5, "scientific", 2],
86 "Composite Stress": [6, "engineering", 4],
87 "Composite Strain": [7, "fixed", 6],
88 "Stress": [10, "engineering", 2],
89 }
90 # Change window type
91 ses.get(hw.Window).type = "animation"
92
93 startPageId = ses.get(hw.Page).id + 1
94
95 # Loop over data types, 1 page per data type
96 for dType in list(resDict.keys()):
97 ap = hw.Page(title=dType, layout=9)
98 ses.setActive(hw.Page, page=ap)
99
100 # Loop over data components, one window per component
101 for i, w in enumerate(ses.getWindows()):
102 dComp = resDict.get(dType)[i]
103 ses.setActive(hw.Window, window=w)
104
105 # Load Model
106 w.addModelAndResult(model = modelPath, result=resultPath)
107
108 # Set scalar results
109 res = ses.get(hv.Result)
110 resScalar = ses.get(hv.ResultDefinitionScalar)
111 resScalar.setAttributes(dataType=dType, dataComponent=dComp)
112
113 # Plot results
114 res.plot(resScalar)
115
116 # Define legend settings
117 leg = ses.get(hv.LegendScalar)
118 leg.setAttributes(
119 numberOfLevels=legDict.get(dType)[0],
120 numericFormat=legDict.get(dType)[1],
121 numericPrecision=legDict.get(dType)[2],
122 )
123
124 # Define ISO settings
125 resIso = ses.get(hv.ResultDefinitionIso)
126 resIso.setAttributes(dataType=dType, dataComponent=dComp)
127 dispIso = ses.get(hv.ResultDisplayIso)
128 res.plotIso(resIso)
129
130 # Set ISO value dependent on min/max
131 dispIso.value = leg.minValue + (leg.maxValue - leg.minValue) / 5
132
133 # Set animation frame 1
134 animTool = hw.AnimationTool()
135 animTool.currentFrame = 1
136
137 # Capture jpg
138 jpgPath = os.path.join(outDir, dType + " - " + dComp + "_iso_view.jpg")
139 capture.file = jpgPath
140 capture.capture()
141
142 # Capture H3D
143 h3dPath = os.path.join(outDir, dType + " - " + dComp + ".h3d")
144 exportH3D.setAttributes(file=h3dPath, window=w)
145 exportH3D.export()
146
147 # Use Model, Collection and Part class to isolate component
148 if True:
149 mod = ses.get(hv.Model)
150 col = hv.Collection(hv.Part)
151 mod.hide(col)
152 mod.get(hv.Part, 172).visibility = True
153 # Use evalHWC isolate component for export
154 else:
155 hw.evalHWC("hide component all")
156 hw.evalHWC("show component 172")
157
158 # Set Views and export
159 hw.evalHWC("view orientation left")
160 jpgPath = os.path.join(outDir, dType + " - " + dComp + "_left_view.jpg")
161 capture.file = jpgPath
162 hw.evalHWC("show component all")
163 hw.evalHWC("view orientation iso")
164
165 ses.setActive(hw.Page, id=startPageId)
166
167
168if __name__ == "__main__":
169 MyCustomGui()
Figure 2. Start GUI and exported images / H3D’s of ‘Macro with GUI’
Figure 3. hw.Page created for one data type by ‘Macro with GUI’
Example 03 - Contour Maximum by Sphere#
After the standard steps (setting up the window, loading the model/result files, and contouring the results), the example shows the user how to select elements around the element with the maximum contour plot value using FilterBySphere. It proceeds with setting up custom properties of the legend, including custom header font. It then displays the contour plot only on the entities inside the sphere collection. Finally, it creates a note using the HWC commands, sets the results to the first animation frame and puts the model into an iso orientation.
1import hw
2import hw.hv as hv
3import os
4
5scriptDir = os.path.abspath(os.path.dirname(__file__))
6modelFile = os.path.join(scriptDir, "aerobox", "aerobox.fem")
7resultFile = os.path.join(scriptDir, "aerobox", "aerobox-LC1-2.op2")
8
9hotspotRadius = 400
10
11# Load Model
12ses = hw.Session()
13ses.new()
14page = ses.get(hw.Page)
15win = ses.get(hw.Window)
16win.type = "animation"
17win.addModelAndResult(model=modelFile, result=resultFile)
18
19# Contour scalar
20res = ses.get(hv.Result)
21resScalar = ses.get(hv.ResultDefinitionScalar)
22resScalar.setAttributes(
23 dataType="Composite Stress", dataComponent="vonMises", layer="Max"
24)
25res.plot(resScalar)
26
27# Create Collection via TopN filter
28maxElemCol = hv.Collection(hv.Element, populate=False)
29elemFilter = hv.FilterByScalar(operator="topN", value=1)
30maxElemCol.addByFilter(elemFilter)
31
32# Get centroid of element with maximum scalar value
33maxElem = maxElemCol.getEntities()[0]
34centroid = maxElem.centroid
35
36# Create collection with given radius
37sphereCol = hv.Collection(hv.Element, populate=False)
38sphereFilter = hv.FilterBySphere(
39 x=centroid[0],
40 y=centroid[1],
41 z=centroid[2],
42 radius=hotspotRadius
43)
44sphereCol.addByFilter(sphereFilter)
45
46# Define font
47headFont = hw.Font(size=14, style="bold")
48
49# Modify legend
50legend = ses.get(hv.LegendScalar)
51legend.setAttributes(
52 headerText="Hostpot Radius = " + str(hotspotRadius),
53 headerVisible=True,
54 headerFont=headFont,
55 numberOfLevels=8,
56 numericFormat="fixed",
57 numericPrecision=0,
58)
59
60# Contour only sphere collection
61resScalar.collection = sphereCol
62res.plot(resScalar)
63
64# Attach max note with evalHWC
65maxId = str(maxElem.id)
66maxLabel = "Max Element " + maxId
67hw.evalHWC('annotation note create "' + maxLabel + '"')
68hw.evalHWC('annotation note "'
69 + maxLabel
70 + '" attach entity element '
71 + maxId
72)
73hw.evalHWC(
74 'annotation note "'
75 + maxLabel
76 + '" \
77 display text= "Max Element: {entity.id}\\nMax Value: {entity.contour_val}" \
78 movetoentity=true \
79 filltransparency=false \
80 fillcolor="255 255 255"'
81)
82
83# Set frame with AnimationTool()
84animTool = hw.AnimationTool()
85animTool.currentFrame = 1
86
87# Modify view with evalHWC
88hw.evalHWC("view orientation iso")
Figure 4. Output of ‘Contour Maximum by Sphere
Example 04 - Query Result Data with Default Settings#
The example shows how to set up a contour, vector, and tensor plot, followed by the querying of the displayed results using QueryResultsTool. An instance of this class is created and the result data is extracted into a Numpy array using the query() method. The default settings/attribute of the QueryResultsTool object are used.
1import hw
2import hw.hv as hv
3import os
4
5ALTAIR_HOME = os.path.abspath(os.environ['ALTAIR_HOME'])
6modelFile = os.path.join(ALTAIR_HOME,'demos','mv_hv_hg','animation','dyna','bumper','bumper_deck.key')
7resultFile = os.path.join(ALTAIR_HOME,'demos','mv_hv_hg','animation','dyna','bumper','d3plot')
8
9# Load Model/Results
10ses = hw.Session()
11ses.new()
12win = ses.get(hw.Window)
13win.type = 'animation'
14win.addModelAndResult(model=modelFile, result=resultFile)
15
16# Set scalar, vector and tensor results
17res = ses.get(hv.Result)
18resScalar = hv.ResultDefinitionScalar(dataType='Stress',
19 dataComponent='vonMises')
20res.plot(resScalar)
21resVector = hv.ResultDefinitionVector(dataType='Stress')
22res.plot(resVector)
23resTensor = hv.ResultDefinitionTensor(dataType='Stress')
24resTensor.format = 'component'
25resTensor.setComponentStatus(xx=True,yy=True,zz=True,xy=True,yz=True,zx=True)
26res.plot(resTensor)
27
28# Set View
29hw.evalHWC('view projection orthographic | view matrix -0.021537 0.988942 0.146732 0.000000 0.872753 0.090190 -0.479758 0.000000 -0.487686 0.117728 -0.865045 0.000000 -99.918198 345.190369 584.070618 1.000000 | view clippingregion -284.806213 129.713852 528.670959 864.158752 -722.333801 601.748169')
30
31# Set time step
32animTool = hw.AnimationTool()
33animTool.currentFrame = res.getSimulationIds()[-2]
34win.draw()
35print('')
36print('Query with Defaults')
37print('-------------------')
38
39# Create Query Result Tool
40queryTool = hv.QueryResultsTool()
41print('Data Source Info:')
42
43# Get available data source info array
44dataSourceInfoArray = queryTool.getDataSourceInfo()
45print(dataSourceInfoArray)
46
47# Query NumPy with default settings
48queriedData = queryTool.query()
49print('')
50
51# Get data source query created by default
52dataSource = queryTool.getDataSourceQuery()
53print('Default data source query = {}'.format(dataSource))
54
55# Get default collection
56entCol = queryTool.collection
57print('Size of default {} collection = {}'.format(entCol.entityType,entCol.getSize()))
58print('')
59
60# NumPY array
61print('NumPy Array:')
62print('Length numpy array = {}'.format(len(queriedData)))
63print(queriedData)
Figure 5. Console output of query NumPy array with default settings
Example 05 - Query Result Data with Custom Query#
After the standard steps (setting up the window, loading the model/result files, and contouring the results), the example shows how to create a collection of elements with the scalar value greater than 100 using FilterByScalar. This collection is used as the input for the QueryResultsTool object in order to extract the data only for a specific entity selection. The queried data is defined via the setDataSourceQuery() method and extracted into a Numpy array using the query() method.
1import hw
2import hw.hv as hv
3import os
4
5ALTAIR_HOME = os.path.abspath(os.environ['ALTAIR_HOME'])
6modelFile = os.path.join(ALTAIR_HOME,'demos','mv_hv_hg','animation','dyna','bumper','bumper_deck.key')
7resultFile = os.path.join(ALTAIR_HOME,'demos','mv_hv_hg','animation','dyna','bumper','d3plot')
8
9# Load Model/Results
10ses = hw.Session()
11ses.new()
12win=ses.get(hw.Window)
13win.type = 'animation'
14win.addModelAndResult(model=modelFile, result=resultFile)
15
16# Set scalar results
17res = ses.get(hv.Result)
18resScalar = hv.ResultDefinitionScalar(dataType='Stress',
19 dataComponent='vonMises')
20res.plot(resScalar)
21
22animTool = hw.AnimationTool()
23animTool.currentFrame = 1
24win.draw()
25
26# Create element collection
27elemCol = hv.Collection(hv.Element,populate=False)
28
29# Add all elements with a value > 0
30valFilter = hv.FilterByScalar(operator='>',value=100)
31elemCol.addByFilter(valFilter)
32
33# Create Query Result Tool
34queryTool = hv.QueryResultsTool()
35
36# Set Element Collection
37queryTool.collection = elemCol
38print('')
39queryTool.setDataSourceQuery(
40 [['element', 'id'],
41 ['contour', 'value'],
42 ['element','config'],
43 ['component','pool'],
44 ['component','name'],
45 ['element','normal']]
46)
47
48# Data source query
49print('Data source query = {}'.format(queryTool.getDataSourceQuery()))
50
51# Query NumPy array
52queriedData = queryTool.query()
53print('')
54
55# Get default collection
56print('Size of {} collection with value > 0 = {}'.format(elemCol.entityType,elemCol.getSize()))
57print('')
58
59# NumPY array
60print('NumPy Array:')
61print('Length numpy array = {}'.format(len(queriedData)))
62print(queriedData)
Figure 6. Console output of query NumPy array with custom query