How to integrate new UI elements to the plugin?

Hello.

I have been following all the steps suggested but I have been getting stuck here and there during the implementation. I do have some specific questions for my use case.

I have developed a plugin that imports a CSV file and as output it visualizes DFG (Directly follows Graph).

And also, I have a personal Java Project that reads the same CSV file and outputs some optimization recommendations and values to the user. This project also contains UI elements like Sliders, Dropdown lists and Text boxes using which user can enter the data and the output is dynamically printed in a Text Area.

My use case is to create a plugin that contains both DFG and the UI from my personal project.

Here are some questions regarding the same:
  1. According to the documents I have gone through about the ProMTool, I understood that there is a visualizer that is picking up the DFG graph using connections and outputs the visualization of the the graph as output. I would like to use the same visualizer but then also add the UI elements (as I have in my personal project). May I know is it possible?
  2. I would like to have an output of my new plugin to be something like in the image attached. I want to have the "DFG panel" as already implemented visualizer which is already developed. Alongside, I would also like to have the controls panel on right with UI elements (eg. sliders). When user interacts with there sliders, I want to have the values that change dynamically in "Values Panel". (Please Note: DFG graph remains constant). May I know if it possible to create such an output in the ProMTool.
  3. What is difference between requiredParameterLabels = { 0, 1 }, requiredParameterLabels = { 0 }....? What is effected by overloading the values like 0, 1, etc?
  4. Is there any inbuilt option for accommodating sliders etc? (like a widget or something that will hold the sliders and their functionality may be?

I know I could create a new visualizer with all the elements I want to have in it and show it as an output. But I don't have a clue how to write a visualizer for DFG from scratch. Hence, I would like to have the already implemented visualizer of DFG to be included in the usecase.

Also please refer to the image attached with the question. Help would be much appreciated since I got stuck with this issue since 2 months.

Thank you.
sample.jpeg 40.2K

Answers

  • hverbeekhverbeek Posts: 910
    Dear @ge82gop ,

    1. 2.

    Yes, this is possible. Basically, a visualizer plugin returns a JComponent, and I assume that your controls and values panels are also JComponents. Then you can create a new main component that contains the three panels in the configuration your figure shows. I would be using a TableLayout for this, but that is a matter of taste. Your new visualizer then returns this main component as its visualization. Somethins like follows:

    JComponent mainComponent = new JPanel();
    // Create layout with two rows and two columns.
    double size[][] = { { TableLayoutConstants.FILL, TableLayoutConstants.FILL }, { TableLayoutConstants.FILL, TableLayoutConstants.FILL } };
    mainComponent.setLayout(new (TableLayout(size));
    mainComponent.add(dfgPanel, "0, 0"); // Upper left
    mainComponent.add(valuesPanel, "0, 1"); // Lower left
    mainComponent.add(controlsPanel, "1, 0, 1, 1"); // Upper and lower right
    return mainComponent;

    If the user changes the controls, then you remove the DFG panel from the component, call the visualizer plugin for the new panel, and add it to the component as the new DFG panel:
    mainComponent.remove(dfgPanel);
    dfgPanel = // call DFG visualizer here
    mainComponent.add(dfgPanel, "0, 0");
    mainComponent.revalidate();
    mainComponent.repaint();
    3.

    In the Plugin annotation, you have declared a list of inputs (parameterLabels).  In the PluginVariant annotation you need to specify which of these inputs are required for this variant (this method). Here, {, 0, 1} indicates the inputs with indices 0 and 1. That means, your method should have three parameters: The PluginContext (always comes first), the parameters for the input at index 0, and the parameter for the input at index 1. If you use { 0 }, then you only need two parameters: The context and the parameter at index 0.

    4.

    The slickerbox library and the Widgets package contain a number of useful widgets that you could use. For a slider, you could use the NiceSlider from slickerbox. See below fopr a snippet. Note that the updateRight method here updates a visualizer like in your use case. In your case, this could be something like updateDfgPanel().
      final NiceSlider equivalenceSlider = SlickerFactory.instance().createNiceIntegerSlider("Equivalence", 0, 20,
                    100 - configuration.getEquivalenceThreshold(), Orientation.HORIZONTAL);
            equivalenceSlider.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    int value = 100 - equivalenceSlider.getSlider().getValue();
                    logSkeleton.setEquivalenceThreshold(value);
                    configuration.setEquivalenceThreshold(value);
                    logSkeleton.cleanPrePost();
                    updateRight();
                }
            });
    As a result, if the user changes the slider, the visualization will be updated.

    Kind regards,
    Eric.



  • ge82gopge82gop Posts: 13
    edited March 6
    Hello Mr. Eric,

    Thank you so much for your wonderful suggestions. They worked perfectly concerning my UI requirements (placement of the different panels is bit tricky but I will figure it out). However I am unable to figure out one requirement still. 

    I am using a jar file "InductiveMinerDepricated". I include it in my build path as external jar files. The reason I am using this is to use the in-built methods to obtain DFG (Directly Follows Graph) from XLog. Here is how I am doing it.
    public class BlockProM {
    @Plugin(name = "BlockProm", parameterLabels = { "CSV" }, returnLabels = { "DFG " }, returnTypes = {
    Dfg.class }, userAccessible = true, help = "This is BlockPromTool DFG")
    @UITopiaVariant(affiliation = "Universit", author = "Manoj", email = "manoj@outlook.com")
    public Dfg generateDFG(UIPluginContext context, CSVFile csvFile)
    throws ConnectionCannotBeObtained {
    XLog xlog = context.tryToFindOrConstructFirstNamedObject(XLog.class, "Convert CSV to XES", null, null, csvFile); Dfg dfg = context.tryToFindOrConstructFirstNamedObject(Dfg.class, "Convert log to directly follows graph", null,null, xlog); return dfg;
    }
    }
    When I run the tool with above snippet, "PromTool" automatically recognises the "visualiser" which takes "DFG" as it's input and outputs a JComponent containing "graph". My problem is that I am unable to figure out which "visualiser" (the method name or the class name) takes DFG as it's input and returns a JComponent containing the graph as its output.

    You have suggested me to do this in the above comment,
    dfgPanel = // call DFG visualizer here 
    But I personally don't know how can I visualise the DFG since I am using the methods in the JAR files to develop DFG (which is just a single line of code).

    However, after some debugging, I found one line which I thought might be helpful
    graphPanel = ProMJGraphVisualizer.instance().visualizeGraph(context, graph);
    But the above method takes "PluginContext" and "DirectedGraph" as it's input and returns a JComponent as an output and can be easily added to UI. But, in my case, I have "UIPluginContext" and "DirectlyFollowsGraph" (whose structure is different from DirectedGraph).

    May I know if there is any method like "ProMJGraphVisualizer.instance().visualizeGraph" which takes in "DirectlyFollowsGraph" and "UIPluginContext" as inputs and returns a Jcomponent that contains a graph as an output? 

    (I believe there should be one since the tool is visualising DFG if used directly as mentioned in the above piece of code)


    Post edited by ge82gop on
  • hverbeekhverbeek Posts: 910
    Hi,

    The visualizer for the Dfg (org.processmining.plugins.inductiveminer2.plugins.DfgMsdVisualisationPlugin) can be found in the InductiveMiner package. Provided a DirectlyFollowsGraph, it returns a DotPanel. I do not know by heart how to grab the contents of this panel and save it to some file.

    Given that a visualizer plugin is also a plugin, you can also try to call the visualizer like a plugin:
    dotPanel = (DotPanel) context.tryToFindOrConstructFirstNamedObject(JComponent.class, "Directly follows model visualisation", null, null, dfg);
    Details on the DotPanel can be found in the GraphViz package.

    When using ProM in a headless fashion like you are doing, there may be not much use in calling something like ProMJGraphVisualizer.instance().visualizeGraph (Widgets package). The JGraph-based visualizer only compute the layout of the graph when visualized on the screen. As a result, this would result in a Dfg without any layout.

    Kind regards,
    Eric.










  • ge82gopge82gop Posts: 13
    edited March 8
    Hello Mr. Eric,

    Thank you for your suggestion. I have looked into it and tried to implement it. However, I get a popup with "NullPointerException" and in the error stack trace, it shows an error "ConnectionCannotBeObtained". Please see the below codes that I am using.

    I am generating a DFG using the code below and also passing the same DFG to the previously suggested "DOTPANEL" line of code.

    I have also tried returning "DotPanel.class" instead of "JComponent.class" but I got the same error.

    public class BlockPromModel {
    private final Dfg dfg;
    private final DotPanel dfgPanel;
    public BlockPromModel(UIPluginContext context, XLog xlog, CSVFile file) throws ConnectionCannotBeObtained {
    dfg = context.tryToFindOrConstructFirstNamedObject(Dfg.class, "Convert log to directly follows graph", null,null, xlog);
    dfgPanel = (DotPanel) context.tryToFindOrConstructFirstNamedObject(JComponent.class, "Directly follows model visualisation", null, null, dfg);
    }
    public DotPanel getDfgPanel() {
    return dfgPanel;
    }
    }


    Below is the error trace I get. (Attached as an image)


    May I know how can I resolve this error?
    Post edited by ge82gop on
  • hverbeekhverbeek Posts: 910
    edited March 9

    I guess this does not work because the JComponent is not considered to be a resource. As a result of this, the plugin cannot be invoked this way. The alternative is to call the visualizer directly:
    DotPanel dfgPanel = org.processmining.plugins.inductiveminer2.plugins.DfgMsdVisualisationPlugin.fancy(dfg);
    Kind regards,
    Eric.

    Post edited by hverbeek on
  • ge82gopge82gop Posts: 13
    edited March 14
    Hello Mr. Eric,

    Thank you so much for your reply. The particular line that you have mentioned in the above comment didn't work (Reason: it expects class "DirectlyFollowsGraph", but my dfg variable belongs to the class Dfg). But, your suggestion helped me to know how to find the visualizer that I require and use it. The suggestion helped a lot. I found the visualizer and the line below did the trick.

    Dotpanel dfgPanel = org.processmining.plugins.inductiveVisualMiner.plugins.GraphvizDirectlyFollowsGraph.visualise(dfg);
    And I have small follow-up question: 

    Like web development (where the application reloads as soon as we save the changes), is there any way that the PromTool UI also reloads as soon as I make save the changes in the file?

    Currently I am re-running the whole PromPlugin to see the changes I do which takes time to see the output since it involves many steps that I have to perform beforehand in the tool, to reach to that point/output to see the changes I made in the visualiser. Hopefully, if there is some setting/option or a flag that I can set, which will auto reload the Plugin for me as soon as I save the file, and I need not re-run the plugin and do all the steps again and again, will be helpful.
    Post edited by ge82gop on
  • hverbeekhverbeek Posts: 910
    Hello @ge82gop ,

    There is no such monitoring mechanism in ProM. You would have to implement a visualizer plugin that actively monitors the file, and that refreshes the visualization if the file has been changed.

    Regular plugins in ProM run for some time, and disappear after they have run.

    Kind regards,
    Eric.
  • ge82gopge82gop Posts: 13
    Hello Mr. Eric,

    With your wonderful guidance through your answers for my previous questions, I would have been able to come very far on my task including DFG along with some UI components like sliders to the output.

    However, I am stuck with a very small issue that I am unable to get my head around.

    My final output has a typical layout that is divided into grids. To be specific:
    1. My main root panel (highlighted in pink) is a panel with GridBagLayout divided into 2 panels. Left panel (contains graph Highlighted in Green) with 40% of width and Right panel(Highlighted in Blue) with 60% of width.
    2. Right Panel (containing graph) as set to have BorderLayout.
    3. LeftPanel (Highlighted in blue) is set to have GridLayout with 2 rows and 1 column. First row (Upper panel in the main right panel highlighted in brown) contains a panel that has BorderLayout and a tabbed pane (each containing JTable with scrollpane) in it. Second row (Lower panel in the main right panel highlighted in brown) also has BorderLayout and a tabbed pane in it.
    However, in the 2nd screenshot that I have attached, when the Tab "Default Optimizations" is selected in the lower tabbed pane in the right panel, the whole layout seems to be ideal to my plan.

    But when "Rate Control" tab is selected in the lower tabbed pane on the right panel, the left panel (containing graph) is squeezed. And also, whenever I add data to the tabs of the lower tabbed pane, the left panel (containing graph) is getting squeezed.

    Do you have any suggestions of how I can make the grid size constant despite of adding data to the tabs of the lower tabbed pane? 

    I couldn't attach the images here. I am not sure why. Please find the screenshot in this link.

    [1] Layouts highlighted
    [2] Before Graph Panel is Squeezed
    [3] Graph Panel is Squeezed

    Kind regards,
    Manoj.
  • hverbeekhverbeek Posts: 910

    My guess is that this is because the component for the Rate control is too wide to fit your ideal layout. You could try to set the maximal width for this component, but basically you would need to know how wide the entire root panel is.

    I would use a TableLayout (see https://www.oracle.com/java/technologies/tablelayout.html) instead of the nested GridBagLayout. With the TableLayout you can fix your ratios of 40%-60% and 50%-50% nicely. Something like follows (using your colors to identify the components):

    double size[][] = { { TableLayoutConstants.Fill,  TableLayoutConstants.Fill,  TableLayoutConstants.Fill,  TableLayoutConstants.Fill,  TableLayoutConstants.Fill }, {  TableLayoutConstants.Fill,  TableLayoutConstants.Fill } };
    pinkPanel.setLayout(new TableLayout(size));
    pinkPanel.add(greenPanel, "0, 0, 1, 1");
    pinkPanel.add(topRedPanel, "2, 0, 4, 0");
    pinkPanel.add(bottomRedPanel, "2, 1, 4, 1");

    This will fix the sizes of these components, and as a result the Rate control component will be forced to use a less wide space.

    Kind regards,
    Eric.








  • ge82gopge82gop Posts: 13
    Hello Mr. Eric,

    Thank you so much for the suggestion. The solution you provided works flawlessly as I wanted it to be. 

    Kind Regards,
    Manoj.
Sign In or Register to comment.