In [119]: np.array([1,0,2,0],dtype=bool)
Out[119]: array([ True, False, True, False])
In [120]: np.array([1, False, 2, False, []])
Out[120]: array([1, False, 2, False, list([])], dtype=object)
Note the dtype. With object dtype, the elements of the array are Python objects, just like they are in the source list.
In the first case the array dtype is boolean. The elements represent boolean values, but they are not, themselves, Python True/False objects. Strictly speaking Out[119] does not contain np.bool_ objects. Out[119][1] is type bool_, but that's the result of the 'unboxing'. It's what ndarray indexing produces when you ask for an element. (This 'unboxing' distinction is true for all non-object dtypes.)
Normally we don't create dtype objects, preferring np.array(True), but to follow your example:
In [124]: np.bool_(True)
Out[124]: True
In [125]: type(np.bool_(True))
Out[125]: numpy.bool_
In [126]: np.bool_(True) is True
Out[126]: False
In [127]: type(True)
Out[127]: bool
is is a strict test, not just for equality, but identity. Objects of different classes don't satisfy a is test. Objects can satisfy the == test without satisfying the is test.
Let's play with the object dtype array:
In [129]: np.array([1, False, 2, np.bool_(False), []])
Out[129]: array([1, False, 2, False, list([])], dtype=object)
In [130]: [i is False for i in _]
Out[130]: [False, True, False, False, False]
In the Out[129] display, the two False objects display the same, but the Out[130] test shows they are different.
To focus on your questions.
np.bool_(False)is a unique object, but distinct fromFalse. As you note it has many of the same attributes/methods asnp.array(False).If the array dtype is
boolit does not contain Pythonboolobjects. It doesn't even containnp.bool_objects. However indexing such an array will produce abool_. And applyingitem()to that in turn produces a Pythonbool.If the array object dtype, it most likely will contain Python
bool, unless you've taken special steps to includebool_objects.
In [119]: np.array([1,0,2,0],dtype=bool)
Out[119]: array([ True, False, True, False])
In [120]: np.array([1, False, 2, False, []])
Out[120]: array([1, False, 2, False, list([])], dtype=object)
Note the dtype. With object dtype, the elements of the array are Python objects, just like they are in the source list.
In the first case the array dtype is boolean. The elements represent boolean values, but they are not, themselves, Python True/False objects. Strictly speaking Out[119] does not contain np.bool_ objects. Out[119][1] is type bool_, but that's the result of the 'unboxing'. It's what ndarray indexing produces when you ask for an element. (This 'unboxing' distinction is true for all non-object dtypes.)
Normally we don't create dtype objects, preferring np.array(True), but to follow your example:
In [124]: np.bool_(True)
Out[124]: True
In [125]: type(np.bool_(True))
Out[125]: numpy.bool_
In [126]: np.bool_(True) is True
Out[126]: False
In [127]: type(True)
Out[127]: bool
is is a strict test, not just for equality, but identity. Objects of different classes don't satisfy a is test. Objects can satisfy the == test without satisfying the is test.
Let's play with the object dtype array:
In [129]: np.array([1, False, 2, np.bool_(False), []])
Out[129]: array([1, False, 2, False, list([])], dtype=object)
In [130]: [i is False for i in _]
Out[130]: [False, True, False, False, False]
In the Out[129] display, the two False objects display the same, but the Out[130] test shows they are different.
To focus on your questions.
np.bool_(False)is a unique object, but distinct fromFalse. As you note it has many of the same attributes/methods asnp.array(False).If the array dtype is
boolit does not contain Pythonboolobjects. It doesn't even containnp.bool_objects. However indexing such an array will produce abool_. And applyingitem()to that in turn produces a Pythonbool.If the array object dtype, it most likely will contain Python
bool, unless you've taken special steps to includebool_objects.
There is some confusion with the variables, what is happening is a "confusion" between the module and python, use isinstance(variable, type) to check what is it an if is usable on your code.
Creating a single variable as a bool variable works just fine, python reeds it correctly:
np_bool = np.bool(True)
py_bool = True
print(isinstance(np_bool, bool)) # True
print(isinstance(py_bool, bool)) # True
But with lists it can be different, numpy bool lists are not bool values on a list as you can see in this example:
# Regular list of int
arr0 = [-2, -1, 0, 1, 2]
# Python list of bool
arr1 = [True, False, True, False]
# Numpy list of bool, from int / bool
arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)
arr3_b = np.array([True, False, True, False], dtype=bool)
print(isinstance(arr0[0], int)) # True
print(isinstance(arr1[0], bool)) # True
print(isinstance(arr3_a[0], bool)) # False
print(isinstance(arr3_b[0], bool)) # False
In order to use a variable from the numpy list is required a conversion with bool()
arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)
x = (bool(arr3_a[0]) is True)
print(isinstance(x, bool)) # True
Quick example of use:
arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)
for c in range(0, len(arr3_a)):
if ( bool(arr3_a[c]) == True ):
print(("List value {} is True").format(c))
else:
print(("List value {} is False").format(c))
Yes, you can write a one bit raster with rasterio*.
You need to:
- write to a format that supports a 1bit dataset, such as GeoTIFF;
- ensure your numpy array is
np.uint8/ubyteso rasterio doesnt raise theTypeError: invalid dtype: 'bool'exception; and - pass the
NBITS=1creation option to tell the underlying GDAL GeoTIFF driver to create a one bit file.
import numpy as np
import rasterio as rio
with rio.open('test_byte.tif') as src:
data = src.read()
profile = src.profile
with rio.open('test_bit.tif', 'w', nbits=1, **profile) as dst:
dst.write(data)
# If your array is not a byte dtype, you need to cast it as ubyte/uint8
# dst.write(data.astype(np.uint8))
Checking output file size
$ ls -sh test_bit.tif
228K test_bit.tif
$ ls -sh test_byte.tif
1.8M test_byte.tif
$ gdalinfo test_bit.tif
Driver: GTiff/GeoTIFF
Files: test_bit.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x41 Type=Byte, ColorInterp=Palette
Image Structure Metadata:
NBITS=1
$ gdalinfo test_byte.tif
Driver: GTiff/GeoTIFF
Files: test_byte.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x5 Type=Byte, ColorInterp=Gray
If you call rasterio.dtypes.check_dtype(np.bool_) you'll see that it's not a known dtype, because gdal doesn't support a true 1-bit dtype. GDT_Byte is the smallest. The list that rasterio is checking against is:
dtype_fwd = {
0: None, # GDT_Unknown
1: ubyte, # GDT_Byte
2: uint16, # GDT_UInt16
3: int16, # GDT_Int16
4: uint32, # GDT_UInt32
5: int32, # GDT_Int32
6: float32, # GDT_Float32
7: float64, # GDT_Float64
8: complex_, # GDT_CInt16
9: complex_, # GDT_CInt32
10: complex64, # GDT_CFloat32
11: complex128} # GDT_CFloat64
uint8 and int8 are mapped to the ubyte, as seen here:
https://github.com/mapbox/rasterio/blob/master/rasterio/dtypes.py#L29-L45
numpy.array(old_matrix, dtype=bool)
Alternatively,
old_matrix != 0
The first version is an elementwise coercion to boolean. Analogous constructs will work for conversion to other data types. The second version is an elementwise comparison to 0. It involves less typing, but ran slightly slower when I timed it. Which you use is up to you; I'd probably decide based on whether "convert to boolean" or "compare to 0" is a better conceptual description of what I'm after.
You should use array.astype(bool) (or array.astype(dtype=bool)). Works with matrices too.