{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Edit Data\n",
    "Create and edit a **Record** object and write your changes to the MI server.\n",
    "\n",
    "This notebook describes how to edit text-based attributes. See the following notebooks for additional attribute types:\n",
    "\n",
    "- [Point and range attributes](./12_Add_Point_Range_Data.ipynb)\n",
    "- [Date, integer, and logical attributes](./13_Add_Date_Integer_and_Logical_Data.ipynb)\n",
    "- [Functional attributes](./07_Import_Functional_Data.ipynb)\n",
    "- [Tabular attributes](./09_Edit_Tabular_Data.ipynb)\n",
    "- [File, picture, and hyperlink attributes](./11_Add_Files_Pictures_and_Hyperlinks.ipynb)\n",
    "- [Pseudo-attributes](./10_Edit_Pseudo-attributes.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connect to MI\n",
    "Get a database and table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import datetime\n",
    "from GRANTA_MIScriptingToolkit import granta as mpy\n",
    "\n",
    "mi = mpy.connect('http://localhost/mi_servicelayer', autologon=True)\n",
    "db = mi.get_db(db_key='MI_Training')\n",
    "db.set_unit_system(unit_system='SI (Consistent)', absolute_temperatures=True)\n",
    "tab = db.get_table('Design Data')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a new record and path\n",
    "Create a path in the table from a starting folder, in this case, the top level folder, using `path_from()`.\n",
    "Specify `end_node` to create a new **Record** object at the end of the path with that name."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<Record long name:STK Example 5:Tue Mar 23 15:50:51 2021>,\n",
       " <Record long name:AMS 6520>)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "now = datetime.now().strftime(\"%c\")\n",
    "record_name = 'STK Example 5:{}'.format(now)\n",
    "record = tab.path_from(None, tree_path=['High Alloy Steel', 'AMS 6520'], end_node=record_name)\n",
    "record, record.parent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Edit the record's attributes\n",
    "Get some attributes associated with the record."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "tab.bulk_fetch([record], attributes=['Common Name',\n",
    "                                     'Product Form',\n",
    "                                     'Statistical Basis',\n",
    "                                     'Available mechanical properties'])\n",
    "common_name = record.attributes['Common Name']\n",
    "product_form = record.attributes['Product Form']\n",
    "statistical_basis = record.attributes['Statistical Basis']\n",
    "available_properties = record.attributes['Available mechanical properties']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Edit their data values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "common_name.value = 'STK Example 5 Test Material'\n",
    "product_form.value = 'Plate'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "*Statistical Basis* is a single valued discrete attribute, and can be set either with a string or a list containing a\n",
    "single string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statistical Basis supports multivalued data? False\n"
     ]
    }
   ],
   "source": [
    "print(\"{} supports multivalued data? {}\".format(statistical_basis.name, statistical_basis.is_multivalued))\n",
    "statistical_basis.value = 'S basis'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Available mechanical properties* is a multivalued discrete attribute. It can be set either with a string or a list of\n",
    "strings for each value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Available mechanical properties supports multivalued data? True\n"
     ]
    }
   ],
   "source": [
    "print(\"{} supports multivalued data? {}\".format(available_properties.name, available_properties.is_multivalued))\n",
    "available_properties.value = ['Tensile', 'Compression']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set the record's release status\n",
    "If the record is being created in a version-controlled table,\n",
    "decide whether the record should be released after creation.\n",
    "The record is created in the **unreleased** state\n",
    "to allow more data to be added later without creating a new version."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "record.flag_for_release = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Write your changes to MI\n",
    "First, specify the attributes on the record which you want to update on the server."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "record.set_attributes([common_name, product_form, statistical_basis, available_properties])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then write the changes to MI. The list of updated **Record** objects is returned."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Record Name: STK Example 5:Tue Mar 23 15:50:51 2021, State: Unreleased\n"
     ]
    }
   ],
   "source": [
    "record = mi.update([record])[0]\n",
    "print('Record Name: {0}, State: {1}'.format(record.name, record.release_state))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 'Not Applicable' flag\n",
    "Further edits can be made to the same **Record** object. In this case, the *Condition* attribute is not relevant,\n",
    "so the `is_applicable` property is set to False. This sets the attribute to 'Not Applicable' in Granta MI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "condition = record.attributes['Condition']\n",
    "condition.is_applicable = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set the new attributes to update, and update again to write the latest changes to the server.\n",
    "No further changes are required for this record, so the record will be released."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Record Name: STK Example 5:Tue Mar 23 15:50:51 2021, State: Released\n"
     ]
    }
   ],
   "source": [
    "record.set_attributes([condition])\n",
    "record.flag_for_release = True\n",
    "record = mi.update([record])[0]\n",
    "\n",
    "print('Record Name: {0}, State: {1}'.format(record.name, record.release_state))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check the `Record.all_versions` property for a dictionary of all versions of the record. The dictionary\n",
    "contains a single version, confirming that only a single version was created in Granta MI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'v1': <Record long name:STK Example 5:Tue Mar 23 15:50:51 2021>}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "record.all_versions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Output the record's attributes\n",
    "The attribute values are accessed via the same properties used for assignment.\n",
    "*Statistical Basis* and *Available mechanical properties* are discrete attributes, so their `value` properties contain a\n",
    "list of strings.\n",
    "*Condition* is set to 'Not Applicable'; this is checked when printing the attribute value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Common Name: STK Example 5 Test Material\n",
      "Product Form: Plate\n",
      "Statistical Basis: S basis\n",
      "Available mechanical properties: Tensile, Compression\n",
      "Condition: <Not Applicable>\n"
     ]
    }
   ],
   "source": [
    "common_name = record.attributes['Common Name']\n",
    "print('Common Name: {0}'.format(common_name.value))\n",
    "\n",
    "product_form = record.attributes['Product Form']\n",
    "print('Product Form: {0}'.format(product_form.value))\n",
    "\n",
    "statistical_basis = record.attributes['Statistical Basis']\n",
    "print('Statistical Basis: {0}'.format(statistical_basis.value[0]))\n",
    "\n",
    "available_properties = record.attributes['Available mechanical properties']\n",
    "result = \", \".join([prop for prop in available_properties.value])\n",
    "print('Available mechanical properties: {0}'.format(result))\n",
    "\n",
    "condition = record.attributes['Condition']\n",
    "print('Condition: {0}'.format(condition.value if condition.is_applicable else '<Not Applicable>'))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
