To prevent spam users, you can only post on this forum after registration, which is by invitation. If you want to post on the forum, please send me a mail (h DOT m DOT w DOT verbeek AT tue DOT nl) and I'll send you an invitation in return for an account.

How to change position (x,y) of a transition in a petri net

Dear Community,

I want to change the position of a manually generated transition in a petri net. The result should be a kind of enhanced petri net that shows with which confidence a certain activity in the log was predicted and the confidence of the second best guess. I can change other attributes, e.g. size via the attribute map of org.processmining.models.graphbased.directed.petrinet.elements.Transition , but there seem to be no such element for the position in the graph. IST.pdf shows how it looks right now, while SOLL.pdf illustrates how it is supposed to be.

Any help will be highly appreciated.

Kind regards,

Oliver
SOLL.pdf 122.6K
IST.pdf 123K

Answers

  • hverbeekhverbeek Posts: 436
    Dear Oliver,

    Your observation is correct, positions are not stored directly in the elements. Instead, a graph has an associated GraphLayoutConnection object where positions can be set (like other things, like linewidth and such). For a given net, you can get this object using the following snippet (assuming that context is your current PluginContext):

            try {
                layout = context.getConnectionManager().getFirstConnection(GraphLayoutConnection.class, context, net);
            } catch (ConnectionCannotBeObtained e) {
                layout = new GraphLayoutConnection(net);
            }

    In case such a connection does not exist yet, you might want to create one:

            GraphLayoutConnection layout = new GraphLayoutConnection(net);

    This layout object has a setPosition method that takes two parameters: the object of which the position should be set (the transition in your case) and a position (given as a Point2D object). By heart, this position should be the position of the upper left corner of the bounding box of the object.

    Kind regards,

    Eric.

  • OllyseusOllyseus Posts: 27
    edited June 2016
    Dear Eric,

    thank you very much for your quick, professional and helpful answer post.

    Unfortunately the following line leaving the layout variable with 'null' in try and it jumps to catch:                            
    layout=context.getConnectionManager().getFirstConnection(GraphLayoutConnection.class, context, net);

    Maybe it is because the net is not generated by my own plugin but by alphaminer that is invoked from mine and hence I might not have the correct context.

    I then created a new one like you suggested, but I wasn't able to get a position from it for the transaction 1 under which I want to place transaction 2, but instead a nullpointerexception

    Do you have any suggestions for fixing that?

    Kind regards,

    Oliver
    Post edited by Ollyseus on
  • hverbeekhverbeek Posts: 436
    Hi Oliver,

    It seems I forgot one statement: Adding the connection to the connection pool:

            GraphLayoutConnection layout = new GraphLayoutConnection(net);
            context.addConnection(layout);

    In the back, the context uses the connection manager, so the specific context instance is not important.

    If the net has been visualized, there should be a LayoutConenction for it... but you might not have visualized the results from the Alpha Miner. Also, when importing from a PNML file, this LayoutConenction will be created.

    Cheers,

    Eric.

  • hverbeekhverbeek Posts: 436
    Hi Oliver,

    You also might need to copy existing layout information from the old net to that of the new net. Creating the GraphLayoutConenction does not automatically fill it. Perhaps you can use the LayoutUtils class (from the PetriNets package) for this? In particular the copyLayout method seems useful.

    Cheers,

    Eric.
  • OllyseusOllyseus Posts: 27
    Dear Eric,

    thanks again for your good feedback. I tried to use the method you suggested, but the keypoint is that  I don't get the connection/layout from the old net, which is why I can not copy it to the new one.

    I attached a screenshot of the Error Message, and I'll try to find a way to solve this, and will post again if I found one.

    But do you have an idea why I can't get a connection? If more code is needed for a guess, I would be happy to post it.

    Cheers,

    Oliver
  • hverbeekhverbeek Posts: 436
    Hi Oliver,

    My guess is that the old Petri net has not been visualized. The visualizer takes care of constructing a GraphLayoutConnection if there is none yet, and of determining a layout.

    You might be running into a bit of a deadlock here. I guess you do not want to show the old Petri net, but you can only get positions of objects in that net after it has been layed out, and that only happens when it is shown. Therefore, to show the net net, you need to show the old net first.

    In the past, we have tried to visualize a Petri net 'off-screen', that is, to have it layed out without showing it on the screen. So far, we did not succeed :-(. If you succeed, we would definitely want to know :-).

    A workaround could be to create visualizer that first shows the old net, then rearranges the layout in the new net based on the now existing layout of the old net, and then replace the visualization of the old net by the visualization of the net. The old net might be shown to the user for some time, however.

    Cheers

    Eric.
  • OllyseusOllyseus Posts: 27
    edited June 2016
    Hi Eric,

    I wouldn't care so much if the original petri net would be shown first.

    I tried to implement your suggestion, but as I found out the copyLayout-Method is supposed to be invoked of a single node instead of a whole petri net (stated in its documentation).

    As I don't want just to reference the original petri net but have a real copy of it which I can change, I implemented a copy-method on my own, which copies each elements seperately (transactions, places, edges).

    It can be seen in the attached image. Unfortunately there is again an exception thrown when I want to add an arc between a transaction and a note, saying that one of the elements wouldn't be in the new net, but actually they are. Do you have any idea what the issue is here? I'm trying for hours without any progress...

    Furthermore I don't know how to visualize the original petri net first in the same plugin, so that I can use its layout. I thought it is only visualized when the plugin is finished (?)

    Thank you so much for your guidance, I would be lost otherwise :smiley:

    Best,

    Oliver

    PS: If you want to have a deeper look into the YourAlgorithm.java class, here is the whole code:  https://codeshare.io/r77wB



    EDIT: My guess is that the exception occurs because the place and transition in the new net are only copies and not the original ones, which is why the cannot be identified. But I don't how to solve the problem with the methods provided by the existing framework.
    Post edited by Ollyseus on
  • OllyseusOllyseus Posts: 27
    Dear Eric,

    I'm happy to tell you that I found a solution for this proble on my own. Instead of copying I just modified the original normal petri net, because I don't need the basic one anymore. Your tipp with the visualization was excellent, and after a while I figured out how to solve it. It even works off-screen! :)

    I will present my solution for you and for following readers.

    At first a layoutconnection is created with:

            GraphLayoutConnection layout = new GraphLayoutConnection(net);
            context.addConnection(layout);

    Afterwards the net which was generated by the alphaminer is "visualized", but this happens offscreen

            PetriNetVisualization v = new PetriNetVisualization();
            v.visualize(context, net);

    Now, position data is already accessible and changeable, as can be seen in my own method changepositions:

    private void changePosition(Petrinet net, PluginContext context, GraphLayoutConnection layout) {

            Iterator it = net.getTransitions().iterator();
           
            while(it.hasNext()){
                Transition curr = (Transition) it.next();
                if(curr.getLabel().equals("Sitting (0.29)")){
                   
                Iterator it2 = net.getTransitions().iterator();
               
                Transition stand = null;
               
                while(it2.hasNext()){

                    Transition curr2 = (Transition) it2.next();
                    if(curr2.getLabel().equals("Standing (0.61)")){
                        stand = curr2;
                    }
                }
           
                Point2D pos = layout.getPosition(stand);
               
                int x = (int) (pos.getX());
                int y = (int) (pos.getY() + 40);
               
                Point2D posSub =  new Point(x,y);
               
                layout.setPosition(curr, posSub);
            }
        }

    I hope this will help future developers a bit.

    Have a great day,
    Best,

    Oliver



Sign In or Register to comment.