How to create a Python Result with a node scoping option and results coming from another result obj?

Rohith Patchigolla
Rohith Patchigolla Member, Moderator, Employee Posts: 216
100 Comments 25 Answers Second Anniversary 25 Likes
✭✭✭✭

I evaluated a result with “Max over Time” on hundres of steps, which takes a lot of time to evaluate. Now, I would like to zoom into certain area, select FE items, say Nodes, plot this result only on those nodes without having to change the scope of the original result and reevaluate. Python result seems to be a solution. An example could help.

Answers

  • Rohith Patchigolla
    Rohith Patchigolla Member, Moderator, Employee Posts: 216
    100 Comments 25 Answers Second Anniversary 25 Likes
    ✭✭✭✭

    One could create a python result to extract results from an already evaluated result object via obj.PlotData option, and pass the result data to a custom field which can then be plotted via Python Result.

    Here is an example. There are two parts. Script part and Property Provider path. Please paste them at respective locations once you insert a new python result object, then Reload properties, select an already evaluated result (give a unique name if there are duplicates), select some nodes, and evaluate the python result.

    This can be extended to element selection as well I suppose with some more changes.

    Script part:

    def post_started(sender, analysis):# Do not edit this line
        define_dpf_workflow(analysis)
    
    # Uncomment this function to enable retrieving results from the table/chart
    # def table_retrieve_result(value):# Do not edit this line
        # import mech_dpf
        # import Ans.DataProcessing as dpf
        # wf = dpf.Workflow(this.WorkflowId)
        # wf.Connect('contour_selector', value)
        # this.Evaluate()
    
    def define_dpf_workflow(analysis):
        import mech_dpf
        import Ans.DataProcessing as dpf
        mech_dpf.setExtAPI(ExtAPI)
        dataSource = dpf.DataSources(analysis.ResultFileName)
    
        nodeIdsScoped = this.GetCustomPropertyByPath("My Properties/Scoping Property/Geometry Selection").Value.Ids
    
        myResult = this.GetCustomPropertyByPath("My Properties/Result Selection").ValueString
        myResultObj = DataModel.GetObjectsByName(myResult)[0]
        myResultPlotData = myResultObj.PlotData
    
        node_to_result = dict(zip(myResultPlotData["Node"], myResultPlotData["Values"]))
        filtered_results = [node_to_result[node_id] for node_id in nodeIdsScoped]
    
        npl_field = dpf.FieldsFactory.CreateScalarField(nodeIdsScoped.Count, "Nodal")
        npl_field.Data = filtered_results
    
        my_scoping = dpf.Scoping()
        my_scoping.Location = "Nodal"
        my_scoping.Ids = nodeIdsScoped
        npl_field.Scoping = my_scoping
    
        forward = dpf.operators.utility.forward_field()
        forward.inputs.field.Connect(npl_field)
    
        dpf_workflow = dpf.Workflow()
        dpf_workflow.Add(forward)
        dpf_workflow.SetOutputContour(forward)
        dpf_workflow.Record('wf_id', False)
        this.WorkflowId = dpf_workflow.GetRecordedId()
    

    Property Provider part: Paste the below 3 functions in place of already existing reload_props() function. So, the old reload_props() is replaced and two new functions added i.e. get_options_handler() and dropDownValid().

    def reload_props():
        this.PropertyProvider = None
    
        # comment the following return to allow the rest of the function definition to be executed and add properties
        #return
    
        """
        Some sample code is provided below that shows how to:
            1. Create an instance of the Provider. The Provider class is used to add custom properties to the details.
            2. Use the Provider instance to add custom properties.
            3. Configure those custom properties.
        """
    
        # Create the property instance
        provider = Provider()
        #expression_prop = group.AddProperty("Expression Property 1", Control.Expression) # Expression is a string
        #
        ## Configure the double property to be parameterizable. As a default the property will be an input parameter.
        ## However, by updating the ParameterType property, it can be configured to be a output parameter as well.
        ## double_prop.CanParameterize = True
        ## double_prop.ParameterType = ParameterType.Output
        #
        ## The valid range set here is used by the IsValid handler in the Provider class, please look at the class definition above.
        ## If interested in the implementation, please look at the class definition below
        #double_prop.ValidRange = (1.0, 4.0)
    
        # Create a new group named Group 2.
        group_two = provider.AddGroup("My Properties")
    
        options_prop = group_two.AddProperty("Result Selection", Control.Options)
        options_prop.GetOptionsCallback= get_options_handler
        options_prop.IsValidCallback = dropDownValid
    
        # Add a scoping property to the second group created above
        scoping_prop = group_two.AddProperty("Scoping Property", "Scoping", "property_templates")
    
        ## Add an options property to the second group
        #options_prop = group_two.AddProperty("Options Property", Control.Options)
        #
        ## Add a couple options to the options property.
        #options_prop.Options = {1 : "Value 1", 2 : "Value 2"}
    
        # Connects the provider instance back to the object by setting the PropertyProvider member on this, 'this' being the 
        # current instance of the Python Code object.
        this.PropertyProvider = provider
    
    
    def get_options_handler(prop):
        global opt
        try:
            numOptions_beforeRefresh = len(opt)
        except:
            ExtAPI.Log.WriteMessage("Opt is not yet defined")
        opt = {}
        num_opt=1
        for comp in [child for child in ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.Result) if child.Parent == this.Parent]:
            opt[num_opt] = comp.Name
            num_opt+=1
        if prop.Value != None:
            if str(prop.Value) > str(len(opt)):
                prop.Value = None
        if "numOptions_beforeRefresh" in locals():
            if numOptions_beforeRefresh > len(opt):
                prop.Value = None
    
        return opt
    
    def dropDownValid(prop):
        if prop.Value==None:
            return False
        elif prop.ValueString.isnumeric() == True:
            return False
        else:
            return True