In addition to the basic routines there are some packaged facilities for common sequences of calls. Most deal with dynamic control of acceptable values when getting the parameter. Some are needed because the in choices and range limits imposed by the ADAM interface module are static, and therefore cannot be adjusted depending on the values of other parameters or data. Note that in the extended routines that follow, all call a PAR_GETx routine which first checks that each supplied value satisfies these interface-file constraints, and prompts for a new value if it does not. Only after these tests are made will each value be compared with the constraints in the extended routines. Therefore, you are recommended not to use the in and range fields for parameters obtained using the extended routines.
Here is an example of handling your own constraints to illustrate why it is more convenient to use the packaged routines, where applicable, and also to demonstrate how you might write your own extended routine should you need one. It is a little contrived, since the PAR library already provides the most-common combinations.
Here we obtain from parameter NAME an integer that is not exactly divisible by 3, set the dynamic default to 1, and interpret null to mean set the value to 3. See SUN/104 for details of the MSG_ calls.
To set another constraint you have to modify the logical expression for variable NOTOK, and revise the ERR_REP error report, possibly with more tokens. Suppose variables VMIN and VMAX define a range of permitted values, which is inclusive when VMAX is the larger of the two and exclusive when VMAX is less than VMIN. The constraint expression could modified to the following.
and the error report would look something like this
In practice you would probably define a logical variable outside the loop to indicate whether the range was inclusive or exclusive.6
Having looked ‘behind the scenes’, we can now look at what the PAR_ extended routines offer.
A parameter value may be forced to lie within a range using a call to the generic routine PAR_GDR0x. The name is derived from Get with a Default and Range. For example,
gets the value for the real parameter SCALE using a dynamic default of 1.0, stores the value in the variable SCAFAC, and ensures that the value lies in the range 0.0–2.0. If a supplied value is out of this range, PAR_GDR0R reports the acceptable limits and prompts the user for another value. (This applies to all the routines with constraints described in Section 7.) Thus the user would see something like the following.
The fifth argument (NULL) will normally be false. When it is true, it instructs the PAR routine to return the dynamic-default value whenever a null value is supplied, and then to annul the error status. If the MSG filtering level (see SUN/104) is set to ‘verbose’, an informational message will be output.
In the above case if NULL were made .TRUE., and the user entered the null symbol whilst in ‘verbose’ mode, the dialogue would be as follows:
NULL should only be set true when the dynamic default will always give reasonable behaviour in the application.
For all but the last example in Section 7, the null flag is set to .FALSE., and will not be mentioned again until then.
Swapping the limits lets you exclude values in the range. Therefore,
would permit a value of 3.5, unlike before, as well as 0.0 and 2.0. However, 1.5 would not now be acceptable.
Notice that the suggested default has disappeared.7 This occurred because 1.0 violates the range constraint, and it is a feature of the PAR_ extended routines. If you do not want a dynamic default, set the dynamic-default argument to a value that violates the constraints. The range-exclusion feature is present in all the PAR_ extended routines that have a range constraint.
Not surprisingly, there are only versions of the range-constraint routines for integer, real, or double-precision parameters. These have the usual I, R, and D suffices respectively. The range limits have the same data type as the value.
There are similar generic routines for obtaining an array of values between limits. The first permits up to a given number of values to be obtained. We modify the example from the previous section to illustrate this routine.
This time up to ten values may be obtained from parameter SCALE, and stored in the array SCAFAC. All the values must lie in the range 0.0–2.0. Since the number of values is not fixed, there is no dynamic-default argument. PAR_DEF1x can be called prior to PAR_GDRVx, if desired.
If you want an exact number of values, there is a routine to do this for you. For example, suppose that you want red, green, and blue intensities to define a colour, then the following code would obtain exactly three normalised intensities – one for each colour – between zero and one.
The default must be an array. Should you not want a dynamic default in this case, just set the first element of DEFAUL to be negative or greater than one.
From the user’s perspective, instructions will be given if additional values are required.
First the user gives too many values, and is told how many to give. Next too few are supplied, so PAR_GDR1R asks for another. Again the user is not paying attention and gives the whole RGB value instead of just the outstanding blue intensity. Finally, the user gives the last value, yielding an RGB of 1.0,0.0,0.0 or the colour red.
Another variation of the theme is when you want to have an exact number of values, and each value is constrained to its own range. For instance, suppose that you wanted to obtain the two-dimensional co-ordinates of a point within a rectangle, whose bounds are known. The following code could obtain the required values, where LBND and UBND define the lower and upper co-ordinates of the rectangle.
PAR_GRM1x will inform the user of any value(s) that violate a range, and prompts for new values. The name is derived from Get with Ranges for Multiple dimensions.8
If you want to constrain each value of an array to its own range, but do not require an exact number of values, there is even a PAR routine to do that. PAR_GRMVx returns up to some maximum number of values of values, each within a defined range. In the following example an application needs integer compression factors (COMPRS) along each of NDIM dimensions. These must be positive and no greater than the size of the array along each dimension, and are set by the CMPMIN and CMPMAX arrays. ACTVAL returns the actual number values obtained from parameter COMPRESS, and in this example, it is used to set no compression for the higher dimensions.
There are occasions when you need an odd or even integer. For example, the size of a smoothing kernel must be odd. PAR provides two routines with these functions. Thus,
obtains an odd integer between 3 and 11 from parameter BOX, and stores it in variable BOXSIZ. The dynamic default is 5. Similarly,
gets a even value in the range 2 to 10 from parameter OFFSET, with a dynamic default of 2. Zero counts as an even number, and so it would be acceptable here.
A common requirement is to select an option from a menu. PAR_CHOIC offers this functionality. You provide a list of options separated by commas. When the user selects a choice not in this menu, an error report appears that lists the available options, and the user is prompted. 9 PAR_CHOIC permits the user of your application to use an unambiguous abbreviation. However, the unshortened value is returned. The value is also in uppercase, though the list of options need not be so.
So in the above example there are ten options available for parameter OPTION. The dynamic default is ’Region’. If you assign the second argument with a value not in the main list, such as a blank string, it instructs PAR_CHOIC not to set a dynamic default. Note that PAR_CHOIC only returns character values.
This is what the user might see for the above example.
The first value is unacceptable as it is not in the menu. The second is ambiguous because there are
several options beginning with an ess. Had the user entered sl
say, the abbreviation would have
selected a value of ’SLICE’. The final value appears not to be in the list of choices, but PAR_CHOIC
allows the user one typing mistake, and so the user actually selects option ’LIST’. In this
case, a warning message is output unless the MSG filtering level (see SUN/104) is set to
‘quiet’.
There is a similar routine – PAR_CHOIV – to get a vector of character values from a menu.
Should you wish to combine the constraints of a numeric value within a range, and a list of options, there are PAR routines to do it for you. Here is an illustration to show how this might be profitably used. The application from which the following extract is taken wants to replace certain array values with a constant; this can either be a numeric value or set to the bad-pixel value.
This obtains from parameter NEWLO a value which is either ’BAD’ or a real value. The value is returned in variable CNEWLO. VAL__MINR and VAL__MAXR are the minimum and maximum values, and VAL__BADR is the bad value, for the real data type, and VAL__SZR is the maximum number of characters needed to store a real value; all symbolic constants are defined in the PRM_PAR include file ( SUN/39). The dynamic default is ’0.0’. Remember that the dynamic default and returned value are strings. Therefore, you must first test the returned value for being any of the items on the menu, before converting it to a number. Since the returned value may be undefined following an error, it is prudent to check the status before using the value.
Should the user give an unacceptable value, PAR_MIX0x informs the user of the error and lists the available options, and then invites the user to supply another value.
Here is a more subtle example. This only has numbers in the menu, but it is advantageous when only certain numeric values are acceptable.
Here PAR_MIX0I obtains an ‘integer’ that is either 5, 11, 23, 47, 49, or in the range 101–1500, and returns it in the character variable CPLATE. CHR_CTOI converts the string into a true integer value, PLATNO. Since the second argument of PAR_MIX0I is a blank string, there is no dynamic default. To produce a suggested default, the second argument would have to be one of the menu options, or satisfy the range constraint (when converted to an integer). If we had swapped the range limits, PAR_MIX0I would allow all values not in the range 102–1499.
PAR_GTD0L obtains a scalar logical value, with a dynamic default defined, and has the capability of handling a null status. Thus the following obtains a value from the parameter SWITCH and stores it in the variable called POWER. The dynamic default is .TRUE..
The third argument is the same as we met in Section 7.1. If we reverse the polarity of NULL, PAR_GTD0L will assign the dynamic default to POWER whenever the parameter is in the null state, and returns with STATUS set to SAI__OK. To reiterate NULL=.TRUE. should only be used when the dynamic default will always give reasonable behaviour in the application. This is highly likely for a logical value.
6In the ADAM implementation users of your application may wish to take advantage of the MAX/MIN facility. If this is so you will need to add calls to PAR_MAXI and PAR_MINI in the previous example.
7This assumes that the ppath in the ADAM interface file starts with ’DYNAMIC’
.
8In retrospect the name probably should have been PAR_GDM1x for Get with Defaults and Multiple ranges, but the existing name is already in use in applications.
9Remember that in the ADAM implementation the PAR_GET0C call made by PAR_CHOIC will first test the obtained value against the range or in fields in the interface file. If the supplied value is unacceptable, the user will be prompted by PAR_GET0C. Only once these constraints are passed will the value be tested against the menu.