Menu

#360 getParam constraints, setOutputParam

Autoplot 2014a
open
nobody
None
7
2024-08-26
2014-05-13
No

Jython scripts use getParam to get inputs. The command uses up to four parameters, which are:
1. the name of the variable
2. the default value of the variable, which also constrains the type.
3. documentation string
4. constraints on inputs.

Item 4 is what is proposed for extension. I'd like to allow constraints on range, and Craig has asked for human-readable documentation for enumerations.

Discussion

  • Jeremy Faden

    Jeremy Faden - 2014-05-13

    Just playing with this a little:

    sc= getParam( 'sc', 'a', 'RBSP Spacecraft', [ 'a', 'b' ] )
    values= { 1:'good', 2:'okay', 3:'bad', 9:'unknown' }
    sc= getParam( 'quality', 1, 'Quality', values )
    filt= getParam( 'filt', 30, 'filter', { '_ge':0, '_lt':100, '_cadence':1 } )
    

    Note the underscore is a hint that these are reserved words. Dictionaries loose their sorting, so maybe instead

    values= { 1:'good', 2:'okay', 3:'bad', 9:'unknown' }
    sc= getParam( 'quality', 1, 'Quality', [1,2,3,9], values )
    

    Another reserved value would be '*' indicating any value is allowed.

    Other reserved words:
    _gt,_ge,_lt,_le
    _length

     

    Last edit: Jeremy Faden 2014-05-13
  • Jeremy Faden

    Jeremy Faden - 2016-09-16

    setOutputParam has been planned for a while, and I put in forward-compatibility code so that old Autoplots would still handle this when it is a full feature.

    I'd really like to get these new constraints in before AGU.

     
  • Jeremy Faden

    Jeremy Faden - 2019-06-14

    This is a left-over feature request which would be really nice to use. Often I'd like to show some example inputs, but I don't want to say the examples are the only inputs.

    Often I use "case" to be an enumeration of valid inputs to a script, so saying case=1 sets all the other parameters. This works fairly well for interactive use, but doesn't work with the "run batch" (batchmaster) tool, where there's another ticket for this problem. See also https://sourceforge.net/p/autoplot/bugs/2065/

     

    Last edit: Jeremy Faden 2019-06-14
  • Jeremy Faden

    Jeremy Faden - 2019-06-14

    For the human labels on an enumeration, I would use:

    constraint= { values:[1,2,3,9], labels:['good', 'okay', 'bad', 'unknown'] }
    sc= getParam( 'quality', 1, 'Quality', constaint )

     
  • Jeremy Faden

    Jeremy Faden - 2019-06-14

    More constraints:
    constraint= { 'min':0, 'max':100 }
    constraint= { 'min':0.0, 'max':100.0, 'step':5.0 } # used when generating inputs. 2.5 is a valid entry.
    constraint= { 'regex':'sc[1234]' }
    constraint= { 'enum':[1,2,3,9] }
    constraint= { 'subset':'ant1,ant2,ant3,ant4,ant5,' } # a subset of these should be selected
    constraint= { 'examples':[1,2,3,9] } # like enum, but any value outside of the set is also valid

     

    Last edit: Jeremy Faden 2019-10-09
  • Jeremy Faden

    Jeremy Faden - 2019-07-04
    • Priority: 5 --> 7
     
  • Jeremy Faden

    Jeremy Faden - 2019-10-09

    I just noticed in autoplot2017.py, I claim that constraint can be a dictionary with QDataSet properties like VALID_MIN and VALID_MAX. I think there's a lot of things that ignores (like subset or examples), but it's worth mentioning on this ticket. I'd like to make sure with this next release that if a dictionary is used, then it will be ignored, future-proofing the getParam call.

    Also I'm adding setScriptTitle, setScriptDescription, setScriptLabel and setScriptIcon, which presently do nothing.

     
  • Jeremy Faden

    Jeremy Faden - 2019-10-22

    When writing a different code I put in "values" instead of "enum", and I think this is probably a better name. (enum is more computer-sciencey, but isn't any more precise.) I also looked at "oneOf" and "anyOf" but I think the capitalization is going to cause problems, and anyOf seems ambiguous.

     
  • Jeremy Faden

    Jeremy Faden - 2019-10-24

    I've introduced a color-type for the parameters. The GUI is still lacking and could be made more effective.

    c= getParam( 'color', Color.GRAY, 'line color', [ Color.GREY, Color.RED] )
    
     
  • Jeremy Faden

    Jeremy Faden - 2020-02-05

    I've added examples, used instead of values, which allows other things to be specified. So for example:

    orbit= getParam( 'orbit', 24, 'orbit number', { 'examples':[ 24,25,26, 27, 28, 29, 30 ]} )

    has the advantage that it works with orbit=23 and orbit=31.

     
  • Jeremy Faden

    Jeremy Faden - 2022-02-10

    With somewhat strange scripts running on a server, being run by strangers, this provides an important way for scripts to control parameters. I showed the script dev/demos/2021/20210408/demo1000000RGBColorPoints.jy to a friend and they immediately started putting huge values in for the symbol size to try and break the server. Being able to constrain the min and max values would address this issue.

     
  • Jeremy Faden

    Jeremy Faden - 2022-03-05

    Another nice constraint for timeranges would be to limit the length of time requested (to limit processing time), to require a specific length (1 day to support file boundaries) and boundaries. This might be something like { 'formatsTo';'$Y-$m' } to mean only months are accepted.

     
  • Jeremy Faden

    Jeremy Faden - 2022-03-05

    In the Run Batch Tool I now look at the min and max properties.

     
  • Jeremy Faden

    Jeremy Faden - 2022-03-05

    See https://github.com/autoplot/documentation/blob/master/docs/jython/getParamConstraints.md
    where I start to work out documentation for the scientists.

    I also thought it would be useful to have { 'format':'$Y-$m-$d' } which would allow the time range to be constrained to just days.

     
  • Jeremy Faden

    Jeremy Faden - 2022-06-21

    Here's a Python code which starts to implement the new logic:

    import re
    
    _paramMap = {}
    _paramSort = []
    
    params = {}
    
    
    # name is the name of the input parameter.
    # deflt is the default value for the input parameter.
    # doc is any documentation for the parameter.
    # constraint is used to declare any constraints, presently one of: a list of enumerated values, or a dictionary with VALID_MIN, VALID_MAX and other relevant QDataSet properties.
    def getParam(name, deflt, doc='', constraint=''):
        """<html>get the parameter from the URI<ul>
      <li>name is the name of the input parameter.
      <li>deflt is the default value for the input parameter.
      <li>doc is any documentation for the parameter.
      <li>constraint is used to declare any constraints, presently one of: a list of enumerated values, or a dictionary with VALID_MIN, VALID_MAX and other relevant QDataSet properties.<ul>
      """
        if type(name).__name__ == 'int':
            name = 'arg_%d' % name
        _paramMap[name] = [name, deflt, doc, constraint]
        _paramSort.append(name)
        if type(params) is dict:
            if name in params:
                t = type(deflt)  # Ed demonstrated this allows some pretty crazy things, e.g. open file, so be careful...
                v = t(params[name])
                if isinstance(constraint, list):
                    if v not in constraint:
                        raise Exception('value is not one of allowed values: %s %s' % (name, v))
                elif isinstance(constraint, dict):
                    if 'regex' in constraint:
                        if not re.match(constraint['regex'], v):
                            raise Exception('value does not match regular expression: %s %s' % (name, v))
                    if 'min' in constraint and v < constraint['min']:
                        raise Exception('value is less than minimum: %s %s' % (name, v))
                    if 'max' in constraint and v > constraint['max']:
                        raise Exception('value is greater than maximum: %s %s' % (name, v))
                return v
            else:
                return deflt
        else:
            print('in jython script, variable params was overriden.')
            return deflt
    
    
    params['sc'] = 'B'
    params['len'] = 18
    params['date'] = '2018-02-02'
    
    lenn = getParam('len', 10, "boom length", {"min": 10, "max": 35})
    date = getParam('date', '2020-02-02', "date to study", {"regex": "\d{4}-\d{2}-\d{2}", "min":'2016-01-01', "max":'2022-12-31'})
    date2 = getParam('date2', '2020-02-02', "date to study", {"format": "$Y-$j", "min":'2016-001', "max":'2022-365'})
    a = getParam('sc', 'B', "RBSP A or B", ['A', 'B'])
    
    print(a, lenn, date)
    
     
  • Jeremy Faden

    Jeremy Faden - 2023-03-12

    I think there should be a way to hint if slider, droplist, or exclusive checkbox should be used.

     
  • Jeremy Faden

    Jeremy Faden - 2024-06-13

    I'm experimenting with adding "stringType" which can be "file", instead of using a File object. This way a whole bunch of new types can be added without relying on Java types.

     
  • Jeremy Faden

    Jeremy Faden - 2024-08-26

    It would be nice in some cases for a script to declare outputs, be it a file written to disk, plot made on the canvas, or text sent to stdout. This would allow https://cottagesystems.com/AutoplotServlet/ScriptGUIServlet
    to know what it needs to look for and how to generate an output screen without running the script.
    Also, for png output, it could declare the size of the png and if the script doesn't create the right size, handle the error.