dennis vlaar
dennis vlaar

Reputation: 53

How to make custom graph that maps duration of events and amount of events?

I have a dataset that shows contact events between bloodcells over time. I have data on which frame an event starts and when it ends. The dataframe looks like this:

Cell_id1 Cell_id2 Begin_frame End_frame
ID_1 ID_10 4 5
ID_1 ID_10 12 18
ID_1 ID_11 16 20
ID_1 ID_12 22 24

The graph I want to make will look like this: graph

The green dots with line will represent Cell_id1, and the red dots with lines will be the Cells in Cell_id2. The X-axis represents frames, so each dot is a new frame. Each time there is a contact event with a different cell, it will move up 1 on the y-axis.

You can ignore the red circles after the green dots.

I have no idea how to do this, so even a hint in the good direction would be great!

Upvotes: 0

Views: 83

Answers (1)

ravenspoint
ravenspoint

Reputation: 20596

The first step will be to work out the positions on the Y axis.

Calculate the number of different ids there are in the second column ( in your example there are 3 ) Assign each id to an integer in order of first contact. In your example you will get

contacted cell position on Y-axis
ID10 1
ID11 2
ID12 3

Here is the psuedo code to draw the graph. Note that it places a dot at the end frame of a contact.

LOOP over contacted cells
   SET contact false
   LOOP over frames
      IF begin frame
         SET contact true
      IF contact true
          X = time frame number
          Y = position on Y from above table
          Draw red dot at X,Y
      IF end frame
          SET contact false

Here is a C++ implementation of this algorithm.

Step 1: Assigning a unique index to each call pairs that come into contact

void cContacts::indexContacts()
{
    for (auto &contact : myContact)
    {
        if (std::find(
                myUnique.begin(),
                myUnique.end(),
                contact) == myUnique.end())
            myUnique.push_back(contact);
    }
}

Step 2: draw dots using above psuedo code algorithm

void cContacts::placeDots()
{
    // loop over contacts
    for (auto &contact : myContact)
    {
        // track whether we are in contact
        bool incontact = false;

        // loop over frames
        for (int frame = 1; frame <= mymaxframe; frame++)
        {
            if (frame == contact.start)
                incontact = true;

            if (incontact)
            {
                // in contact - work out y position of dot from unique index
                int yPosition = std::find(
                                    myUnique.begin(),
                                    myUnique.end(),
                                    contact) -
                                myUnique.begin() + 1;

                // draw the dot - here I just output the co=-ordinates
                std::cout << "dot at " << frame << "," << yPosition << "\n";
            }

            if (frame == contact.end)
                incontact = false;
        }
    }
}

The output looks like this

dot at 4,0
dot at 5,0
dot at 12,0
dot at 13,0
dot at 14,0
dot at 15,0
dot at 16,0
dot at 17,0
dot at 18,0
dot at 16,1
dot at 17,1
dot at 18,1
dot at 19,1
dot at 20,1
dot at 22,2
dot at 23,2
dot at 24,2

Using these locations to draw the red circles

enter image description here

You can find the complete code for this application at https://github.com/JamesBremner/bloodcell2

Upvotes: 1

Related Questions