LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
The Policy Authoring Format (PAF)

PAF is an LSST-specific format for Policy data that is optimized for human editing. It is very similar to property files commonly used in Java and Unix applications. A simple example might look like this:

#<?cfg paf policy ?>
#
# this is a comment
#
standalone:  true          # a boolean parameter (value is true or false)
filter.threshold: 32.5     # a double parameter
filter.maxIterations: 13   # an integer parameter
label:  Special Filter     # a string value

Fuller examples can be in examples/policies directory; see the files ending in the .paf extension.

The Leading Line

It is recommended, but not required, that the first line of the policy file contain a content identifier: "#<?cfg paf policy ?>" This line signals to the Policy framework that the file contains policy parameter names and values in PAF format, so that it can choose the proper parser. If this line does not appear, the framework can usually recognize the format either from the file extension (.paf) or from the first parameter definition.

Spacing

One can be fairly liberal with the use of spacing. The following is legal:

standalone              :  true          
    filter.threshold    :  32.5     
    filter.maxIterations:  13   
     label              :  Special Filter     # a string value

It is illegal to insert spaces within a parameter name.

Parameter Names

Everything left of the first colon (:) is the parameter name which can either be a so-called "top-level" parameter name–one that contains no periods (.)–or a hierarchical name. Each field delimited by dots must begin with a letter and as a whole contain only letters or numbers. The following are legal names:

width
Width
WIDTH
image2jpeg.cmd
convolve.gauss1.width
convolve.gauss2.width

Floating Point Values

The usual IEEE formats for floating point numbers are supported:

convolve.gauss1.width:  1.2
convolve.gauss2.width:  0.9
convolve.gauss1.width:  .22
convolve.gauss2.width:  1.457e-02
convolve.gauss3.width:  1e-3

Boolean Values

The strings true and false are recognized as boolean values:

standalone: true
verbose:  false

If you want a string value set to either "true" or "false", enclose the value in quotes (see next section):

# These are string values, NOT booleans
standalone: "true"
verbose:  "false"

Variations with different letter cases are not recognized as booleans; instead, they will be interpreted as strings:

# These are NOT booleans; they are loaded as strings
standalone: True
verbose:  FALSE

String Values

A string value can be indicated by enclosing the value in double or single quotes (" or '). Single quotes can be used if the value is to explicitly include a double quote, and vice versa. The quotes can be omitted if the value...

The following are legal string-valued parameters:

label1:  select a function
label2:  width
label3:  'target image'
label4:  "the center's position"
choices: "gaussian" 'box' "airy"   # a 3-element array of string values
help:   "A long explanation can span across multiple lines
         as long as the value is enclosed in quotes.  When multi-line
         values are parsed, each new-line character and its surrounding 
         spaces will be replaced with a single space."

Array Values

Array valued parameters can be formatted in one of two ways. They can either be placed one line, delimited by spaces:

standalone:           true true false           # boolean array
filter.threshold:     32.5 0.9 .22 1.457e-02    # double array
filter.maxIterations: 13 21 27 50               # integer array
label:                "joe" "fred" "evelyn"     # a string value

or they can be broken up across several lines:

filter.threshold:     32.5  0.9 
filter.threshold:     .22   
filter.threshold:     1.457e-02  

In both examples above, "filter.threshold" will contain a 4-element array.

It is illegal to mix types within an array. It is also an error to separate array values with characters other than spaces (e.g. commas):

# ILLEGAL!
filter.threshold:  3  4.7    # mixed types!
graph.minimum:  5
graph.minimum:  3.2          # changed types!

filter.threshold:  3, 4.7    # don't use commas!
graph.labels:  "x", "y"      # don't use commas!

Policy Values

Hierarchical parameters can be indicated in two ways. The short hand version shown thus far captures the hierarchy in the parameter name with the use of dots (.):

filter.threshold: 32.5     # a double parameter
filter.maxIterations: 13   # an integer parameter

In this example the name "filter" implicitly resolves to a Policy value–a set of named parameters–containing 2 parameters, "threshold" and "maxIterations". This can alternatively be written explicitly:

filter: {
   threshold:      32.5
   maxIterations:  13
}

In this latter form, the "sub-parameters" must each be on a separate line. The can however share a line with the opening or closing brace:

filter: {     threshold:  32.5
          maxIterations:  13    }

Note that the opening brace must be on the same line as the Policy name:

# ILLEGAL!
filter: 
{
   threshold:      32.5
   maxIterations:  13
}

Note also that once you establish that a name is at the root of a hierachy (i.e. that it is of type Policy), it is illegal to assign another type to it:

filter.threshold:  32.5    
filter:            "Airy"    # ERROR!  Type for filter has changed!

Arrays of Policies

It is possible to have an array of sub-Policies accessible via a single name. The way to accomplish this in the policy file is to repeat the use of the parameter name, giving each a different set of values:

filter: {     threshold:  2.5
          maxIterations:  150   }
filter: {     threshold:  32.5
          maxIterations:  13    }
filter: {     threshold:  35.0
          maxIterations:  13    }

Including Other Policy Files

If a parameters value starts with an at sign (@), the value type is assumed to be a Policy and the string following the @ is interpreted to be either a file path or URN. When parsed via (createParser()), an attempt will be made to open that file and read the contents as Policy. Each of the parameters given there will be assumed to be sub-parameters under the name given in the first policy file. For example, suppose a policy file contains:

filter:  @filter_policy.paf

and the file filter_policy.paf contains:

threshold:      32.5
maxIterations:  13

This would be equivalent to the following defined in a single file:

filter.threshold: 32.5     
filter.maxIterations: 13   

By default, the createPolicy(policyFile) function will look for the referenced Policy files under the same directory as the original Policy file. Alternatively, you can pass an additional pathname to the function that will be assumed to contain the policy files to be included, e.g.:

   p = Policy.createPolicy("policy.paf", "examples/policies")

Including non-local Policy Files

If a parameters value starts with "@urn:eupspkg:", the value type is assumed to be a Policy in a directory that is determined by environment variables. For example:

filter: @urn:eupspkg:some_package:local/repository:path/to/filter.paf

This URN line consists of:

Further, "urn:eupspkg:" can be abbreviated as a second "@":

filter: @@some_package:local/repository:path/to/filter.paf