QCustomPlot Discussion and Comments

Showing IP address on axisReturn to overview

Hi,

For now i have x-axis as time, y-axis as IP addresses. It's a program working on pcap files, and I'm plotting a graph to show how many connection attempts are there from the host PC based on time. setData() only seems to take in QVector<double>, which I had to manually convert IP addresses from xxx.xxx.xxx.xxx format to integers format such as 1855919686. Now from integers, I had to convert it to double variable, which is saved and displayed on the graph as 1.8559*10^9.

Is there a way that I could convert it back to xxx.xxx.xxx.xxx and display on the graph axis? Or better, is there a way that it could take in string for the y-axis in my case?

This is how I am currently doing it:

QVector<double> x2(i), y2(i);

for(int o = 0; o <= i; o++){
    //unsigned int arrayIPxTime[o][0] holds value of timesecond, [o][1] holds value of IP in integer format
    double dSec = arrayIPxTime[o][0] - startSecond;
    double dMin = dSec/60;
    double ipv4addr = arrayIPxTime[o][1];
    x2[o] = dMin;
    y2[o] = ipv4addr;
}

ui->widget_graph2->addGraph(0);
QCPScatterStyle myScatter;
myScatter.setShape(QCPScatterStyle::ssDisc);
myScatter.setSize(2);
ui->widget_graph2->graph(0)->setScatterStyle(myScatter);
ui->widget_graph2->graph(0)->setLineStyle(QCPGraph::lsNone);
ui->widget_graph2->graph(0)->setData(x2, y2);
ui->widget_graph2->xAxis->setRange(0, totalmin+(totalmin*0.05));
ui->widget_graph2->xAxis->setLabel("Time (min)");
ui->widget_graph2->yAxis->setRange(0, totalIP+(totalIP*0.05));
ui->widget_graph2->yAxis->setLabel("Connection Attempts (IP)");
ui->widget_graph2->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
ui->widget_graph2->replot();       

Thank you so so so much for any help!

Here is my contact: lee_weixian@hotmail.com

Hello Ken,

I got quite the same need. My approach has been:
* get the list of y-axis elements ie your IPs (you can use std::unique or a map for example)
* assign an internal ID (your y-axis value on the plot) to each y-axis element
* when plotting, convert your y-axis element to internal ID

Hope it helps.

@Juleing, thank you so much!

Could you give me any hint on how to do the "internal ID" thing please? Can't find any related info in the documentation.

Actually I also realised that setData() also takes in a QDataMap, but I have no idea at all how to work with QDataMap. I tried searching on the Internet but couldn't find any clues :(

Thanks again so much! :))

Let's take an example:
* 172.20.1.25 at t1
* 172.20.1.24 at t2
* 172.20.1.26 at t3
* 172.20.1.24 at t4

List of unique IPs (have a look at std::unique for example) for which you have to assign your own ID, up to you to choose the strategy (you can choose to get ordered IPs to build the ID with 0 for lowest IP):
* 172.20.1.24 => ID = 0 (because lowest IP)
* 172.20.1.25 => ID = 1 (because a bit higher IP)
* 172.20.1.26 => ID =2 (because highest IP)

Then, loop over you IPs & times and replace the IP by previous index.
for(IPs) {
x = time
y = convertIPToID(IP)
}

Is that easier to undestand with this example?

Julieng,

I understand the part where you say to assign a double ID purposely for assigning the QVector<double>. That actually could solve the QVector<double> issue! Thanks!

But how could I convert the ID back to xxx.xxx.xxx.xxx format to make the graph display xxx.xxx.xxx.xxx axis and coordinates? Did I misunderstand your sentence when plotting, convert your y-axis element to internal ID in your previous post?

Really thanks a lot!

Sounds like a good case for an own QCPAxisTicker subclass. Have a look at the other subclasses that are already part of QCP (and of course the QCPAxisTicker documentation), for how to make own subclasses.

In your case, you could just reimplement getTickLabel, and there convert your double (which practically is your int IP address) to the corresponding string that will be shown as tick label.

If you want to prevent fractional IPs, which the default implementation of getTickStep would try to produce, just reimplement getTickStep and make sure it only returns integer tick steps (by calling the base class getTickStep and making sure any tick step < 1 is rounded up to 1.0, and any other tick steps are rounded to the nearest integer).

Should be relatively easy to implement, I might turn this into a tutorial for making own axis tickers.

Ok, I better understand your question. I have done a QCPAxisTickerText and used addTick(internal ID, IP sting). Not as elegant solution as DerManu's but working well in my case :-)

Thanks Julieng and Dermanu.

Dermanu, could you please give a short example on how to use getTickLabel to solve my issue? Because I tried searching and really couldn't find any detailed explanation of this function in the documentation.

Really appreciate a lot for your help!

Did you look at these parts of the QCPAxisTicker documentation?
http://www.qcustomplot.com/documentation/classQCPAxisTicker.html#a8201eb4aa8be192bf786b126eb5ee089
http://www.qcustomplot.com/documentation/classQCPAxisTicker.html#axisticker-subclassing