Interface ModelFormulaContext
- All Superinterfaces:
DistFormulaContext
- All Known Subinterfaces:
ModelCalcFormulaContext
model
binding. It provides access to a PO specific API,
not available in any of the other Pricefx modules. API calls that add, update or delete objects are only possible in a model calculation step,
cf.
ModelCalcFormulaContext
A PO model has at least one stage: 'Definition'. This is the context of the PO logic called when saving or updating a model.
It should be noted that the UI updates a model before triggering a calculation (though this is client specific behaviour, not required or enforced by the Pricefx backend). A model is therefore typically updated multiple times in its life cycle, as when first created, it tends to be (re-)calculated many times thereafter.
While not mandatory, a PO model is not likely to be useful, or even needed, when no Calculation steps are defined. Costly, i.e. computationally expensive, time-consuming jobs are normally required to be run to prepare a model for future use. In machine learning terminology, one might refer to this as the 'training' phase. Once trained, one might talk about using the model for prediction, or classification. In Pricefx this is achieved by evaluating the model. While, again, optional, a useful model tends to define an 'Evaluation' logic that performs this function.
The ModelType is what pieces this together. Models are created from a chosen ModelType.
The ModelType
defines these key characteristics:
- logic: UniqueName of the main logic; this is the logic that as minimum implements the 'Definition' behaviour. It can also, selectively, define the behaviour in other stages by virtue of setting the 'Calculation Context' on the logic element. (see further down for a list of valid calculation contexts).
- libLogic: Optional. UniqueName of a logic that serves as a library specific to this ModelType. Its elements can be accessed through
the
lib
binding. - analysisLogic: Optional. UniqueName of the logic that is evaluated when triggering an analysis or inspection from the UI. What this looks like is
specific to the UI. What is important is that it is a triggered by a
datamart.modeleval/analysis
request to the JSON API. - evalLogic: Optional. UniqueName of the logic that is evaluated when using ('evaluating') a prepared model from other modules, for example from
Pricing logic in QuoteConfigurator or PriceBuilder. See
ModelEvaluator
for details. - recordLogic: Optional. UniqueName
- generatesData: True or false. Indicates that the module will use its PA backing table to store data, result etc. A client can use this flag to decide on whether to show a data table for the model or not.
- generatesTables: True or false. Indicates that the module will create additional DMTables. A client can use this flag to decide on whether to show a section where these tables can be accessed.
- generatesRecords: True or false. Indicates that the module will generate ModelRecords (the technical name) aka 'Policy Records' (the UI name). A client can use this flag to decide on whether to show a section where these records can be accessed.
- generatesTrees: True or false. Indicates that the module will generate one or more trees (see
ModelCalcFormulaContext.addTree(String, Collection)
). A client can use this flag to decide on whether to show a section where these trees can be accessed. - calcSteps: Optional. Defines a List
, of which each can be triggered independently and in any other, though the expectation is that they would, at least initially, be executed in sequence. Some steps, depending entirely on the PO logic implementation, might be skipped, and some steps might be rerun after the initial calculation. There are no enforced rules; the ModelType documentation should clarify the allowed and desired behaviour.
CalcStep
is defined as:
- name: The name of the calculation step, to be unique across all steps. This is the value returned by a
- label: An optional label or description that can be used by the UI.
- category: An optional category, that allows a UI to group calculation steps together. In the Unity PO UI, for the Segmentation model type, calculation steps are divided in 'Analysis' steps (not to be confused with the analysis logic behaviour) and 'Calculation' steps. In Segmentation, the 'Analysis' steps are "DataPrep', 'DataProfile' and 'PriceDrivers'. The 'Calculation' steps are 'Segmentation', 'Scoring' and 'Pricing'.
- logic: The optional UniqueName of the logic to be executed for this step. When not set, the calculation step's logic is assumed to be implemented by the (mandatory) main logic specified in the
- distributed: True or false. Indicates whether this step can be executed in distributed mode. For a non-distributed step, no additional logic level configuration is required. PO will simply execute this step using the associated logic. For a distributed step, however, there is a pre-condition in that some previous step in the model calculation is assumed to have created so called
getCalculationStep()
call.
ModelType.logic
attribute.
CalculationItems
, representing units of work for this step.
Each such unit of work can then be executed by one of the workers in a distributed execution pool. There is in fact a threshold,
below which the distributed calculation will not kick in (100 by default, set by the formulaEngine.script.optimizer.slaveCalcItemThreshold
instance parameter), in order to avoid creating overhead for low number of work units.
See ModelCalcFormulaContext.addOrUpdateCalcItem(Object, Object, Object)
for more details.
- definition: Evaluated when a model is saved
- calculation: Evaluated in a calculation step
- calculation-init: Evaluated when calculating a distributed step, once, before the individual CalculationItems are processed
- calculation-summary: Evaluated when calculating a distributed step, once, after all the individual CalculationItems have been processed
- analysis: Evaluated in in the Analysis (Classic) and Results (Unity) sections of the UI
- evaluation: Evaluated when
- record: Evaluated after a record using
ModelEvaluator.evaluate(Map)
is invoked
ModelCalcFormulaContext.addRecord(String, TimePeriod, Map, Map, boolean...)
when the calculate == true
-
Nested Class Summary
Modifier and TypeInterfaceDescriptionstatic class
Representation of a node in a model tree (see for ex. -
Method Summary
Modifier and TypeMethodDescriptionEach model is backed by a table in the PA DB.findRecord
(String name, Date validOnDate, String wfStatus) Finds the ModelRecord, if it exists, with the given name, valid on the given day (record.startDate <= validOnDate <= record.endDate), and with the given workflow status, if notnull
.findRecords
(Filter filter, String... sortBy) Finds ModelRecords associated to this model using only Filter criteria.findTreeNode
(String treeName, List<String> path) ListaddTree(String treeName, Matrix2D data, Collection levelCols, Collection labelCols, String outputColName, String outputColFormat); String treeName, Matrix2D data, Collection levelCols, Collection labelCols, String outputColName, String outputColFormat ); Finds the tree node, if it exists, in the given tree with the given path
.A ModelType definition, optionally (but usually) defines a number of calculation steps.getDef()
A typical (set of) PO logic(s) covers various stages: definition, calculation, analysis, record and evaluation.When a clients retrieves the required input parameters for a given stage (definition, calculation step, analysis...), there is the option to set an initial value for a parameter.Retrieves the field definitions previously added usingaddField(Object)
.FilterNode
In the context of a call to thedatamart.modeleval
end point (JSON API), the client request can specify the 'filterNodeId' parameter.LikegetFilterNodePath(Long)
, but for the preset FilterNode revealed bygetFilterNode()
only.getFilterNodePath
(Long nodeId) Given the id of a FilterNode, in some tree previously added to the model, this method returns the logical path from the root to that node.getInput()
Exposes all the input values passed in with a ModelEval request (user entries), or all of the inputs persisted in the model, when in a calculation.getLabel()
Gets all the entries of the LookupTable (PP) named 'Model Params <model.uniqueName>'.Gets the ModelRecord ('PolicyRecord' in the UI) set as context in the 'record' logic evaluation (the logic set in the ModelType.recordLogic attribute).Returns the source name of this model, which is often needed as a parameter in queries, charts and such on the model in the analysis phase; and avoids retreiving the whole model with get().Gets a table object representing the DMTable with the given name, which was previously created using theModelCalcFormulaContext.addTable(String, Object)
method while calculating the model.Adds a new parameter, or overwrites an existing parameter value, being an entry in the 'Model Params <model.uniqueName>' PP.void
Methods inherited from interface DistFormulaContext
getAllocationFields, getCalcItem, getIncLoadDate, getLoadMode, getTarget, getTargetFields, isIncremental
-
Method Details
-
getUniqueName
String getUniqueName()- Returns:
- The unique name of the model
-
getLabel
String getLabel()- Returns:
- The label name of the model
-
getSourceName
String getSourceName()Returns the source name of this model, which is often needed as a parameter in queries, charts and such on the model in the analysis phase; and avoids retreiving the whole model with get().
Typically used when building a query against the model's backing table, and when defining charts with the model as a source.In the 'Segmentation' logic for example, the 'DataPrep' step filters and loads the transaction data in the model's table, and subsequent steps then query the model's table for better performance.
Note: The source name for a PO model has the form 'DMM.'
. - Returns:
- The source name of the model
-
getDef
A typical (set of) PO logic(s) covers various stages: definition, calculation, analysis, record and evaluation.
Not all are always needed - the ModelType defines which one are. Still, a persisted data object accessible to all stages is usually required.
In the 'Segmentation' model type, for example, the selected transactions source and field mapping (product, customer etc. fields) are stored by the Definition logic in the built-inmodel.def
map.Note: As the map is persisted in the model, it is important not to put any non-serializable objects in it. When in doubt, stick to Collections of (Collections of...) primitives, String, Number, Date etc.
Sample code:model.def.policyStartDate = api.dateUserEntry("Start Date") model.def.policyEndDate = api.dateUserEntry("End Date")
- Returns:
- The model.def map
-
getDefaults
When a clients retrieves the required input parameters for a given stage (definition, calculation step, analysis...), there is the option to set an initial value for a parameter. This is done with code like this snippet:
In a new model, the UI will render this input having the initial 50 value, but then the user can override it and save.def PARAM = "Floor Percentile" model.def.floorPercentile = api.integerUserEntry(PARAM) model.defaults[PARAM] = 50
- Returns:
- The map of default parameters
-
getInput
Exposes all the input values passed in with a ModelEval request (user entries), or all of the inputs persisted in the model, when in a calculation. Note that in the ModelEval scenario, the inputs are not necessarily stored in the model yet. In this use case, the logic leverages knowledge of already provided input values (provided by the client/UI) to determine additionally required inputs.- Returns:
- A map of input parameter (name,value) pairs.
-
addField
Each model is backed by a table in the PA DB. This way, a model can be used as a source to a query or chart.
But unlike for example a DataSource, the user or configuration engineer is not expected to define its fields in the UI.
Instead, the model dynamically - in the definition logic - defines its fields using this method. The fields to be added normally depend on user inputs, such as the selected revenue, volume and margin fields in the Segmentation logic example.Sample code:
def ctx = api.getDatamartContext() def sourceName = ctx.sourceSelectionEntry("Transaction Source", "DM", "DMDS") // allow selection from DMs and DSs def source = ctx.getFieldCollection(sourceName) if (source) { def fields = source.fc.fields.collectEntries{ [it.name, it] } def fieldName = ctx.fieldSelectionEntry("Product Field", source, "DIM") if (fieldName) { def field = fields[fieldName] model.addField(field) // leverage the field definition from the source model.addField( [name:field.name, label:field.label, type:field.type, dimension:true, key:false] ) // or define it explicitly }
- Parameters:
fieldDef
- The field definition as a map of (property, values) pairs- Returns:
- The model binding. to facilitate a builder pattern
-
getFields
Collection<DMField> getFields()Retrieves the field definitions previously added usingaddField(Object)
.
Note that as DMField is a non-whitelisted type, the Groovy sandbox will convert the DMField objects to maps, resulting in the same field definition representation as used inaddField(Object)
.- Returns:
- Collection of field definitions previously added using
addField(Object)
-
getSourceQuery
DatamartContext.Query getSourceQuery() -
setSourceQuery
-
getCalculationStep
Object getCalculationStep()A ModelType definition, optionally (but usually) defines a number of calculation steps. When the user, or a 3rd party via the JSON API, or a schedule ModelCalculation DataLoad, request a calculation, the step to execute is identified by the DataLoad'scalculationContext
attribute. This allows PO to identify the step, and hence the logic to be executed. When there is no dedicated logic defined for each calculation step, this method exposed the name of the calculation step being executed to the logic, so it can selectively evaluate the relevant elements.- Returns:
- A map representation of the
CalcStep
being executed. UsuallyCalcStep.name
is sufficient to drive any conditional Groovy code execution.
-
findTreeNode
ListaddTree(String treeName, Matrix2D data, Collection levelCols, Collection labelCols, String outputColName, String outputColFormat); String treeName, Matrix2D data, Collection levelCols, Collection labelCols, String outputColName, String outputColFormat ); Finds the tree node, if it exists, in the given tree with the given path
.
The path is the list of values for the first, second etc. level of the tree (see e.g.ModelCalcFormulaContext.addTree(String, Collection)
).
Note: to find a leaf node, values for all levels are to be provided. Fewer values will result in an intermediate level node to be returned, if such a node exists of course.- Parameters:
treeName
- Name of the tree to be created, i.e. FilterNode.name of the root nodepath
- List of values for the various levels in the tree.- Returns:
- The id of the FilterNode with the given path (from the root node). See also
getFilterNodePath(Long)
-
getFilterNodePath
Given the id of a FilterNode, in some tree previously added to the model, this method returns the logical path from the root to that node.Example: if the identified node in the below tree is 'Retail' in EMEA, then the filter node path is [Region:"EMEA", Channel:"Retail"], with 'Region' and 'Channel' assumed to be the level names, in that order, defined when first creating the tree (see
ModelCalcFormulaContext.addTree(String, Collection)
).Segments | + EMEA | | | + Retail | + APAC | + Retail | + Industry
- Parameters:
nodeId
- The id of a FilterNode that exists in a tree previously added to the model- Returns:
- The path to the given FilterNode as a map of (level,value) pairs
-
getFilterNode
FilterNode getFilterNode()In the context of a call to thedatamart.modeleval
end point (JSON API), the client request can specify the 'filterNodeId' parameter.
The value of this parameter is to be the id of a FilterNode object, previously created by the model. In the 'Segmentation' model type, for example, the 'Segmentation' calculation step creates a 'Segments' tree, in which each node, including the root node, is a FilterNode object.
In the 'Results' section in the Unity UI, when the user selects a node in the Segments tree, a subsequentmodeleval
call retrieves the details of the selected segment.- Returns:
- A map representation of the selected FilterNode
-
getFilterNodePath
LikegetFilterNodePath(Long)
, but for the preset FilterNode revealed bygetFilterNode()
only.- Returns:
- The path to the selected FilterNode as a map of (level,value) pairs
-
getRecord
Gets the ModelRecord ('PolicyRecord' in the UI) set as context in the 'record' logic evaluation (the logic set in the ModelType.recordLogic attribute). The evaluation is done when a record is added usingModelCalcFormulaContext.addRecord(String, TimePeriod, Map, Map, boolean...)
when the calculate argument is true.- Returns:
- A map representation of the ModelRecord
-
findRecord
Finds the ModelRecord, if it exists, with the given name, valid on the given day (record.startDate <= validOnDate <= record.endDate), and with the given workflow status, if notnull
. If wfStatus isnull
, there is no filter condition on record.workStatus.Valid workflow statuses are:
- DRAFT
- SUBMITTED
- DENIED
- APPROVED
- NO_APPROVAL_REQUIRED
- WITHDRAWN
- Parameters:
name
- The name of the record give when first creating it, usingModelCalcFormulaContext.addRecord(String, TimePeriod, Map, Map, boolean...)
}validOnDate
- The date on which the record is to be validwfStatus
- The workflow status the records needs to be in, ignored ifnull
- Returns:
- A map representation of the record
-
findRecords
Finds ModelRecords associated to this model using only Filter criteria.- Parameters:
filter
- The criteria the records needs toad here tosortBy
- Optional sort fields- Returns:
- A list of map representations of the records, empty of none matched the criteria.
-
getParams
Gets all the entries of the LookupTable (PP) named 'Model Params <model.uniqueName>'. All the user entries for the model are automatically stored in that PP. In addition, the logic can add parameters programmatically (cf.setParam(String, Object, boolean...)
).- Returns:
- A map of param (name, value) pairs
-
setParam
Adds a new parameter, or overwrites an existing parameter value, being an entry in the 'Model Params <model.uniqueName>' PP.- Parameters:
name
- Name of the parametervalue
- The parameter value, which needs to be JSON-serializableifMissing
- If true, an existing parameter's value will not be overwritten. This makes it easier to add default parameters, not overwriting the value that was set by an end user.- Returns:
- The added PP entry, as a map. Mostly useful to get the
id
of the added/updated entry.
-
getAttachments
- Returns:
- The names of all the files attached to the model. This can for example be used to populate a dropdown user entry.
- Throws:
IOException
-
getTable
Gets a table object representing the DMTable with the given name, which was previously created using theModelCalcFormulaContext.addTable(String, Object)
method while calculating the model. A reference to this table can then be used when building aDatamartContext.Query
on that DMTable.- Parameters:
tableName
- The table name.- Returns:
- The Table object with the given tableName if it exists, or null if not.
-