-
Notifications
You must be signed in to change notification settings - Fork 135
input data
InputData is a library for describing data and checking and reading it.
Generally it is used by creating subclasses of InputData.ParameterInput
Example:
class DistributionClass(InputData.ParameterInput):
"""
Description of class
"""
After they are created they need to be initialized by calling the class method createClass.
Example:
DistributionClass.createClass("DistributionClass",
contentType=InputTypes.StringType)
Alternatively, InputData.parameterInputFactory can be used to both subclass ParameterInput and to call createClass.
Example:
DistributionClass = InputData.parameterInputFactory("DistributionClass",
contentType=InputTypes.StringType)
After that the subclasses of ParameterInput can have subnodes and parameters added.
Parameters are added with the addParam that takes the name and the type.
Example:
DistributionClass.addParam("distribution_name", InputTypes.StringType)
The content type and the parameter type are subclasses of InputTypes.InputType.
There are several predefined types including InputTypes.StringType and InputTypes.IntegerType and InputTypes.FloatType.
There is an enum type maker that can be used to create types that only allow from a list of strings.
Example:
YesOrNoType = InputTypes.makeEnumType("YesOrNo","YesOrNoType",["yes","no"])
To create a subnode, first create it, and then add it to the parent node with addSub
Example:
metricInput = InputData.parameterInputFactory("Metric", contentType=InputTypes.StringType)
metricInput.addParam("class", InputTypes.StringType, True)
metricInput.addParam("type", InputTypes.StringType, True)
inputSpecification.addSub(metricInput)
Note that addSub can take a quantity:
inputSpecification.addSub(metricInput, InputData.Quantity.one)
where the possibilities are Quantity.zero_to_one, Quantity.zero_to_infinity (default), Quantity.one, Quantity.one_to_infinity.
Where to put code:
The standard method for defining these is to add a class method called getInputSpecification
Example:
class Something(SomeBase):
@classmethod
def getInputSpecification(cls):
"""
Method to get a reference to a class that specifies the input data for
class cls.
@ In, cls, the class for which we are retrieving the specification
@ Out, inputSpecification, InputData.ParameterInput, class to use for
specifying input of cls.
"""
inputSpecification = InputData.parameterInputFactory(cls.__name__, ordered=False, baseNode=InputData.RavenBase)
inputSpecification.addParam("name", InputTypes.StringType, True)
return inputSpecification
For classes where they should inherit from the base class, they can get the parent input specification, and use that as a start.
Example:
@classmethod
def getInputSpecification(cls):
inputSpecification = super(ComparisonStatistics, cls).getInputSpecification()
inputSpecification.addParam("something", InputTypes.IntegerType)
return inputSpecification
Reading data from XML files
First, create a class instance. Then use the parseNode function on the XML node. After that, the children can be checked with the subparts variable, or parameters can be checked with the parameterValues variable. The main data will be stored in the value variable. There are also functions getName() that gets the subnode's name and findFirst that finds the first subnode with the given name.
Example XML:
<NDCartesianSpline>
<dataFilename type="PDF">2DgaussianCartesianPDF.txt</dataFilename>
</NDCartesianSpline>
Example Reading:
paramInput = NDCartesianSpline.getInputSpecification()()
paramInput.parseNode(xmlNode)
dataFilename = paramInput.findFirst('dataFilename')
if dataFilename != None:
self.dataFilename = os.path.join(self.workingDir,dataFilename.value)
functionType = dataFilename.parameterValues['type']
Example Reading subnodes:
for child in paramInput.subparts:
if child.getName() == 'Metric':
metricType = child.parameterValues['type']
metricText = child.value
For some of the classes, the descr parameter is used to automatically generate LaTeX documentation. See ravenframework/Optimizers/acquisitionFunctions/ProbabilityOfImprovement.py
for example. Note that doc/user_manual/generate_docs.sh
needs to be manually run to do this. Also note that _
are automatically escaped, but if the _
is followed by a {
it is not escaped (example l_{2}
can be used to get a subscript).
specs.addSub(InputData.parameterInputFactory('epsilon', contentType=InputTypes.FloatType,
descr=r"""$\epsilon_{0} is the minimum value""")
It is possible to allow a ParameterInput instance to collect undefined inputs; that is, input whose contents and structure is not known before run time. To do this, set the strictMode
parameter when defining the spec to False
.
When a ParameterInput node has strictMode
set to False, any hierarchal input that is not defined specifically in the spec will be saved as a list of input tree elements (specifically, raven.utils.TreeStructure.InputNode
instances). Each of these may have an arbitrary number of sub-elements, attributes, text, and so on. When read in, these are stored on the ParameterInput in an attribute called additionalInput
, which is a list of the InputNode instances.
By default, the spec does not take any action on the additionalInput
entries. The developer can pass these instances to custom code, parse information from them, etc.
For example, see within the unit test for the InputSpec, located at raven/tests/framework/unit_tests/testInputData.py
. In that example, node <B>
has strict mode disabled, and so stores each of the subnodes of <B>
as InputNode instances in the B.additionalInput
list.