PDA

View Full Version : how to make min and max values of spectrogram dynamical?



rambo83
1st March 2010, 12:32
Hello,

I wonder whether it is possible to get the actual min and max range values of spectrogram and not to set them manually, like I do it now (see the code below). I mean, after the data for spectrogram was calculated, then the max and min values should be known, right? How to get them then? I don't want to set the range manually, but it should be done according to the current data. Help me please.

best regards,



typedef double (*benchFunc)(vector<double>); // definition of function pointer for benchmark function

// this class creates the data of objective function

class SpectrogramData: public QwtRasterData
{
public:
SpectrogramData(benchFunc b, double rang1[2], double rang2[2], int dims[2], vector<double> fix_vec , unsigned dimens, QwtDoubleInterval interval ):
QwtRasterData(QwtDoubleRect(rang1[0], rang2[0], rang1[1]- rang1[0], rang2[1]- rang2[0]))
{
MybenchFunc = b;
valuesRange = interval; //<<<<<<<<<< here it is set manually
dim_ind[0] = dims[0]; dim_ind[1] = dims[1];
dimensions = dimens;
fix_vals = fix_vec;
}

virtual QwtRasterData *copy() const
{
return new SpectrogramData(*this);
}

virtual QwtDoubleInterval range() const //<<<<<<<<<<< here the range will be returned
{
return valuesRange;
}

virtual double value(double x, double y) const
{
vector<double> coords;
coords = vector<double>(dimensions, 0); // create a vector of size "dimensions" containing zeros
if(dimensions > 2){ // if the benchmark function has more dimensions than 2, then...
for(unsigned i=0 ; i < dimensions ; ++i){
coords[i] = fix_vals[i]; // ... copy first all fixed values into vector and then...
}
coords[dim_ind[0]] = x; // replace the values of dimensions to be visualized
coords[dim_ind[1]] = y;
}
else{
coords[dim_ind[0]] = x;
coords[dim_ind[1]] = y;
}
const double result = MybenchFunc( coords);
return result;
}

private:

benchFunc MybenchFunc; // function pointer for benchmark function
QwtDoubleInterval valuesRange;
int dim_ind[2];
unsigned dimensions;
vector<double> fix_vals;
};

rambo83
1st March 2010, 15:24
Hello,

I tried to get it dynamical by manipulating the membver variable, but it is obviously not allowed due to const functions. How can I avoid the error?

plot.cpp: In member function 'virtual double SpectrogramData::value(double, double) const':
plot.cpp:75: error: no matching function for call to 'QwtDoubleInterval::setMinValue(double) const'
/data/home/vanselm/.HRI/Proxy/hri/tree/External/qwt/5.2.0/include/qwt_double_interval.h:171: note: candidates are: void QwtDoubleInterval::setMinValue(double) <near match>
plot.cpp:78: error: no matching function for call to 'QwtDoubleInterval::setMaxValue(double) const'
/data/home/vanselm/.HRI/Proxy/hri/tree/External/qwt/5.2.0/include/qwt_double_interval.h:181: note: candidates are: void QwtDoubleInterval::setMaxValue(double) <near match>
make[1]: *** [../obj/linux-amd64-gcc-lsb31/plot.o] Error 1
make: *** [obj_qt] Error 2

here is my current code:


typedef double (*benchFunc)(vector<double>); // definition of function pointer for benchmark function

// this class creates the data of objective function

class SpectrogramData: public QwtRasterData
{
public:
SpectrogramData(benchFunc b, double rang1[2], double rang2[2], int dims[2], vector<double> fix_vec , unsigned dimens, QwtDoubleInterval interval ):
QwtRasterData(QwtDoubleRect(rang1[0], rang2[0], rang1[1]- rang1[0], rang2[1]- rang2[0]))
{
MybenchFunc = b;
//valuesRange = interval;
dim_ind[0] = dims[0]; dim_ind[1] = dims[1];
dimensions = dimens;
fix_vals = fix_vec;
valuesRange.setInterval(0 , 0);
}

virtual QwtRasterData *copy() const
{
return new SpectrogramData(*this);
}

virtual QwtDoubleInterval range() const
{
return valuesRange;
}

virtual double value(double x, double y) const
{
vector<double> coords;
coords = vector<double>(dimensions, 0); // create a vector of size "dimensions" containing zeros
if(dimensions > 2){ // if the benchmark function has more dimensions than 2, then...
for(unsigned i=0 ; i < dimensions ; ++i){
coords[i] = fix_vals[i]; // ... copy first all fixed values into vector and then...
}
coords[dim_ind[0]] = x; // replace the values of dimensions to be visualized
coords[dim_ind[1]] = y;
}
else{
coords[dim_ind[0]] = x;
coords[dim_ind[1]] = y;
}
double result = MybenchFunc( coords);
if(result < valuesRange.minValue()){
valuesRange.setMinValue((double)result);
}
if(result > valuesRange.maxValue()){
valuesRange.setMaxValue((double)result);
}
return result;
}

private:

benchFunc MybenchFunc; // function pointer for benchmark function
QwtDoubleInterval valuesRange;
int dim_ind[2];
unsigned dimensions;
vector<double> fix_vals;
};

