## Lattice Expression Language

Subsections

A boolean mask associated with an image indicates whether a pixel is good (mask value True) or bad (mask value False). If the mask value is bad, then the image pixel is not used for computation (e.g. when finding the mean of the image).

An image can have zero (all pixels are good) or more masks. One mask can be designated as the default mask. By default it will be applied to the image (from Glish, designation of the default mask is handled by the maskhandler function of the Image tool).

When using LEL, the basic behaviour is that the default mask is used. However, by qualifying the image name with a suffix string, it is possible to specify that no mask or another mask should be used. The suffix is a colon followed by the word nomask or the name of the alternative mask.

```  myimage.data
```

The first example uses the default mask (if the image has one). The second example uses no mask (thus all pixels are designated good) and the third example uses mask othermask.

Note that if the image name is enclosed in quotes, the mask name should be enclosed too. It means that a colon cannot be part of an image name.

It is also possible to use a mask from another image like

```  myimage.data:nomask[myotherimage::othermask]
```
This syntax is explained in the section describing regions

We have seen in the previous section that lattices (in this case images) can have an associated mask. These masks are stored with the image - they are persistent.

It is also possible to create transient masks when a LEL expression is executed (dawn, usually). This is done with the operator [] and a boolean expression. For example,

```  sum( lat1[lat1<5 && lat1>10] )
```
creates a mask for lat1 indicating that only its elements fulfilling the boolean condition should be taken into account in the sum function. Note that the mask is local to that part of the expression. So in the expression

```  sum( lat1[lat1<5 && lat1>10] ) + sum(lat1)
```
the second sum function takes all elements into account. Masking can also be applied to more complex expressions and it is recursive.

```  (lat1+lat2)[lat3<lat4]
sum( lat1[lat1<5][lat1>10] )
(lat1 + lat2[lat3<lat4]) [lat1<5]
```
The first example applies the mask generated by the [] operator to the expression lat1+lat2. The second example shows the recursion (which ANDs the masks). It is effectively a (slower) implementation of the first example in this subsection. In the last example, the expression inside the parentheses is only evaluated where the condition [lat1<5] is true and the resulting expression has a mask associated with it.

Please note that it is possible to select pixels on an axis by means of the function INDEXIN (or by the INDEXi IN expression) as shown in the previous section about miscellaneous functions.

As explained in the previous subsections, lattices can have a mask. Examples are a mask of good pixels in an image, a mask created using a boolean condition and the operator [], or a mask defining a region within its bounding box.
A pixel is bad when the image has a mask and when the mask value for that pixel is False. Functions like max ignore the bad pixels.
Note that in a MeasurementSet a False mask value indicates a good visibility. Alas this is a historically grown distinction in radio-astronomy.

Image masks are combined and propagated throughout an expression. E.g. when two lattices are added, the mask of the result is formed by and-ing the masks of the two lattices. That is, the resultant mask is True where the mask of lattice one is true AND the mask of lattice 2 is True. Otherwise, the resultant mask is False.

In general the mask of a subexpression is formed by and-ing the masks of the operands. This is true for e.g. +, *, atan2, etc.. However, there are a few special cases:

• The mask created by operator[condition] is formed by and-ing the condition result, the mask of the result, and the mask of the subexpression where the condition is applied to. For example, suppose lat1 and lat2 each have a mask. Then in
```  sum( lat1[lat2<5] )
```
the sum function will only sum those elements for which the mask of lat1 and lat2 is valid and for which the condition is true.

• The logical AND operator forms the resultant mask by looking at the result and the masks of the operands.

```  lat1[lat1<0 && lat2>0]
```
Let us say both lat1 and lat2 have masks. The operand lat1<0 is true if the mask of lat1 is true and the operand evaluates to true, otherwise it is false. Apply the same rule to the operand lat2 > 0. The AND operator gives true if the left and right operands are both true. If the left operand is false, the right operand is no longer relevant. It is, in fact, 3-valued logic with the values true, false, and undefined.

Thus, the full expression generates a lattice with a mask. The mask is true when the condition in the [] operator is true, and false otherwise. The values of the output lattice are only defined where its mask is true.

• The logical OR operator works the same as the AND operator. If an operand has a true value the other operand can be ignored.

• The mask of the result of the replace function is a copy of the mask of its first operand. The mask of the second operand is not used at all.

• The iif function has three operands. Depending on the condition, an element from the second or third operand has to be taken. The resultant mask is formed by the mask of the condition and-ed with the appropriate elements from the masks of the second or third operand.

• The value function returns the value without a mask, thus it removes the mask from a value. It has the same effect as the image:nomask construction discussed above. However, the value function is more general, because it can also be applied to a subexpression.

• The mask function returns the mask of a value. The returned value is a boolean lattice and has no mask itself. When the value has no mask, it returns a mask consisting of all True values. When applied to an image, it returns its default mask.

Consider the following more or less equivalent examples:

```   value(image1)[mask(image2)]
```
The first two use the default mask of image2 as the mask for image1.
The latter uses mask0 of image2 as the mask for image1. It is equivalent to the first two examples if mask0 is the default mask of image2.

It is possible that the entire mask of a subexpression is false. For example, if the mean of such a subexpression is taken, the result is undefined. This is fully supported by LEL, because a scalar value also has a mask associated with it. One can see a masked-off scalar as a lattice with an all false mask. Hence an operation involving an undefined scalar results in an undefined scalar. The following functions act as described below on fully masked-off lattices:

• MEDIAN, MEAN, VARIANCE, STDDEV, AVDEV, MIN, MAX
result in an undefined scalar:
• NELEMENTS, NTRUE, NFALSE, SUM
result in a scalar with value 0.
• ANY
results in a scalar with value F.
• ALL
results in a scalar with value T.
• LENGTH, NDIM
ignore the mask because only the shape of the lattice matters.

You should also be aware that if you remove a mask from an image, the values of the image that were previously masked bad may have values that are meaningless.