Reading data from boolean OLCI product Masks using snappy


Hi Again,

I’m trying to read in the Masks present in a subset OLCI reflectance product.
I first load the mask group:
Masks = sub_product.getGroup(‘Masks’)
I then access the mask I am interested in:
glintMask = Masks.get(‘quality_flags_sun_glint_risk’)

However this return an object of type org.esa.snap.core.datamodel.ProductNode. This type does not have the readPixel method as for object types org.esa.snap.core.datamodel.Band. This is an example of what I’d like to do but for the tie points:
lon = rp.getTiePointGrid(‘TP_longitude’).readPixels(0, 0, w, h, np.zeros(w * h, np.float32))

Thus I am struggling to read the data from the [boolean] Masks. Can you help to point to methods to read in the boolean masks?



Instead of getGroup(‘GroupName’) it is besser to use getMaskGroup()
This returns a ProductNodeGroup which will give you the masks you want.
The mask will have integer values, either 0 or 255


Hi Marko,

I’m still struggling to read in the Mask data to a numpy array.

Masks = sub_product.getMaskGroup(‘Masks’) > org.esa.snap.core.datamodel.ProductNodeGroup
landMask = Masks.get(‘quality_flags_land’) > org.esa.snap.core.datamodel.ProductNode
I don’t see any methods to readPixels for a ProductNode object. Can you help?

I know I can read the masks using flag codings from the Band ‘quality_flags’, but it would be easier I think to read them in directly from the boolean Masks group if possible.


If you let landMask be org.esa.snap.core.datamodel.Mask you have the readPixels() available. The values are integer (0|255) and not boolean.


HI Marko,

Sorry, but I can’t seem to be able to work out how to create the org.esa.snap.core.datamodel.Mask class to access the mask layer. Please would you be able to provide some more instructions how to turn the org.esa.snap.core.datamodel.ProductNode object into the org.esa.snap.core.datamodel.Mask object?



Hi Marko, again, any advice on which method I can use from org.esa.snap.core.datamodel.Product (or other class object) to access an org.esa.snap.core.datamodel.mask object appreciated, .getband does not work for masks as far as I can tell… Thanks again!


After searching for days, I settled on a work around by reading in the L1 flag band, then accessing the flags using bitget function. However, it may be an issue that the mask layers are not read accessible… since I found no method to do so…

mask_group = product.getMaskGroup()

mymask = mask_group.get("mymask")

mymaskdata = ... # some numpy array allocation of type int32 and shape (height, width)
mymask.readPixels(0, 0, width, height, mymaskdata)



Thanks Norman, however:

mask_group = product.getMaskGroup()
mymask = mask_group.get(‘quality_flags_land’)
mymask.readPixels(0, 0, width, height, np.zeros((h , w), np.float32))

Traceback (most recent call last):
File “”, line 1, in
mymask.readPixels(0, 0, width, height, np.zeros((h , w), np.float32))
AttributeError: ‘org.esa.snap.core.datamodel.ProductNode’ object has no attribute ‘readPixels’

Likely a bug.


It seems that mymask is interpreted as a ProductNode which does not have the readPixels methods.
Can you make it org.esa.snap.core.datamodel.Mask?


Was this ever resolved? When I try to make the node a mask as for example:

product = snappy.ProductIO.readProduct(product_path)
mask_group = product.getMaskGroup()
mymask = mask_group.get('quality_flags_land')
h = product.getSceneRasterHeight()
w = product.getSceneRasterWidth()
data = np.zeros(w * h, np.uint32)
im = snappy.Mask.getSourceImage(mymask)
im.getData().getPixels(0,0,w,h, data)
data.shape = h, w

data remains zeros


Mmmh, strange. Didn’t know that this is not working.

What happens if you try this:
mymask.readPixels(0,0,w,h, data)

Maybe it is better to read from the mask directly and not from the underlying image.


This has the problem that @MarkWilliamMatthews was describing:

AttributeError: 'org.esa.snap.core.datamodel.ProductNode' object has no attribute 'readPixels'


Ah ok. The reason for the error is that Python doesn’t know that mymask is a Mask.
In Java mask_group.get(...) returns a ProductNode<Mask>. This information gets lost in Python.
It should be possible to cast it to a Mask.

from snappy import Mask
my_real_mask = jpy.cast(myMask, Mask)

Afterwards it should be possible to call readPixels on my_real_mask.


Works perfectly, thanks