Let us assume that you have multiple tables, and you’d like to aggregate them in a non-structured way. For example, you might have three tables coming from a design point, two from another design point, and four from a third design point. You might even have that each table contains the data for a different variable vs. Time, with no structure or information on what the variable might be. Now, you want to create a single plot for each design point, with all the existing variables vs. Time.
The fact that there is no way to know beforehand what variables you have for each design point, nor how many tables you will have, complicates things a bit when creating a template for an Ansys Dynamic Reporting (ADR) report. Fortunately, ADR contains a generator that is designed to iterate over all the items with a specific tag value: the iterator generator. So, here is how you can simply address the problem. Start a new ADR service on top of a new database:
import ansys.dynamicreporting.core as adr
a = adr.Service(db_directory=r'D:\tmp\iterators\new_db')
a.start(create_db=True)
Now, add to the database some tables for each design point. In this example, we will create values by scratch. Remember to tag each item with the design point number.
import numpy as np
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(0,10)), list(np.arange(0,1,0.1)*3)], dtype="|S20")
tmp_table.labels_row = ["Time", "Pressure"]
tmp_table.set_tags("dp=dp0")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(3,7)), list(np.arange(0,1,0.25)**2)], dtype="|S20")
tmp_table.labels_row = ["Time", "Temperature"]
tmp_table.set_tags("dp=dp0")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(5,12)), list(np.arange(1,1.6,0.1)*0.1)], dtype="|S20")
tmp_table.labels_row = ["Time", "Velocity"]
tmp_table.set_tags("dp=dp0")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(2,8)), list(np.arange(0,6)+1.2)], dtype="|S20")
tmp_table.labels_row = ["Time", "Pressure"]
tmp_table.set_tags("dp=dp1")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(0,10)), list(np.arange(3,13)**0.2)], dtype="|S20")
tmp_table.labels_row = ["Time", "Vorticity"]
tmp_table.set_tags("dp=dp1")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(3,10)), list(np.arange(3,10))], dtype="|S20")
tmp_table.labels_row = ["Time", "Temperature"]
tmp_table.set_tags("dp=dp2")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(0,15)), list(np.arange(0,1.5,0.1)*2 - 0.4)], dtype="|S20")
tmp_table.labels_row = ["Time", "Pressure"]
tmp_table.set_tags("dp=dp2")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(12,17)), list(np.arange(1,6)**2)], dtype="|S20")
tmp_table.labels_row = ["Time", "Velocity"]
tmp_table.set_tags("dp=dp2")
tmp_table = a.create_item()
tmp_table.item_table = np.array([list(np.arange(0,10)), list(np.arange(0,1,0.1)*3)], dtype="|S20")
tmp_table.labels_row = ["Time", "Static Pressure"]
tmp_table.set_tags("dp=dp2")
Now, time to create the report templates. The first step is to create an Iterator generator, and make it iterate over the dp
tag. From the adr_template_editor
interface, this is how it should look like:
This will return the existing items, grouped by the value of the dp tag. If you want to verify this mechanism, you can plate a Tab template as a child to the Iterator. This will show that there are three sets of tabs, one for each dp, with one tab for each of the tables.
Now, let’s make each set of tables into a plot. Create a Merge template generator under the Iterator. Leave all the defaults, except for the Generated items: from Append (default) to Replace. Now, set the following properties:
plot = line
(change the rendering to be line plots)
yaxis = [1,3,5,7] (yaxis is all the odd axis, which corresponds to the variables)
xaxis = [0,2,4,6]
(xaxis is all the even axis, which corresponds to Time) `
The result is the set of plots, one for each design points. 1
Now, these templates can be generated via the python API with the following lines:
server = a.serverobj
template_0 = server.create_template(name="Iterator", parent=None, report_type="Layout:iterator")
template_0.params = '{"tag": "dp"}'
server.put_objects(template_0)
template_1 = server.create_template(name="Merging", parent=template_0, report_type="Generator:tablemerge")
template_1.params = '{"HTML": "", "merge_params": {"column_labels_as_ids": 1, "transpose_output": 0, "force_numeric": 0, "merge_type": "row", "column_merge": "all", "column_id_row": "0", "collision_tag": "", "unknown_value": "nan", "table_name": "merged table", "source_rows": "\'*|duplicate\'"}, "generate_merge": "replace", "properties": {"plot": "line", "xaxis": "[0,2,4,6]", "yaxis": "[1,3,5,7]"}}'
server.put_objects(template_1)
server.put_objects(template_0)
Notice how all it takes is the combination of two simple templates to be able to handle a complex situation for reports where both the number of data points coming from the user, and the type of data that is contained in these items are unknown. This is the power of the Ansys Dynamic Reporting technology.
Note: remember you can stop the ADR service at the end of this exercise with the following line:
a.stop()
Further Reading
If you're looking for more articles on Ansys Dynamic Reporting here are some of our more popular reads: