{ "cells": [ { "cell_type": "markdown", "id": "9beeccb7", "metadata": {}, "source": [ "# WolfArray - Data type\n", "\n", "A `WolfArray` can store any type of data, including:\n", "\n", "- `int` (integer8, integer16, integer32)\n", "- `float` (floating point number, 32-bit or 64-bit)\n", "- `bool` (boolean/logical)\n", "\n", "WOLF types are defined as follows (for compatibility with Fortran and VB6):\n", "\n", "- WOLF_ARRAY_HILLSHAPE = -1\n", "- WOLF_ARRAY_FULL_SINGLE = 1\n", "- WOLF_ARRAY_FULL_DOUBLE = 2\n", "- WOLF_ARRAY_SYM_DOUBLE = 12\n", "- WOLF_ARRAY_FULL_LOGICAL = 4\n", "- WOLF_ARRAY_CSR_DOUBLE = 5\n", "- WOLF_ARRAY_FULL_INTEGER = 6\n", "- WOLF_ARRAY_FULL_SINGLE_3D = 7\n", "- WOLF_ARRAY_FULL_INTEGER8 = 8\n", "- WOLF_ARRAY_FULL_UINTEGER8 = 88\n", "\n", "Equivalent Numpy types can be obtained using the `dtype` attribute." ] }, { "cell_type": "code", "execution_count": null, "id": "c5c3a6c3", "metadata": {}, "outputs": [], "source": [ "# import _add_path\n", "from wolfhece.wolf_array import WolfArray, WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_DOUBLE, header_wolf" ] }, { "cell_type": "markdown", "id": "a9d720ed", "metadata": {}, "source": [ "## Using \"whichtype\" during WolfArray creation\n", "\n", "`whichtype` is a parameter that specifies the type of data to be stored in the WolfArray.'" ] }, { "cell_type": "code", "execution_count": 2, "id": "b2453ffe", "metadata": {}, "outputs": [], "source": [ "h = header_wolf()\n", "h.shape = (10,10)\n", "\n", "w_single = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_SINGLE)\n", "w_double = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_DOUBLE)\n", "w_integer8 = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_INTEGER8)\n" ] }, { "cell_type": "markdown", "id": "2e422719", "metadata": {}, "source": [ "## Get equivalent Numpy type\n", "\n", "The `dtype` attribute of a WolfArray object can be used to get the equivalent Numpy type. The `dtype` attribute is a property of the WolfArray class that returns the data type of the array as a Numpy dtype object." ] }, { "cell_type": "code", "execution_count": 3, "id": "e841c53e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " float32\n", " float64\n", " int8\n" ] } ], "source": [ "# check the dtype of the array and the WolfArray object\n", "print(w_single.dtype, w_single.array.dtype)\n", "print(w_double.dtype, w_double.array.dtype)\n", "print(w_integer8.dtype, w_integer8.array.dtype)" ] }, { "cell_type": "markdown", "id": "59eb65ec", "metadata": {}, "source": [ "## Modifying Values in a WolfArray\n", "\n", "The `array` attribute of a WolfArray is a Numpy masked array, allowing you to leverage Numpy's powerful indexing and slicing capabilities to modify its values.\n", "\n", "Key Considerations:\n", "\n", "- Ensure that the modifications maintain the **same data type** as the original array.\n", "- The memory layout must remain **contiguous**." ] }, { "cell_type": "code", "execution_count": 4, "id": "a76bd160", "metadata": {}, "outputs": [], "source": [ "# Modify some values in the array\n", "w_integer8.array [0,0] = 10\n", "w_integer8.array [-1,-1] = 11" ] }, { "cell_type": "markdown", "id": "bc95fafc", "metadata": {}, "source": [ "## Type conversion\n", "\n", "All `wolfhece` versions : \n", "\n", "To convert the type of a WolfArray, you have to:\n", "\n", "- create a new WolfArray with the desired type and the same shape as the original one\n", "- copy the data from the original WolfArray to the new one using the `set_array_from_numpy` method, passing tha converted array by Numpy `astype`." ] }, { "cell_type": "code", "execution_count": 5, "id": "08fbfccb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " float32\n", "10.0 \n", "11.0 \n", "1.0 \n" ] } ], "source": [ "# convert the array to a different type (all wolfhece versions)\n", "w3_single = WolfArray(srcheader=w_integer8.get_header(), whichtype=WOLF_ARRAY_FULL_SINGLE)\n", "\n", "w3_single.set_array_from_numpy(w_integer8.array.astype(w3_single.dtype))\n", "\n", "print(w3_single.dtype, w3_single.array.dtype)\n", "print(w3_single.array [0,0], type(w3_single.array [0,0]))\n", "print(w3_single.array [-1,-1], type(w3_single.array [-1,-1]))\n", "print(w3_single.array [0,1], type(w3_single.array [0,1]))" ] }, { "cell_type": "markdown", "id": "231d10ed", "metadata": {}, "source": [ "For wolfhece 2.2.6 and later, you can use the `mold` attribute of the WolfArray class to convert the type of a WolfArray. \n", "\n", "The class will automatically convert the data to the specified type when you set the `whichtype` attribute (for memory, default value is `WOLF_ARRAY_FULL_SINGLE`). \n", "\n", "This is a more convenient way to convert the type of a WolfArray without having to create a new array and copy the data manually." ] }, { "cell_type": "code", "execution_count": 6, "id": "bba69eac", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.2.16\n" ] } ], "source": [ "# convert the array to a different type (wolfhece 2.2.6 and above)\n", "from wolfhece.apps.version import WolfVersion\n", "print(WolfVersion().get_version())\n", "\n", "if WolfVersion().get_version() >= '2.2.6':\n", " w4_single = WolfArray(mold=w_integer8, whichtype=WOLF_ARRAY_FULL_SINGLE)\n", " print(w4_single.dtype, w4_single.array.dtype)\n", " print(w4_single.array [0,0], type(w4_single.array [0,0]))\n", " print(w4_single.array [-1,-1], type(w4_single.array [-1,-1]))\n", " print(w4_single.array [0,1], type(w4_single.array [0,1]))" ] }, { "cell_type": "markdown", "id": "fe9d5930", "metadata": {}, "source": [ "## Representation Space\n", "\n", "Each data type has a different representation space. For example, an array of type `WOLF_ARRAY_FULL_SINGLE` occupies 4 bytes per element, while an array of type `WOLF_ARRAY_FULL_DOUBLE` occupies 8 bytes per element.\n", "\n", "Floating-point numbers are represented using the IEEE 754 standard, which defines the binary representation of floating-point numbers.\n", "\n", "Integers are represented using the standard binary representation, where each bit corresponds to a power of 2.\n", "\n", "The value ranges for each data type are as follows:\n", "\n", "- **`int8`**: -128 to 127\n", "- **`int16`**: -32,768 to 32,767\n", "- **`int32`**: -2,147,483,648 to 2,147,483,647\n", "- **`int64`**: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807\n", "- **`uint8`**: 0 to 255\n", "- **`uint16`**: 0 to 65,535\n", "- **`uint32`**: 0 to 4,294,967,295\n", "- **`float32`**: -3.4028235e+38 to 3.4028235e+38\n", "- **`float64`**: -1.7976931348623157e+308 to 1.7976931348623157e+308\n", "- **`bool`**: 0 or 1\n", "\n", "It is the user's responsibility to ensure that the data stored in the array falls within the limits of the chosen data type's representation space. Exceeding these limits can lead to undefined behavior or calculation errors." ] }, { "cell_type": "code", "execution_count": 7, "id": "c589b7c6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-24 \n" ] } ], "source": [ "w3_single.array [2,2] = 1000.0 # set a value in the new array\n", "w4_int8 = WolfArray(mold=w3_single, whichtype=WOLF_ARRAY_FULL_INTEGER8) # Try to convert to int8\n", "\n", "print(w4_int8.array [2,2], type(w4_int8.array [2,2])) # 1000.0 should be converted to 1000 but the type is int8 so 1000 is not possible" ] }, { "cell_type": "code", "execution_count": 8, "id": "eb66a6e5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int8(-24)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Check the conversion of a \"BAD\" float to int8\n", "import numpy as np\n", "\n", "np.float32(1000.0).astype(np.int8) # 1000.0 should be converted to 1000 but the type is int8 so 1000 is not possible" ] }, { "cell_type": "markdown", "id": "78342418", "metadata": {}, "source": [ "## Memory consumption\n", "\n", "The total memory consumption of a WolfArray is determined by the number of elements in the array and the size of each element, which is defined by the data type. The formula for calculating the total memory consumption is:\n", "\n", "```\n", "total_memory = number_of_elements * size_of_each_element\n", "```\n", "\n", "Where:\n", "- `number_of_elements` is the total number of elements in the array (calculated as the product of the dimensions of the array).\n", "- `size_of_each_element` is the size of each element in bytes, which depends on the data type (e.g., 4 bytes for `float32`, 8 bytes for `float64`, etc.).\n", "\n", "The total memory consumption can be viewed using the `memory_usage` property, which returns the total memory consumption of the WolfArray in bytes.\n", "\n", "As WolfArray uses Numpy masked arrays, the total memory consumption is higher due to the mask array overhead. As the mask is a boolean array, it consumes 1 byte per element. " ] }, { "cell_type": "code", "execution_count": 15, "id": "96f7cae1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "400 bytes for the data\n", "100 bytes for the mask\n", "\n", "\n", "Shape : 10 x 10 \n", "Resolution : 0.0 x 0.0 \n", "Spatial extent : \n", " - Origin : (0.0 ; 0.0) \n", " - End : (0.0 ; 0.0) \n", " - Width x Height : 0.0 x 0.0 \n", " - Translation : (0.0 ; 0.0)\n", "Null value : 0.0\n", "\n", "\n" ] } ], "source": [ "h = header_wolf()\n", "h.shape = (10,10)\n", "a = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_SINGLE)\n", "\n", "print(a.memory_usage, 'bytes for the data')\n", "print(a.memory_usage_mask, 'bytes for the mask')\n", "print('\\n')\n", "print(a)" ] }, { "cell_type": "markdown", "id": "09ed430b", "metadata": {}, "source": [ "Conversion in kilobytes (KB) can be done by dividing the total memory consumption by 1024.\n", "\n", "Conversion in megabytes (MB) can be done by dividing the total memory consumption by 1024^2.\n", "\n", "Conversion in gigabytes (GB) can be done by dividing the total memory consumption by 1024^3." ] } ], "metadata": { "kernelspec": { "display_name": "python3.11", "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.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }