Bit Reader

Encode/Decode a set of bits

Initializes with parameter options, which must be a dictionary with the following format:

  • keys must be a str with the bits places, example: '0-1' means bit 0 and bit 1

  • values must be a dictionary with the bit value as the key and the category (str) as value. Categories must be unique.

  • Encode: given a category/categories return a list of possible values

  • Decode: given a value return a list of categories

Example

MOD09 (http://modis-sr.ltdri.org/guide/MOD09_UserGuide_v1_3.pdf) (page 28, state1km, 16 bits):


In [1]:
import ee
ee.Initialize()

In [2]:
from geetools import bitreader, cloud_mask

In [3]:
options = {
 '0-1': {0:'clear', 1:'cloud', 2:'mix'},  # cloud state
 '2-2': {0: 'no_shadow', 1:'shadow'},  # cloud shadow (bit 0 is not needed)
 '6-7': {0:'climatology', 1:'low', 2:'average', 3:'high'}  # land/water flag
 }

In [4]:
reader = bitreader.BitReader(options, 16)

Internally it computes a dict with

  • bit_length (length of the group of bits)
  • lshift (left shift)
  • shifted (shifted places)

In [5]:
reader.info


Out[5]:
{'clear': {'bit_length': 2, 'lshift': 0, 'shifted': 0},
 'cloud': {'bit_length': 2, 'lshift': 0, 'shifted': 1},
 'mix': {'bit_length': 2, 'lshift': 0, 'shifted': 2},
 'no_shadow': {'bit_length': 1, 'lshift': 2, 'shifted': 0},
 'shadow': {'bit_length': 1, 'lshift': 2, 'shifted': 1},
 'climatology': {'bit_length': 2, 'lshift': 6, 'shifted': 0},
 'low': {'bit_length': 2, 'lshift': 6, 'shifted': 1},
 'average': {'bit_length': 2, 'lshift': 6, 'shifted': 2},
 'high': {'bit_length': 2, 'lshift': 6, 'shifted': 3}}

In [6]:
print('bit length', reader.bit_length)


bit length 16

DECODE ONE VALUE


In [7]:
value = 204
bits = reader.getBin(value)
print('204:', bits)


204: 11001100

In [8]:
reader.decode(204)


Out[8]:
['clear', 'shadow', 'high']

MATCH ONE VALUE


In [9]:
reader.match(204, 'cloud')


Out[9]:
False

In [10]:
reader.match(204, 'shadow')


Out[10]:
True

ENCODE A VALUE (EXCLUSIVELLY)

In this case, shadow is 00000100 (4) and not 00000101 (5)


In [11]:
reader.encode('shadow')


Out[11]:
4

In [12]:
reader.encode('clear')


Out[12]:
0

In [13]:
reader.encode('no_shadow')


Out[13]:
0

ENCODE A VALUE (ALL)

This will get all values (all combinations where the bit is set)


In [14]:
print(reader.encodeOne('shadow')[0:100])


[4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31, 36, 37, 38, 39, 44, 45, 46, 47, 52, 53, 54, 55, 60, 61, 62, 63, 68, 69, 70, 71, 76, 77, 78, 79, 84, 85, 86, 87, 92, 93, 94, 95, 100, 101, 102, 103, 108, 109, 110, 111, 116, 117, 118, 119, 124, 125, 126, 127, 132, 133, 134, 135, 140, 141, 142, 143, 148, 149, 150, 151, 156, 157, 158, 159, 164, 165, 166, 167, 172, 173, 174, 175, 180, 181, 182, 183, 188, 189, 190, 191, 196, 197, 198, 199]

In [15]:
print(reader.encodeOne('cloud')[0:100])


[1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397]

ENCODE AND


In [16]:
print(reader.encodeAnd('cloud', 'shadow')[0:100])


[5, 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 149, 157, 165, 173, 181, 189, 197, 205, 213, 221, 229, 237, 245, 253, 261, 269, 277, 285, 293, 301, 309, 317, 325, 333, 341, 349, 357, 365, 373, 381, 389, 397, 405, 413, 421, 429, 437, 445, 453, 461, 469, 477, 485, 493, 501, 509, 517, 525, 533, 541, 549, 557, 565, 573, 581, 589, 597, 605, 613, 621, 629, 637, 645, 653, 661, 669, 677, 685, 693, 701, 709, 717, 725, 733, 741, 749, 757, 765, 773, 781, 789, 797]

DECODE AN IMAGE


In [17]:
import ee

In [18]:
import ipygee as ui

In [19]:
Map = ui.Map()
Map.show()



In [20]:
modcol = ee.ImageCollection('MODIS/006/MOD09GA').sort('system:time_start', False)

In [21]:
mod = ee.Image(modcol.first())

BANDS


In [22]:
red = 'sur_refl_b01'
green = 'sur_refl_b04'
blue = 'sur_refl_b03'

In [23]:
qa = 'state_1km'

In [24]:
qa_mask = mod.select(qa)

In [25]:
Map.addLayer(mod, {'bands':[red, green, blue], 'min':0, 'max':5000}, 'Original')

In [26]:
Map.addLayer(qa_mask, {'min':0, 'max':reader.max}, 'QA')

APPLY THE BitReader TO THE BAND THAT HOLDS THE BIT INFORMATION


In [27]:
mask = reader.decodeImage(mod, qa)

In [28]:
Map.addLayer(mask.select(['cloud']), {'min':0, 'max':1}, 'Clouds')

BitReader INFORMATION FOR KNOW COLLECTIONS AVAILABLE IN geetools.cloud_mask MODULE


In [29]:
from geetools import cloud_mask

In [30]:
state1km = cloud_mask.BITS_MODIS09GA

In [31]:
state1km


Out[31]:
{'0-1': {0: 'clear', 1: 'cloud', 2: 'mix'},
 '2': {1: 'shadow'},
 '8-9': {1: 'small_cirrus', 2: 'average_cirrus', 3: 'high_cirrus'},
 '13': {1: 'adjacent'},
 '15': {1: 'snow'}}

In [ ]: