{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# DataObject\n\nThis demo shows some basic features of the ``itom`` dataObject.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from itom import dataObject\nfrom itom import plot\n\n# some constants\nyDim = 480\nxDim = 640\nzDim = 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creation of several data objects\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# empty dataObject\nobjEmpty = dataObject()\n\n# a one-dimensional dataObject does not exist, always create a 1xM or Mx1 instead\nobj2dim = dataObject([yDim, xDim], \"float64\")\nobj3dim = dataObject([zDim, yDim, xDim], \"uint16\")\n\n# Special constructors for zero, ones, eye and randomly filled objects\nobjZero = dataObject.zeros([yDim, xDim], \"float64\") # 2D object filled with zeros\nobjOnes = dataObject.ones([yDim, xDim], \"float64\") # 2D object filled with ones\nobjEye = dataObject.eye(4, \"uint8\") # 4x4 matrix\nobjRand = dataObject.rand([yDim, xDim], \"uint8\") # 2D object filled with uniformly distributed random values\nobjRandN = dataObject.randN([yDim, xDim], \"uint8\") # 2D object filled with Gaussian distributed random values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. hint:: the methods rand and randN create values in the full data range for integer based data types\n whereas the randomly distributed values are in the range [0,1) for floating point data types.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Type conversion\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "objRandFloat = objRand.astype(\"float64\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Assign values to data objects\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# fill the upper half of the object with 5.7 (the operator // makes an integer division)\nobj2dim[0: yDim // 2, :] = 5.7\n\n# fill the bottom half of the object with 6.6 (the operator // makes an integer division)\nobj2dim[yDim // 2:, :] = 6.6\n\n# fill a selected rectangle with -2.0\nobj2dim[5:10, 20:100] = -2.0\n\n# fill the entire 3d object with zero\nobj3dim[:, :, :] = 0\n# replace the 2nd plane of the 3d object by the random values of the casted object\nobj3dim[1, :, :] = objRand.astype(obj3dim.dtype)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Delete objects\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "del objRandFloat" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Shallow copies\n\nPython has the concept to share as much memory as possible between different objects.\nThis also holds for dataObjects. In some cases, e.g. a change of type, shared memories can not\nbe kept, such that an implicit separation of both objects is done.\nIf two objects are shallow copies to each other, the memory as well as tags and other meta information is shared.\nHowever, one object can be a sub-slice, so called region of interest (ROI), of the other one, such that the\nsize of the object is individual for each object.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# both variables point to exactly the same dataObject in memory (everything shared)\nobjZero2 = objZero\n\n# objZero3 is a shallow copy of objZero with the same matrix size\nobjZero3 = objZero[:, :]\n\n# objZero4 is a shallow copy including a region of interest to the first 20 rows and columns\nobjZero4 = objZero[0:20, 0:20]\n\n# change the values in the first 20 rows and columns of objZero4 to 5\nobjZero4[:, :] = 5\n\n# (hence, objZero, objZero2 and objZero4 are changed, too). Proof:\nplot(objZero) # opens a 2d plot of objZero" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Deep copy\nIf you want to have a deep copy, with separated memory and meta information of a dataObject, use the copy-operator'''\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "obj2dimCopy = obj2dim.copy()\nplot(obj2dimCopy)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Accessing values\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(\"objZero at index 0,5 (row, column):\", objZero[0, 5])\n\n# get the first five values of the first row of objZero:\nvals = objZero[0, 0:5] # the last value of a slice is always EXCLUDED from the slice\n\n# vals is now a dataObject, however it can be converted to a tuple:\nprint(\"first five values of objZero:\", vals.value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Axis scaling, offset, description and unit\n\nevery dataObject can have meta information for each axis.\nThe scaling represents unit/px and gives the physical representation of the axis\nThe offset is the offset of the first value in this axis, given in pixel\nThe transformation between pixel and physical coordinates is then:\nphys_coord = (px_coord - offset) * scaling\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "obj2dim.axisScales = (0.1, 0.1) # 0.1 mm / px\nobj2dim.axisOffsets = (0, 100) # the x-axis starts now at -10mm (100 * 0.1)\nobj2dim.axisUnits = (\"mm\", \"mm\")\nobj2dim.axisDescriptions = (\"y-axis\", \"x-axis\")\nobj2dim.setTag(\"title\", \"obj2dim Title\")\n\nobj2dim.valueUnit = u\"\\xb0\" # this is a special character. To allow this, the first line of this script is relevant (right click -> insert codec)\nobj2dim.valueDescription = \"phase\"\n\nplot(obj2dim, properties={\"colorBarVisible\": True})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tags\n\nIt is possible to add string or double valued tags to each dataObject. There are some special tags,\nthat can directly be interpreted by plots (e.g. the 'title' tag). All other tags can be used for any purpose.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "obj3dim.setTag(\n \"title\",\n \"This is a 3d object, use the spin box to switch between planes\",\n)\nplot(obj3dim)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Set additional informations (meta data) as tags\n# Use set tag \"key\", \"value\". Key / value are user defined.\nobj2dim.setTag(\"Creator\", \"itom\")\nobj2dim.setTag(\"Type\", \"Measurement\")\nobj2dim.setTag(\"DummyTag\", \"Delete Me\")\n\n# Retrieve tags by their key and print them\nprint(obj2dim.tags[\"Creator\"])\nprint(obj2dim.tags[\"Type\"])\n\n# Get the complete tag space as a python dictionary\ntagdic = obj2dim.tags\n\n# Get the size of the tagspace\nprint(obj2dim.getTagListSize())\n# or\nprint(len(tagdic))\n\n# List up all tags in the tagspace\nprint(\"\\nMy Taglist\")\nfor key in tagdic.keys():\n print(key + \" -> \" + obj2dim.tags[key])\n\n# Delete a tag\nobj2dim.deleteTag(\"DummyTag\")\n\n# List up all tags in the tagspace\nprint(\"\\nMy Taglist\")\nfor key in obj2dim.tags.keys():\n print(key + \" -> \" + obj2dim.tags[key])\n\n# The dataObject has a protocol function. It is a tag and many filters in c++ add their properties after computation to this string by using addToProtocol\n# Add a protocol to the Object, if object is a ROI-ShallowCopy the ROI is automatically added to the protocol-String\nprint(\"\\nProtocol function:\")\nobj2dim.addToProtocol(\"Created today for test reasons\")\n# Read protocol string\nprint(obj2dim.tags[\"protocol\"])" ] } ], "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.8.10" } }, "nbformat": 4, "nbformat_minor": 0 }