ProSEM In Action

Formulas 3 - Handling Different Feature Types and Errors


This example demonstrates how to make ProSEM formulas that work in projects with mixed Feature Types, for example circles and lines in the same image.  It also shows some techniques for avoiding errors in formula evaluation, and introduces some more advanced formula capabilities such as loops.


  • Handling different Feature Types differently in formulas
  • Checking for errors, and giving error messages

Measurement Example: Photonic Crystal Features

In this example, features in this photonic crystal pattern will be measured and analyzed.

A measurement is setup for the holes to measure and fit an Ellipse, by selecting the Feature Type as Ellipse and the Polarity as Hole. The desired analysis is to compute the Ellipticity, just as in the earlier example. As in that example, the formula setup is:

In ProSEM, all formulas are global, meaning all formulas are calculated for all measured objects. So when all holes in this image are measured, this ellipticity is automatically calculated for each ellipse.

and the Circles & Ellipses data table looks like this, with an ellipticity for each ellipse:

Mixed Feature Types

But what happens when the trench in the middle is also measured? A Line Feature type has no MajorDiameter or MinorDiameter, which are two values necessary for computing an ellipticity. So ProSEM gives the ellipticity the value of "error".

And these same "error" values are in the Lines & Spaces data table:

This is not especially a problem, but it is perhaps unsightly. But this can be handled within the formula to have a different value displayed as the formula result. To do so, a JavaScript operator instanceof and the ProSEM feature type identifier objects will be used to construct different values for different feature types. Here is an enhanced version of the ellipticity formula, which uses a conditional if to choose different values depending on the Feature Type of the measurement being evaluated.

if (this instanceof MetrologyEllipse) {
sqrt(1 - (MinorDiameter / 2) / (MajorDiameter / 2))
} else {
"Not an ellipse."

Here, this is a JavaScript identifier for the measurement being evaluated, instanceof is a standard JavaScript operator which evaluates true or false depending on whether the first object has a property of the second object; or to put it another way, here the expression is true if the feature evaluated is an Ellipse, and is false otherwise.  So in a project, the ellipticity will only be calculated for ellipse features, and all other features and objects will result in the string "Not an ellipse." For ellipses, the results are just as above, but now for a line measurement, the result is:

A friendly and more meaningful message than the generic "error".

Even More Specificity

Formulas are also evaluated for the image object, so a value is displayed when an image name is selected in the images panel. In this example so far, selecting an image would result in the same values being displayed, either "error" or after the enhanced formula was defined, "Not an ellipse", since an image is not an ellipse object. Just as the enhanced formula above made a decision based on the kind of object that was being evaluated, an additional check can be added to provide a different answer if an image is selected in the tree. In this example, when an image is selected, the value displayed will be the average ellipticity of all ellipses in that image, or an appropriate message is not ellipses have been measured and stored.

if (this instanceof MetrologyEllipse) {
    sqrt(1 - (MinorDiameter / 2) / (MajorDiameter / 2));
} else if (this instanceof Image) {
    var eCount = 0;
    var eSum = 0;
    for (var imageGroup = 0; imageGroup < this.length; imageGroup++) {
        for (var groupObject = 0; groupObject < image[imageGroup].length; groupObject++) {
            if (image[imageGroup][groupObject] instanceof MetrologyEllipse) {
                eCount += 1;
                eSum += sqrt(1 - (image[imageGroup][groupObject].MinorDiameter / 2) / (image[imageGroup][groupObject].MajorDiameter / 2));
        } // end for groupObject loop (all objects in this group have been processed)
    } // end imageGroup loop (all groups in this image have been processed)
    if (eCount == 0) {
        "Error: No ellipses measured."
    } else {
        "Img Avg Ellip=" + (eSum / eCount).toFixed(4);
} else {
    "Not an ellipse."

The formula code is mostly the same, but now a new section is added for if the object being evaluated is an image. For an image, the formula is a bit more complex, because the formula needs to step through each group in the image, and for each group look at each measured feature in that group. This results in the nested for loops, for each group and then for each feature within each group. If the feature is an ellipse, then the ellipticity is calculated as before, and the value summed to later compute the average ellipticity. If the measured feature is not an ellipse, then nothing happens and the next feature in sequence is evaluated. One additional conditional nicely handles the condition if there were no ellipses in the image by returning an error message as the value -- without this extra condition, there would be a less friendly JavaScript math error from trying to divide by 0 when computing the average.

Note that in this example, for an image the value returned is a String value type, with some text and then the numeric value shown to four decimal places (from the .toFixed method). Of course, the numeric average could also have been returned, but perhaps not as clear without the text label.

And with this addition, there are three possible results for the Ellipticity variable, depending on the type of object selected:

When an Ellipse is selected:

When an Image is selected:

Or when a measurement other than an ellipse is selected:

This example shows several methods of making formulas handle measurements for different Feature Types. In addition, the formula portion used when an image is selected demonstrates how to loop through all measured objects for an image and make a computation. This looping through all objects will also be used in the next examples.