Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
image_expression_null_value_handling [2022/08/20 19:28]
admin
image_expression_null_value_handling [2022/08/22 04:54] (current)
admin [Null Evaluation]
Line 5: Line 5:
   * The entire expression is one single expression resulting in one single value. ​   * The entire expression is one single expression resulting in one single value. ​
  
-  * Everything ​ is an expression and produces one single value. So, even an ''​if then else'' ​is just one expression resulting in one single value. Therefore, ​ you can sum the results of two separate ​''​if then else''s like ''​(if the  else) + (if then else)''​. ​ Since even the test clause of an ''​if then else'' ​is an expression, you can also replace that with another ​''​if then else''​. Example: ''​if (if i1 > 0 then 1 else i2) then i2 else 1 + i3''​+  * Everything ​ is an expression and produces one single value. So, even an if-then-else is just one expression resulting in one single value. Therefore, ​ you can sum the results of two separate if-then-else's like ''​(if the  else) + (if then else)''​. ​ Since even the test clause of an if-then-else is an expression, you can also replace that with another if-then-else. Example: ''​if (if i1 > 0 then 1 else i2) then i2 else 1 + i3''​
  
-  * The ''​if then else'' ​test assumes that 0 is false and any non-zero value is true.+  * The if-then-else test assumes that 0 is false and any non-zero value is true.
  
 ===== Null Evaluation ===== ===== Null Evaluation =====
Line 13: Line 13:
   * Every time the expression being evaluated results in null, the entire ​ expression becomes null. So, ''​i1 + null''​ will always be null since  something ''​+''​ null is always null.   * Every time the expression being evaluated results in null, the entire ​ expression becomes null. So, ''​i1 + null''​ will always be null since  something ''​+''​ null is always null.
  
-  * The only operators that can contain the //​destructive power// of a null value are ''​isnull(  expression )''​ or ''​expression1 ? expression2'':​ +  * The only operators that can contain the //​destructive power// of a null value are ''​isNull(  expression )''​ or ''​expression1 ? expression2'':​ 
-    - ''​isnull( expression )''​ evaluates the expression and results 1 if the ''​expression''​ evaluates to null, and 0 otherwise.+    - ''​isNull( expression )''​ evaluates the expression and results 1 if the ''​expression''​ evaluates to null, and 0 otherwise.
     - ''​expression1 ​ ? expression2''​ evaluates the ''​expression1''​ and, if the result is  non-null, returns that value. Otherwise, it evaluates ''​expression2''​ and returns the resulting value as its own result.     - ''​expression1 ​ ? expression2''​ evaluates the ''​expression1''​ and, if the result is  non-null, returns that value. Otherwise, it evaluates ''​expression2''​ and returns the resulting value as its own result.
  
   * Null can come from an image, but it can also be produced by some other  events, such as dividing by zero, failing to find a key in a lookup ​ table etc.   * Null can come from an image, but it can also be produced by some other  events, such as dividing by zero, failing to find a key in a lookup ​ table etc.
  
-  * If the ''​if then else'' ​test evaluates to null, the entire ​''​if then else'' ​evaluates to null. Example:+  * If the if-then-else test evaluates to null, the entire if-then-else evaluates to null. Example:
  
      * ''​(if (i1/3 > 9) then i2 else 1 + i3) + 10'':​      * ''​(if (i1/3 > 9) then i2 else 1 + i3) + 10'':​
-        - If ''​i1''​ is null, ''​i1/​3''​ is also null, and ''​i1/​3 > 9''​ also becomes null. Therefore, the ''​if then else'' ​test is null and the entire ​''​if then else'' ​is null. +        - If ''​i1''​ is null, ''​i1/​3''​ is also null, and ''​i1/​3 > 9''​ also becomes null. Therefore, the if-then-else test is null and the entire if-then-else is null. 
         - Now, null is being added to 10, and that also becomes null.         - Now, null is being added to 10, and that also becomes null.
  
      * ''​( (if (i1/3 > 9) then i2 else 1 + i3) + 10 ) ? 20''​ -- Note that we are using the operator ''?''​ now:      * ''​( (if (i1/3 > 9) then i2 else 1 + i3) + 10 ) ? 20''​ -- Note that we are using the operator ''?''​ now:
-        - If ''​i1''​ is null, ''​i1/​3''​ is also null, and ''​i1/​3 > 9''​ also becomes null. Therefore, the ''​if then else'' ​test is null and the entire ​''​if then else'' ​is null. +        - If ''​i1''​ is null, ''​i1/​3''​ is also null, and ''​i1/​3 > 9''​ also becomes null. Therefore, the if-then-else test is null and the entire if-then-else is null. 
         - Then, null is being added to 10, and that also becomes null.         - Then, null is being added to 10, and that also becomes null.
         - Now, null is being caught by the expression ''​null ? 20'',​ since the ''​if then else + 10''​ is null, and the result is 20.         - Now, null is being caught by the expression ''​null ? 20'',​ since the ''​if then else + 10''​ is null, and the result is 20.
  