yodasoda
2nd March 2010, 08:00
what you need is the QValidator Class. More precisely you are going to use QIntValidator and QDoubleValidator.

rambo83
2nd March 2010, 08:21
I have read the documentation of QValidator class and cannot see any relation to my problem here.

Actually, I have already the idea how to get the value ranges dynamically (see the code in my second post), where I just check whether the new calculated value is larger than the maxValue of range or smaller than minValue. The only problem, which occurs here is the fact, that I cannot manipulate the member variable "valuesRange" because all member functions are const. It would be nice, if someone could tell me a trick how to achieve it. Thank you.

best regards,

Vitali

MSUdom5
2nd March 2010, 17:28
You could use mutable:


mutable QwtDoubleInterval valuesRange;

Then you can modify valuesRange within a const function. This is a dirty solution, but it works. :)

rambo83
9th March 2010, 08:52
Thank you for this hint! After making the member variable "mutable" the code can be compiled without errors, but nothing happen, thus nothing is displayed on the spectrogram. What is wrong then?

KosyakOFF
10th March 2010, 10:02
But range() function of QwtRasterData class is virtual. And Im pretty sure that you have your own derived class, Why don't you just overload range() function to give new max/min values?

rambo83
16th March 2010, 08:05
Hello,

I have figured out the problem, why I cannot calculate the value ranges dynamically.
The problem is that the function "value", which calculates the values for x1 and x2 coordinates and stores the min and max value range is executed after the function "range", which gives the min and max boundaries of possible values. In other words, the functions are executed in wrong order. For my understanding, if I set data for spectrogram, then the values for all coordinates should be calculated, so that if in the next step I want to get the values range, then they are already calculated correctly. However, if I execute the code below, then first the function "range" and then "value" is called.

Could you help me please to force the execution in another order?

Thank you


d_spectrogram = new QwtPlotSpectrogram();

// load the corresponding struct with optimization problem
//
optProbList = _mf->getOptProblems();
unsigned index= _mf->objFunction;
double (*f)(vector<double> coord) = optProbList[index]->benchmark;
double rangex1[2] = {optProbList[index]->min[_mf->dim_indices[0]], optProbList[index]->max[_mf->dim_indices[0]]};
double rangex2[2] = {optProbList[index]->min[_mf->dim_indices[1]], optProbList[index]->max[_mf->dim_indices[1]]};
QwtDoubleInterval value_interval = optProbList[index]->valuesRange;

Model *neuralNet = _mf->getMetaModel();
bool useMet = _mf->isMetaModelUsed();

// here the data for ploting is set from the function "SpectrogramData()", in which the data is generated
//
d_spectrogram->setData(SpectrogramData((*f), rangex1, rangex2, _mf->dim_indices , _mf->fixed_values, optProbList[index]->dimensions, value_interval, neuralNet, useMet));
d_spectrogram->attach(this); // attach the data to the plot widget

// set the colors for intensity values
//
QwtLinearColorMap colorMap(Qt::darkCyan, Qt::red);
colorMap.addColorStop(0.25, Qt::cyan);
colorMap.addColorStop(0.5, Qt::green);
colorMap.addColorStop(0.75, Qt::yellow);
d_spectrogram->setColorMap(colorMap);

// A color bar on the right axis
//
QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight);
rightAxis->setTitle("Intensity");
rightAxis->setColorBarEnabled(true);
rightAxis->setColorMap(d_spectrogram->data().range(), d_spectrogram->colorMap()); //<<< here values range are required, but is not calculated yet

// set the scale of color bar
//
setAxisScale(QwtPlot::yRight,
d_spectrogram->data().range().minValue(), //<<< here values range are required, but is not calculated yet
d_spectrogram->data().range().maxValue() ); //<<< here values range are required, but is not calculated yet
enableAxis(QwtPlot::yRight);

Uwe
16th March 2010, 08:43
The range is something, that has to correspond to the color map - but it has nothing to do with the current min/max values of your data set in specific area. But even if you want to have it this way calculating it in QwtRasterData::value is completely the wrong place.

But your main problem is, that you insist on not trying to understand what you are doing. With this attitude you can't be surprised, that nobody answers to your postings anymore.

Uwe

rambo83
16th March 2010, 09:30
I know that the range corresponds to the colormap. This is exactly the reason why I want it to be dynamical. Otherwise, I have to determine the possible range by plotting the function in Matlab and see what is the global minimum and maximum.

I could certainly calculate the min and max range by iterating through x1 and x2 space and determine the range in that way, but then I would have to use 2 FOR loops, which would be very time consuming. Therefore, I had the idea to calculate it within the function "value()" because there all values are calculated anyway. Unfortunately, it is not that easy, as I thought.

@Uwe: How to learn, if nobody answers my questions? ;-)