Reputation: 53
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:
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
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
You can find the complete code for this application at https://github.com/JamesBremner/bloodcell2
Upvotes: 1