WolfArray - Data type
A WolfArray
can store any type of data, including:
int
(integer8, integer16, integer32)float
(floating point number, 32-bit or 64-bit)bool
(boolean/logical)
WOLF types are defined as follows (for compatibility with Fortran and VB6):
WOLF_ARRAY_HILLSHAPE = -1
WOLF_ARRAY_FULL_SINGLE = 1
WOLF_ARRAY_FULL_DOUBLE = 2
WOLF_ARRAY_SYM_DOUBLE = 12
WOLF_ARRAY_FULL_LOGICAL = 4
WOLF_ARRAY_CSR_DOUBLE = 5
WOLF_ARRAY_FULL_INTEGER = 6
WOLF_ARRAY_FULL_SINGLE_3D = 7
WOLF_ARRAY_FULL_INTEGER8 = 8
WOLF_ARRAY_FULL_UINTEGER8 = 88
Equivalent Numpy types can be obtained using the dtype
attribute.
[1]:
import _add_path
from wolfhece.wolf_array import WolfArray, WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_DOUBLE, header_wolf
Using “whichtype” during WolfArray creation
whichtype
is a parameter that specifies the type of data to be stored in the WolfArray.’
[2]:
h = header_wolf()
h.shape = (10,10)
w_single = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_SINGLE)
w_double = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_DOUBLE)
w_integer8 = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_INTEGER8)
Get equivalent Numpy type
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.
[3]:
# check the dtype of the array and the WolfArray object
print(w_single.dtype, w_single.array.dtype)
print(w_double.dtype, w_double.array.dtype)
print(w_integer8.dtype, w_integer8.array.dtype)
<class 'numpy.float32'> float32
<class 'numpy.float64'> float64
<class 'numpy.int8'> int8
Modifying Values in a WolfArray
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.
Key Considerations:
Ensure that the modifications maintain the same data type as the original array.
The memory layout must remain contiguous.
[4]:
# Modify some values in the array
w_integer8.array [0,0] = 10
w_integer8.array [-1,-1] = 11
Type conversion
All wolfhece
versions :
To convert the type of a WolfArray, you have to:
create a new WolfArray with the desired type and the same shape as the original one
copy the data from the original WolfArray to the new one using the
set_array_from_numpy
method, passing tha converted array by Numpyastype
.
[5]:
# convert the array to a different type (all wolfhece versions)
w3_single = WolfArray(srcheader=w_integer8.get_header(), whichtype=WOLF_ARRAY_FULL_SINGLE)
w3_single.set_array_from_numpy(w_integer8.array.astype(w3_single.dtype))
print(w3_single.dtype, w3_single.array.dtype)
print(w3_single.array [0,0], type(w3_single.array [0,0]))
print(w3_single.array [-1,-1], type(w3_single.array [-1,-1]))
print(w3_single.array [0,1], type(w3_single.array [0,1]))
<class 'numpy.float32'> float32
10.0 <class 'numpy.float32'>
11.0 <class 'numpy.float32'>
1.0 <class 'numpy.float32'>
For wolfhece 2.2.6 and later, you can use the mold
attribute of the WolfArray class to convert the type of a WolfArray.
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
).
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.
[6]:
# convert the array to a different type (wolfhece 2.2.6 and above)
from wolfhece.apps.version import WolfVersion
print(WolfVersion().get_version())
if WolfVersion().get_version() >= '2.2.6':
w4_single = WolfArray(mold=w_integer8, whichtype=WOLF_ARRAY_FULL_SINGLE)
print(w4_single.dtype, w4_single.array.dtype)
print(w4_single.array [0,0], type(w4_single.array [0,0]))
print(w4_single.array [-1,-1], type(w4_single.array [-1,-1]))
print(w4_single.array [0,1], type(w4_single.array [0,1]))
2.2.16
Representation Space
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.
Floating-point numbers are represented using the IEEE 754 standard, which defines the binary representation of floating-point numbers.
Integers are represented using the standard binary representation, where each bit corresponds to a power of 2.
The value ranges for each data type are as follows:
``int8``: -128 to 127
``int16``: -32,768 to 32,767
``int32``: -2,147,483,648 to 2,147,483,647
``int64``: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
``uint8``: 0 to 255
``uint16``: 0 to 65,535
``uint32``: 0 to 4,294,967,295
``float32``: -3.4028235e+38 to 3.4028235e+38
``float64``: -1.7976931348623157e+308 to 1.7976931348623157e+308
``bool``: 0 or 1
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.
[7]:
w3_single.array [2,2] = 1000.0 # set a value in the new array
w4_int8 = WolfArray(mold=w3_single, whichtype=WOLF_ARRAY_FULL_INTEGER8) # Try to convert to int8
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
-24 <class 'numpy.int8'>
[8]:
# Check the conversion of a "BAD" float to int8
import numpy as np
np.float32(1000.0).astype(np.int8) # 1000.0 should be converted to 1000 but the type is int8 so 1000 is not possible
[8]:
np.int8(-24)
Memory consumption
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:
total_memory = number_of_elements * size_of_each_element
Where:
number_of_elements
is the total number of elements in the array (calculated as the product of the dimensions of the array).size_of_each_element
is the size of each element in bytes, which depends on the data type (e.g., 4 bytes forfloat32
, 8 bytes forfloat64
, etc.).
The total memory consumption can be viewed using the memory_usage
property, which returns the total memory consumption of the WolfArray in bytes.
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.
[15]:
h = header_wolf()
h.shape = (10,10)
a = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_SINGLE)
print(a.memory_usage, 'bytes for the data')
print(a.memory_usage_mask, 'bytes for the mask')
print('\n')
print(a)
400 bytes for the data
100 bytes for the mask
Shape : 10 x 10
Resolution : 0.0 x 0.0
Spatial extent :
- Origin : (0.0 ; 0.0)
- End : (0.0 ; 0.0)
- Width x Height : 0.0 x 0.0
- Translation : (0.0 ; 0.0)
Null value : 0.0
Conversion in kilobytes (KB) can be done by dividing the total memory consumption by 1024.
Conversion in megabytes (MB) can be done by dividing the total memory consumption by 1024^2.
Conversion in gigabytes (GB) can be done by dividing the total memory consumption by 1024^3.