1###############################################################################
2# Copyright (c) 2023 - 2025 Altair Engineering Inc. All Rights Reserved
3# Contains trade secrets of Altair Engineering, Inc. Copyright notice
4# does not imply publication. Decompilation or disassembly of this
5# software is strictly prohibited.
6###############################################################################
7
8"""
9Example script to demo use of the API to create a simple DOE and Fit and adding an
10inclusion matrix from a csv file.
11
12Windows -
13 <installation_root>/hwdesktop/hst/bin/win64/hstbatch.exe -pyfile doe_inclusion_matrix.py
14"""
15
16import alt.hst.api.session as sess
17import alt.hst.api.api_objects as api_objects
18import csv
19import os
20import pathlib
21import random
22import typing
23
24msg = sess.getMessageService()
25
26
27###############################################################################
28# Helper methods
29###############################################################################
30def addVariable(inputVariableList: api_objects.VariableList,
31 label: str,
32 varname: str,
33 upper: float,
34 lower: float,
35 nominal: float) -> None:
36 """
37 Helper method for adding design variables to an approach
38 """
39 var = inputVariableList.add()
40 var.setDataType(api_objects.DataType.REAL)
41 var.setLabel(label)
42 var.setVarname(varname)
43 var.setUpperBound(upper)
44 var.setLowerBound(lower)
45 var.setNominalValue(nominal)
46 var.setFormatToolType(api_objects.FormatToolTypes.TYPE_CONTINUOUS)
47
48
49def addInclusionMatrixMapping(inclusionMappingList: api_objects.ImportFilePersistedMappingList,
50 varname: str, columnName: str) -> None:
51 """
52 Helper method for mapping a varname to a column header
53 """
54 mapping = inclusionMappingList.add()
55 mapping.setMapToVarname(varname)
56 mapping.setMapFromColumn(columnName)
57
58
59###############################################################################
60# Create a study
61###############################################################################
62studyDir = pathlib.Path(os.getcwd()) / "doe_inclusion_matrix"
63os.makedirs(str(studyDir), exist_ok=True)
64
65# Create the study
66studyList = sess.getStudyList()
67study = studyList.add()
68study.setStudyFile(str(studyDir / 'beverage_can.hstudy'))
69study.setDirectory(str(studyDir))
70
71msg.postInfo('Create study at ( ' + str(studyDir) + ' )')
72msg.postInfo('Created study at ( ' + study.getStudyFile() + ' )')
73
74
75###############################################################################
76# Add a setup approach
77###############################################################################
78approachList = study.getApproachList()
79setupApproach = approachList[0]
80
81# Add a single internal math model to the Setup approach
82modelList = setupApproach.getDefinition().getModelList()
83mathModel = modelList.add()
84mathModel.setModelToolType(api_objects.ModelToolTypes.TYPE_HST_INTERNAL_MATH)
85
86variableList = setupApproach.getDefinition().getDesignVariableList()
87addVariable(variableList, "Width", "width", 3.0, 0.001, 1.0)
88addVariable(variableList, "Height", "height", 5.0, 0.1, 1.0)
89addVariable(variableList, "Depth", "depth", 100.0, 0.5, 1.0)
90
91# Add a single response
92responseList = setupApproach.getDefinition().getResponseList()
93response = responseList.add()
94response.setType(api_objects.DataType.REAL)
95response.setEquation("width*depth+height")
96
97
98###############################################################################
99# Add a DOE approach
100###############################################################################
101doe = approachList.add("doe_1", "DOE 1")
102doe.setTool("Doe")
103
104# Create the inclusion matrix data
105datafile = studyDir / "data_matrix.csv"
106rowCount = 40
107with open(str(datafile), "w+", encoding='utf-8') as csvfile:
108 writer = csv.writer(csvfile)
109 writer.writerow(["width_data", "height_data", "depth_data", "response_data"])
110 for n in range(rowCount):
111 width = random.uniform(0.001, 3.0)
112 height = random.uniform(0.1, 5.0)
113 depth = random.uniform(0.5, 100.0)
114 responseValue = width * height + depth
115 writer.writerow([width, height, depth, responseValue])
116
117# Add an inclusion matrix from a file source
118doeMatrixList = doe.getMatrixList()
119doeMatrix = doeMatrixList.add()
120doeMatrix.setSource("TextFile")
121sourceTool = typing.cast(api_objects.FrameSource_PlainText, doeMatrix.getOrigin())
122fileSettings = sourceTool.getFileSettings()
123fileSettings.setNamedAttribute("file", str(datafile))
124fileSettings.setNamedAttribute("delimiter", "Comma")
125fileSettings.setNamedAttribute("columns_have_headers", True)
126fileSettings.setNamedAttribute("start_import_row", 0)
127fileSettings.setNamedAttribute("end_import_row", rowCount)
128
129mappingList = sourceTool.getMappingList()
130addInclusionMatrixMapping(mappingList, "width", "width_data")
131addInclusionMatrixMapping(mappingList, "height", "height_data")
132addInclusionMatrixMapping(mappingList, "depth", "depth_data")
133addInclusionMatrixMapping(mappingList, response.getVarname(), "response_data")
134
135# Setup the DOE specifications
136doeApproachTool = typing.cast(api_objects.ApproachTool_Doe, doe.getApproachTool())
137doeApproachTool.setUncontrolledPerturbationVarname('Initial')
138
139# We want an Empty DOE since we are using the CSV data
140doe.setDesignVarname("Empty")
141doe.applySpecification()
142
143# Start the DOE evaluation
144doe.startEvaluate()
145
146
147###############################################################################
148# Add a fit approach'
149###############################################################################
150# Add a fit approach using the DOE data
151fit = approachList.add("fit_1", "Fit 1")
152fit.setApproachToolType(api_objects.ApproachToolTypes.TYPE_FIT)
153
154# Add an inclusion matrix, using the DOE approach as the source
155fitMatrixList = fit.getMatrixList()
156fitMatrix = fitMatrixList.getAtIndex(0)
157fitMatrix.setLabel('Train')
158fitSource = typing.cast(api_objects.FrameSource_Approach, fitMatrix.getOrigin())
159fitSource.setApproach(doe.getVarname())
160
161# Enable summary data and approach specific reports
162fitReportList = fit.getReportList()
163fitReportList["hst_data"].setState(True)
164fitReportList["hst_approach_specific"].setState(True)
165
166# Evaluate the fit
167fitApproachTool = typing.cast(api_objects.ApproachTool_Fit, fit.getApproachTool())
168designList = fitApproachTool.getDesignList()
169for design in designList:
170 design.setState(True)
171
172fit.setCommandWriteInputDecksAPI(True)
173fit.setCommandExecuteAnalysisAPI(True)
174fit.setCommandExtractResponsesAPI(True)
175fit.setCommandCreateReportAPI(True)
176fit.applySpecification()
177fit.startEvaluate()
178
179# Save the study file
180study.save()
181
182# Close the current study
183studyList.closeStudy(study.getVarname())