Create Functional Data¶
Populate a functional attribute with data fitted using the Python numpy library.
Import libraries and define a polynomial fit function¶
This example populates a functional attribute for Ultimate Tensile Strength vs Temperature in one table from a polynomial fit of the individual attributes in another table.
[1]:
from datetime import datetime
import numpy as np
from GRANTA_MIScriptingToolkit import granta as mpy
def My4degPolyFitFunc(x, a, b, c, d, e):
return a*np.power(x, 4) + b*np.power(x, 3) + c*np.power(x, 2) + d*x + e
Specify database and table¶
The source data will come from the Tensile Statistical Data table.
[2]:
mi = mpy.connect('http://localhost/mi_servicelayer', autologon=True)
db = mi.get_db(db_key='MI_Training')
db.set_unit_system('Metric', absolute_temperatures=True)
table = db.get_table('Tensile Statistical Data')
Search for test data¶
Construct a search for records in which both the Ultimate Tensile Strength and Test Temperature attributes are populated.
[3]:
search_criteria = [table.attributes['Ultimate Tensile Strength'].search_criterion(exists=True),
table.attributes['Test Temperature'].search_criterion(exists=True)]
Perform the search and extract the results.
[4]:
results = table.search_for_records_where(search_criteria)
Extract the attribute values from the returned records into x and y values.
[5]:
table.bulk_fetch(results, attributes=['Test Temperature', 'Ultimate Tensile Strength'])
x_values = [r.attributes['Test Temperature'].points[0] for r in results]
y_values = [r.attributes['Ultimate Tensile Strength'].points[0] for r in results]
Fit the test data¶
Fit a fourth-order polynomial to your x and y data.
[6]:
coeffs = np.polyfit(x_values, y_values, 4)
Generate x and y values for the fitted equation, using the function you defined at the start.
[7]:
x_fit = np.linspace(np.amin(x_values), np.amax(x_values), 20)
y_fit = My4degPolyFitFunc(x_fit, *coeffs)
Create a record to store the data in¶
The resulting functional data will be written into the Design Data table, using the same unit system.
[8]:
designdata = db.get_table('Design Data')
Create a new record to store your functional data.
[9]:
now = datetime.now().strftime("%c")
recordName = 'STK Example 8:{}'.format(now)
record = designdata.create_record(recordName, subsets={'Metals'})
record.color = 'Green'
Access the (empty) functional attribute, and view its column headers.
[10]:
func = record.attributes['Tens. Ult. Stress (L-dir) with Temp.']
func.column_headers
[10]:
['Y min (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Y max (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Temperature [K]',
'Time [hr]',
'Other []',
'Data Type Lab []',
'Estimated point?']
Populate the functional attribute¶
Add the test data to the functional attribute point-by-point, then view the attribute data. Column headers can be omitted if they aren’t required to represent the data.
[11]:
for x, y in zip(x_values, y_values):
func.add_point({'Temperature':x, 'y':y, 'Data Type Lab':'Test Data'})
func.data
[11]:
[['Y min (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Y max (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Temperature [K]',
'Time [hr]',
'Other []',
'Data Type Lab []',
'Estimated point?'],
[1263.0048828125,
1263.0048828125,
810.9284057617188,
None,
None,
'Test Data',
False],
[1734.37646484375,
1734.37646484375,
699.8172607421875,
None,
None,
'Test Data',
False],
[2078.31, 2078.31, 422.0389938964844, None, None, 'Test Data', False],
[1848.140014648438,
1848.140014648438,
588.7060546875,
None,
None,
'Test Data',
False],
[2399.146240234375,
2399.146240234375,
194.2612762451172,
None,
None,
'Test Data',
False],
[2189.89, 2189.89, 294.2613938964844, None, None, 'Test Data', False]]
Then add the fitted data to the functional attribute point-by-point, and view the attribute data with series number as an extra column.
[12]:
for x, y in zip(x_fit, y_fit):
func.add_point({'Temperature':x, 'y':y, 'Data Type Lab':'Fitted Data'})
func.data_with_series_number
[12]:
[['Y min (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Y max (Tens. Ult. Stress (L-dir) with Temp. [MPa])',
'Temperature [K]',
'Time [hr]',
'Other []',
'Data Type Lab []',
'Estimated point?',
'Series number'],
[1263.0048828125,
1263.0048828125,
810.9284057617188,
None,
None,
'Test Data',
False,
1],
[1734.37646484375,
1734.37646484375,
699.8172607421875,
None,
None,
'Test Data',
False,
1],
[2078.31, 2078.31, 422.0389938964844, None, None, 'Test Data', False, 1],
[1848.140014648438,
1848.140014648438,
588.7060546875,
None,
None,
'Test Data',
False,
1],
[2399.146240234375,
2399.146240234375,
194.2612762451172,
None,
None,
'Test Data',
False,
1],
[2189.89, 2189.89, 294.2613938964844, None, None, 'Test Data', False, 1],
[2392.1796767662504,
2392.1796767662504,
194.2612762451172,
None,
None,
'Fitted Data',
False,
2],
[2333.081679240432,
2333.081679240432,
226.71744095651727,
None,
None,
'Fitted Data',
False,
2],
[2274.7406635683915,
2274.7406635683915,
259.17360566791734,
None,
None,
'Fitted Data',
False,
2],
[2219.003033513455,
2219.003033513455,
291.62977037931745,
None,
None,
'Fitted Data',
False,
2],
[2167.220212523074,
2167.220212523074,
324.0859350907175,
None,
None,
'Fitted Data',
False,
2],
[2120.248643728819,
2120.248643728819,
356.5420998021176,
None,
None,
'Fitted Data',
False,
2],
[2078.449789946381,
2078.449789946381,
388.9982645135177,
None,
None,
'Fitted Data',
False,
2],
[2041.690133675573,
2041.690133675573,
421.4544292249178,
None,
None,
'Fitted Data',
False,
2],
[2009.34117710033,
2009.34117710033,
453.91059393631787,
None,
None,
'Fitted Data',
False,
2],
[1980.2794420887071,
1980.2794420887071,
486.366758647718,
None,
None,
'Fitted Data',
False,
2],
[1952.8864701928815,
1952.8864701928815,
518.822923359118,
None,
None,
'Fitted Data',
False,
2],
[1925.0488226491511,
1925.0488226491511,
551.2790880705181,
None,
None,
'Fitted Data',
False,
2],
[1894.1580803779348,
1894.1580803779348,
583.7352527819182,
None,
None,
'Fitted Data',
False,
2],
[1857.1108439837724,
1857.1108439837724,
616.1914174933183,
None,
None,
'Fitted Data',
False,
2],
[1810.3087337553268,
1810.3087337553268,
648.6475822047184,
None,
None,
'Fitted Data',
False,
2],
[1749.6583896653788,
1749.6583896653788,
681.1037469161184,
None,
None,
'Fitted Data',
False,
2],
[1670.5714713708344,
1670.5714713708344,
713.5599116275185,
None,
None,
'Fitted Data',
False,
2],
[1567.9646582127193,
1567.9646582127193,
746.0160763389187,
None,
None,
'Fitted Data',
False,
2],
[1436.2596492161788,
1436.2596492161788,
778.4722410503188,
None,
None,
'Fitted Data',
False,
2],
[1269.383163090479,
1269.383163090479,
810.9284057617188,
None,
None,
'Fitted Data',
False,
2]]
Adjust the series linestyles (series_linestyles is a dictionary, indexed with integers).
[13]:
func.series_linestyles[1] = 'Markers'
func.series_linestyles[2] = 'Lines'
func.series_linestyles
[13]:
{1: 'Markers', 2: 'Lines'}
Write your changes to MI¶
Set the attributes you’ve modified to update, and write the new record to the server.
[14]:
record.set_attributes([func])
mi.update([record])
[14]:
[<Record long name:STK Example 8:Tue Mar 23 16:15:05 2021>]