View the .ipynb file.

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>]