-The  null evaluation mechanism allows us to write short expressions like ''​i1 + 10''​ to add 10 to every //valid cell// of the ''​i1''​ map, or ''​i1 * i2''​ to  multiply two maps. If one of the map cells is null, the result is null, so in the last example, we are basically just multiplying the corresponding cells where the  two values are valid: ​**everything else will be null**.+The null evaluation mechanism allows us to write short expressions like ''​i1 + 10''​ to add 10 to every //valid cell// of the ''​i1''​ map, or ''​i1 * i2''​ to  multiply two maps. If one of the map cells is null, the result is null, so in the last example, we are basically just multiplying the corresponding cells where the  two values are valid: ​//everything else will be null//.
  
-If we  want to treat all null values as values 1s, in the previous expression, we can write ''​(i1 ? 1) * (i2 ? 1)''​. We can also use the more complicated form using the ''​if then else'' ​to achieve the same result+If we  want to treat all null values as values 1s, in the previous expression, we can write ''​(i1 ? 1) * (i2 ? 1)''​. We can also use the more complicated form using the if-then-else to achieve the same result ​such as ''​(if isNull(i1) then 1 else i1) * (if isNull(i2) then 1 else i2)'',​ or even 
 +  if isNull(i1) and isNull(i2) then 1 
 +  else if not isNull(i1) and not isNull(i2) then i1*i2 
 +  else if not isNull(i1) and isNull(i2) then i1 
 +  else i2
  
-  ​(if isnull(i1) then 1 else i1) * (if isnull(i2) then 1 else i2),+If you need to retrieve the number corresponding to an image null value, you can use the ''​nulliX )''​ expression. For instance, ''​null(i1)''​ returns the number corresponding to the null value of image ''​i1''​. So if, so some reason, you need to retrieve the image value or its corresponding numeric null value, you can use ''​i1 ? null(i1)''​ or ''​if isnull(i1) then null(i1then i1''​. Note that ''​null(i1)''​ is very different from expression ''​null'',​ since ''​null(i1)''​ always returns a valid numeric value and ''​null''​ returns a special construct that, if not containedinvalidates the expression evaluation producing null as a result.
  
-or+===== Proper Way of Testing for Image Values -- Guarding Against Null Values =====
  
-  ​if isnull(i1) and isnull(i2) ​then +Lets assume that we want to replace all occurrences of a given valid value in a image with some other valid valid: ''​if i1 = 2 then 10 else i1''​. Since we are not explicitly guarding the if-then-else test against null, the expression is internally equivalent to ''​if isNull(i1) then null else if i1 = 2 then 10 else i1''​. So, simply using the most compact if-then-else definition works as expected. 
-  ​else if not isnull(i1) and not isnull(i2) then i1*i2 + 
-  else if not isnull(i1) and isnull(i2) then i1 +Now, lets assume the we want do combine two images, a landscape map and road map, as a single map, where roads in the road map are represent by the value 1 and everything ​else is represented using the null value. Assuming the ''​i1''​ is the landscape map and ''​i2''​ is the road map, we might be tempted to write an expression as ''​if i2 = 1 then 1 else i1''​. Unfortunately that is not going to work, since the expression is internally equivalent to ''​if isNull(i2) then null else if i2 = 1 then 1 else i1''​ (we not guarding against null values). As you can see, all occurrences of null values on the road map will be replicated in the output map.
-  ​else i2+
  
-If you need to retrieve ​the number corresponding to image null value, you can use the ''​null( iX )'' ​expression. For instance, ''​null(i1)''​ returns the number corresponding ​to the null value of image ''​i1''​. So if, so some reason, you need to retrieve ​the image value or its corresponding numeric ​null value, you can use ''​i1 ? null(i1)''​ or ''​if ​isnull(i1) then null(i1) then i1''​. ​Note that ''​null(i1)'' ​is very different from expression ''​null'',​ since ''​null(i1)''​ always returns a valid numeric value and ''​null''​ returns a special construct that, if not containedinvalidates ​the expression evaluation producing ​null as a result.+So, the proper way of doing the calculation is using a ''​isNull( iX )''​ to protect ​the if-then-else test against ​the null''​if ​not isNull(i2and i2 = 1 then 1 else i2''​. ​Now we only test for the value in the road map if we are sure that value is not going to contaminate the whole if-then-elseturning ​the result into null.