void PlotWidget::drawData( const ChartDataIndex &index, const ChartAxisIndex &axisSet ) { kDebug()<<index.number()<<index.userData; QVariantList data; int axisCount = model.axisCount( axisSet ); for ( int j = 0; j < axisCount; ++j ) { ChartAxisIndex axis = model.axisIndex( j, axisSet ); if ( model.hasAxisChildren( axis ) ) { kDebug()<<"multiple axis"; } else { data << model.data( index, axis ); } } kDebug()<<data; Q_ASSERT( data.count() == 2 ); QVariantList x = data[0].toList(); QVariantList y = data[1].toList(); QVariant color = model.data( index, Qt::ForegroundRole ); KPlotObject *kpo = new KPlotObject( color.value<QColor>(), KPlotObject::Lines ); for (int i = 0; i < y.count(); ++i ) { kDebug()<<"Add point:"<<x[i].toInt() << y[i].toDouble(); kpo->addPoint( x[i].toInt(), y[i].toDouble() ); kpo->setShowLines(true); } addPlotObject( kpo ); }
void JMoonTool::initPlotObjects() { KPlotObject *orbit[4]; KPlotObject *jpath; long double jd0 = ksw->data()->ut().djd(); KSSun *ksun = (KSSun*)ksw->data()->skyComposite()->findByName( "Sun" ); KSPlanet *jup = (KSPlanet*)ksw->data()->skyComposite()->findByName( i18n("Jupiter") ); JupiterMoons jm; pw->removeAllPlotObjects(); orbit[0] = new KPlotObject( colIo, KPlotObject::Lines, 1.0 ); orbit[1] = new KPlotObject( colEu, KPlotObject::Lines, 1.0 ); orbit[2] = new KPlotObject( colGn, KPlotObject::Lines, 1.0 ); orbit[3] = new KPlotObject( colCa, KPlotObject::Lines, 1.0 ); jpath = new KPlotObject( colJp, KPlotObject::Lines, 1.0 ); QRectF dataRect = pw->dataRect(); double dy = 0.01*dataRect.height(); //t is the offset from jd0, in days. for ( double t=dataRect.y(); t<=dataRect.bottom(); t+=dy ) { KSNumbers num( jd0 + t ); jm.findPosition( &num, jup, ksun ); //jm.x(i) tells the offset from Jupiter, in units of Jupiter's angular radius. //multiply by 0.5*jup->angSize() to get arcminutes for ( unsigned int i=0; i<4; ++i ) orbit[i]->addPoint( 0.5*jup->angSize()*jm.x(i), t ); jpath->addPoint( 0.0, t ); } for ( unsigned int i=0; i<4; ++i ) pw->addPlotObject( orbit[i] ); pw->addPlotObject( jpath ); }
void JMoonTool::initPlotObjects() { KPlotObject *orbit[4]; KPlotObject *jpath; long double jd0 = ksw->data()->ut().djd(); KSSun *ksun = (KSSun*)ksw->data()->PCat->findByName( "Sun" ); KSPlanet *jup = (KSPlanet*)ksw->data()->PCat->findByName( "Jupiter" ); JupiterMoons jm; if ( pw->objectCount() ) pw->clearObjectList(); orbit[0] = new KPlotObject( "io", colIo, KPlotObject::CURVE, 1, KPlotObject::SOLID ); orbit[1] = new KPlotObject( "europa", colEu, KPlotObject::CURVE, 1, KPlotObject::SOLID ); orbit[2] = new KPlotObject( "ganymede", colGn, KPlotObject::CURVE, 1, KPlotObject::SOLID ); orbit[3] = new KPlotObject( "callisto", colCa, KPlotObject::CURVE, 1, KPlotObject::SOLID ); jpath = new KPlotObject( "jupiter", colJp, KPlotObject::CURVE, 1, KPlotObject::SOLID ); double dy = 0.01*pw->dataHeight(); //t is the offset from jd0, in hours. for ( double t=pw->y(); t<=pw->y2(); t+=dy ) { KSNumbers num( jd0 + t/24.0 ); jm.findPosition( &num, jup, ksun ); //jm.x(i) tells the offset from Jupiter, in units of Jupiter's angular radius. //multiply by 0.5*jup->angSize() to get arcminutes for ( unsigned int i=0; i<4; ++i ) orbit[i]->addPoint( new DPoint( 0.5*jup->angSize()*jm.x(i), t ) ); jpath->addPoint( new DPoint( 0.0, t ) ); } for ( unsigned int i=0; i<4; ++i ) pw->addObject( orbit[i] ); pw->addObject( jpath ); }
void KTouchStatistics::updateChartTab() { // remove all current chart objects chartWidget->clearObjectList(); // if no lecture data is available, return if (m_allStats.m_lectureStats.count()==0 || m_lectureIndex >= m_allStats.m_lectureStats.count()) return; // what kind of chart is required? if (levelsRadio->isChecked()) { // TODO : nothing yet } else { // find correct lecture index QMapConstIterator<KURL, KTouchLectureStats> it = m_allStats.m_lectureStats.begin(); int index = m_lectureIndex; while (index-- > 0) ++it; std::vector< std::pair<double, double> > data; QString caption = "Session data"; switch (buttonGroup2->selectedId()) { case 0 : // words per minute // loop over all session data entries in *it and store words per minute data for (QValueVector<KTouchSessionStats>::const_iterator session_it = (*it).m_sessionStats.begin(); session_it != (*it).m_sessionStats.end(); ++session_it) { double t = (*session_it).m_elapsedTime; double wpm = (t == 0) ? 0 : (*session_it).m_words/t*60.0; double tp = (*session_it).m_timeRecorded.toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, wpm) ); } // add current session if selected lecture matches if (m_currentIndex == m_lectureIndex && m_currSessionStats.m_elapsedTime != 0) { double t = m_currSessionStats.m_elapsedTime; double wpm = m_currSessionStats.m_words/t*60.0; double tp = QDateTime::currentDateTime().toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, wpm) ); } chartWidget->LeftAxis.setLabel( i18n("Words per minute") ); chartWidget->LeftAxis.setLabelFormat(0, 'f', 0); break; case 1 : // chars per minute // loop over all session data entries in *it and store chars per minute data for (QValueVector<KTouchSessionStats>::const_iterator session_it = (*it).m_sessionStats.begin(); session_it != (*it).m_sessionStats.end(); ++session_it) { double t = (*session_it).m_elapsedTime; double cpm = (t == 0) ? 0 : (*session_it).m_correctChars/t*60.0; double tp = (*session_it).m_timeRecorded.toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, cpm) ); } // add current session if (m_currentIndex == m_lectureIndex && m_currSessionStats.m_elapsedTime != 0) { double t = m_currSessionStats.m_elapsedTime; double cpm = m_currSessionStats.m_correctChars/t*60.0; double tp = QDateTime::currentDateTime().toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, cpm) ); } chartWidget->LeftAxis.setLabel( i18n("Characters per minute") ); chartWidget->LeftAxis.setLabelFormat(0, 'f', 0); break; case 2 : // correctness // loop over all session data entries in *it and store correctness data for (QValueVector<KTouchSessionStats>::const_iterator session_it = (*it).m_sessionStats.begin(); session_it != (*it).m_sessionStats.end(); ++session_it) { double tc = (*session_it).m_totalChars; double corr = (tc == 0) ? 0 : (*session_it).m_correctChars/tc; double tp = (*session_it).m_timeRecorded.toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, corr) ); } // add current session if (m_currentIndex == m_lectureIndex && m_currSessionStats.m_totalChars != 0) { double tc = m_currSessionStats.m_totalChars; double corr = m_currSessionStats.m_correctChars/tc; double tp = QDateTime::currentDateTime().toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, corr) ); } chartWidget->LeftAxis.setLabel( i18n("Correctness") ); chartWidget->LeftAxis.setLabelFormat(0, 'g', 1); break; case 3 : // skill // loop over all session data entries in *it and store correctness data for (QValueVector<KTouchSessionStats>::const_iterator session_it = (*it).m_sessionStats.begin(); session_it != (*it).m_sessionStats.end(); ++session_it) { double tc = (*session_it).m_totalChars; double corr = (tc == 0) ? 0 : (*session_it).m_correctChars/tc; double t = (*session_it).m_elapsedTime; double cpm = (t == 0) ? 0 : (*session_it).m_correctChars/t*60.0; double skill = corr*cpm; double tp = (*session_it).m_timeRecorded.toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, skill) ); } // add current session if (m_currentIndex == m_lectureIndex && m_currSessionStats.m_totalChars != 0 && m_currSessionStats.m_elapsedTime != 0) { double tc = m_currSessionStats.m_totalChars; double corr = m_currSessionStats.m_correctChars/tc; double t = m_currSessionStats.m_elapsedTime; double cpm = m_currSessionStats.m_correctChars/t*60.0; double skill = corr*cpm; double tp = QDateTime::currentDateTime().toTime_t()/(3600.0*24); data.push_back(std::make_pair(tp, skill) ); } chartWidget->LeftAxis.setLabel( i18n("Skill") ); chartWidget->LeftAxis.setLabelFormat(0, 'f', 0); break; default : return; } // Create plot object for session statistics KPlotObject * ob; if (data.size() <= 1) return; ob = new KPlotObject(caption, "red", KPlotObject::CURVE, 2, KPlotObject::SOLID); // Add some random points to the plot object double min_x = 1e20; double max_x = -1; double max_y = -1; for (unsigned int i=0; i<data.size(); ++i) { double x; if (timeRadio->isChecked()) { x = data[i].first - data[0].first; chartWidget->BottomAxis.setLabel( i18n( "Time since first practice session in days" )); } else { x = i+1; chartWidget->BottomAxis.setLabel( i18n( "Sessions" )); } ob->addPoint( DPoint(x, data[i].second) ); min_x = std::min(x, min_x); max_x = std::max(x, max_x); max_y = std::max(data[i].second, max_y); } if (max_y == 0) max_y = 1; max_y *= 1.1; chartWidget->setLimits( min_x, max_x, -0.1*max_y, max_y ); // kdDebug() << min_x << " " << max_x << " " << max_y << endl; // Add plot object to chart chartWidget->addObject(ob); } }
//Add custom top/bottom axes with tickmarks for each month void modCalcEquinox::addDateAxes() { KPlotObject *poTopAxis = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poTopAxis->addPoint( 0.0, Plot->dataRect().bottom() ); //y-axis is reversed! poTopAxis->addPoint( 366.0, Plot->dataRect().bottom() ); Plot->addPlotObject( poTopAxis ); KPlotObject *poBottomAxis = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poBottomAxis->addPoint( 0.0, Plot->dataRect().top() + 0.02 ); poBottomAxis->addPoint( 366.0, Plot->dataRect().top() + 0.02 ); Plot->addPlotObject( poBottomAxis ); //Tick mark for each month for ( int imonth=0; imonth<12; imonth++ ) { KPlotObject *poMonth = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poMonth->addPoint( dmonth(imonth), Plot->dataRect().top() ); poMonth->addPoint( dmonth(imonth), Plot->dataRect().top() + 1.4 ); Plot->addPlotObject( poMonth ); poMonth = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poMonth->addPoint( dmonth(imonth), Plot->dataRect().bottom() ); poMonth->addPoint( dmonth(imonth), Plot->dataRect().bottom() - 1.4 ); Plot->addPlotObject( poMonth ); } }
void modCalcEquinox::slotCompute() { KStarsData* data = KStarsData::Instance(); KSSun Sun; int year0 = Year->value(); KStarsDateTime dt( QDate(year0, 1, 1), QTime(0,0,0) ); long double jd0 = dt.djd(); //save JD on Jan 1st for ( int imonth=0; imonth < 12; imonth++ ) { KStarsDateTime kdt( QDate(year0, imonth+1, 1), QTime(0,0,0) ); DMonth[imonth] = kdt.djd() - jd0; } Plot->removeAllPlotObjects(); //Add the celestial equator, just a single line bisecting the plot horizontally KPlotObject *ce = new KPlotObject( data->colorScheme()->colorNamed( "EqColor" ), KPlotObject::Lines, 2.0 ); ce->addPoint( 0.0, 0.0 ); ce->addPoint( 366.0, 0.0 ); Plot->addPlotObject( ce ); //Add Ecliptic. This is more complicated than simply incrementing the //ecliptic longitude, because we want the x-axis to be time, not RA. //For each day in the year, compute the Sun's position. KPlotObject *ecl = new KPlotObject( data->colorScheme()->colorNamed( "EclColor" ), KPlotObject::Lines, 2 ); ecl->setLinePen( QPen( ecl->pen().color(), 4 ) ); Plot->setLimits( 1.0, double(dt.date().daysInYear()), -30.0, 30.0 ); //Add top and bottom axis lines, and custom tickmarks at each month addDateAxes(); for ( int i=1; i<=dt.date().daysInYear(); i++ ) { KSNumbers num( dt.djd() ); Sun.findPosition( &num ); ecl->addPoint( double(i), Sun.dec().Degrees() ); dt = dt.addDays( 1 ); } Plot->addPlotObject( ecl ); dSpring = findEquinox( Year->value(), true, ecl ); dSummer = findSolstice( Year->value(), true ); dAutumn = findEquinox( Year->value(), false, ecl ); dWinter = findSolstice( Year->value(), false ); //Display the Date/Time of each event in the text fields VEquinox->setText( KGlobal::locale()->formatDateTime( dSpring, KLocale::LongDate ) ); SSolstice->setText( KGlobal::locale()->formatDateTime( dSummer, KLocale::LongDate ) ); AEquinox->setText( KGlobal::locale()->formatDateTime( dAutumn, KLocale::LongDate ) ); WSolstice->setText( KGlobal::locale()->formatDateTime( dWinter, KLocale::LongDate ) ); //Add vertical dotted lines at times of the equinoxes and solstices KPlotObject *poSpring = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poSpring->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) ); poSpring->addPoint( dSpring.djd()-jd0, Plot->dataRect().top() ); poSpring->addPoint( dSpring.djd()-jd0, Plot->dataRect().bottom() ); Plot->addPlotObject( poSpring ); KPlotObject *poSummer = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poSummer->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) ); poSummer->addPoint( dSummer.djd()-jd0, Plot->dataRect().top() ); poSummer->addPoint( dSummer.djd()-jd0, Plot->dataRect().bottom() ); Plot->addPlotObject( poSummer ); KPlotObject *poAutumn = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poAutumn->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) ); poAutumn->addPoint( dAutumn.djd()-jd0, Plot->dataRect().top() ); poAutumn->addPoint( dAutumn.djd()-jd0, Plot->dataRect().bottom() ); Plot->addPlotObject( poAutumn ); KPlotObject *poWinter = new KPlotObject( Qt::white, KPlotObject::Lines, 1 ); poWinter->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) ); poWinter->addPoint( dWinter.djd()-jd0, Plot->dataRect().top() ); poWinter->addPoint( dWinter.djd()-jd0, Plot->dataRect().bottom() ); Plot->addPlotObject( poWinter ); }
/* <name>Lines</name> <description>Lines from top to bottom</description> <author>Marco Gittler</author> <properties tag="lines" id="lines" /> <parameter default="5" type="constant" value="5" min="0" name="num" max="255" > <name>Num</name> </parameter> <parameter default="4" type="constant" value="4" min="0" name="width" max="255" > <name>Width</name> </parameter> </effect> */ void ParameterPlotter::setPointLists(const QDomElement& d, const QString& paramName, int startframe, int endframe) { //QListIterator <QPair <QString, QMap< int , QVariant > > > nameit(params); m_paramName = paramName; m_itemParameter = d; QDomNodeList namenode = d.elementsByTagName("parameter"); m_max_y = 0; m_min_y = 0; removeAllPlotObjects(); m_stretchFactors.clear(); m_parameterNameList.clear(); m_plotobjects.clear(); QString dat; QTextStream stre(&dat); d.save(stre, 2); //qDebug() << dat; int i = 0; while (!namenode.item(i).isNull() && namenode.item(i).toElement().attribute("name") != m_paramName) ++i; if (namenode.count()) { QDomElement pa = namenode.item(i).toElement(); //QDomNode na = pa.firstChildElement("name"); m_parameterNameList << pa.attribute("namedesc").split(';'); emit parameterList(m_parameterNameList); //max_y=pa.attributes().namedItem("max").nodeValue().toInt(); //int val=pa.attributes().namedItem("value").nodeValue().toInt(); QStringList defaults; if (pa.attribute("start").contains(';')) defaults = pa.attribute("start").split(';'); else if (pa.attribute("value").contains(';')) defaults = pa.attribute("value").split(';'); else if (pa.attribute("default").contains(';')) defaults = pa.attribute("default").split(';'); QStringList maxv = pa.attribute("max").split(';'); QStringList minv = pa.attribute("min").split(';'); for (int i = 0; i < maxv.size() && i < minv.size(); ++i) { if (m_max_y < maxv[i].toInt()) m_max_y = maxv[i].toInt(); if (m_min_y > minv[i].toInt()) m_min_y = minv[i].toInt(); } for (int i = 0; i < m_parameterNameList.count(); ++i) { KPlotObject *plot = new KPlotObject(m_colors[m_plotobjects.size()%m_colors.size()]); plot->setShowLines(true); if (!m_stretchFactors.contains(i) && i < maxv.size()) { if (maxv[i].toInt() != 0) m_stretchFactors[i] = m_max_y / maxv[i].toInt(); else m_stretchFactors[i] = 1.0; } if (i < defaults.size() && defaults[i].toDouble() > m_max_y) defaults[i] = m_max_y; int def = 0; if (i < defaults.size()) def = (int)(defaults[i].toInt() * m_stretchFactors[i]); QString name = ""; if (i < m_parameterNameList.size()) name = m_parameterNameList[i]; plot->addPoint(startframe, def, name); //add keyframes here plot->addPoint(endframe, def); m_plotobjects.append(plot); } /*TODO keyframes while (pointit.hasNext()){ pointit.next(); plot->addPoint(QPointF(pointit.key(),pointit.value().toDouble()),item.first,1); if (pointit.value().toInt() >maxy) max_y=pointit.value().toInt(); }*/ } setLimits(-1, endframe + 1, m_min_y - 10, m_max_y + 10); addPlotObjects(m_plotobjects); }
void titrationCalculator::plot() { width = int(xmax - xmin); //now I'm preparing the kplot widget uid.kplotwidget->removeAllPlotObjects(); uid.kplotwidget->setLimits(xmin, xmax, ymin, ymax); //now I need to set the limits of the plot KPlotObject *kpor = new KPlotObject(Qt::red,KPlotObject::Lines); KPlotObject *kpog = new KPlotObject(Qt::green, KPlotObject::Lines); KPlotObject *kpob = new KPlotObject(Qt::blue, KPlotObject::Lines); redplot = "<polyline points=\""; greenplot = "<polyline points=\""; blueplot = "<polyline points=\""; if (!uid.tableWidget->item(0,0) || uid.tableWidget->item(0,0)->text().isEmpty()) { //go on } else { char yvalue[80]; int tmpy = 0; for (int i = 0; i < uid.tableWidget->rowCount(); ++i) { if (!uid.tableWidget->item(i,0) || uid.tableWidget->item(i,0)->text().isEmpty()) { break; } else { if (uid.tableWidget->item(i,0)->data(Qt::DisplayRole).toString() == uid.yaxis->text()) { QString yvalueq = uid.tableWidget->item(i,1)->data(Qt::DisplayRole).toString(); QByteArray ba = yvalueq.toLatin1(); char *yvaluen = ba.data(); strcpy(yvalue,yvaluen); tmpy = 1; } } } QString mreporto; int iter = 0; if (uid.xaxis->text() == "" or uid.xaxis->text() == " ") { uid.xaxis->setText(i18n("nothing")); } if (tmpy == 0) { QMessageBox::critical(this,i18n("Error"),i18n("Unable to find an equation for Y-axis variable.")); } else { //now we have to solve the system of equations NOTE:yvalue contains the equation of Y-axis variable //we iterates the process until you have an equation in one only unknown variable or a numeric expression mreporto = solve(yvalue); while (end == 0 or lettere == 1) { QByteArray ba = mreporto.toLatin1(); char *tmreport = ba.data(); ++iter; if (end == 1 or lettere == 0) { break; } if (iter > 100) { break; //preventing from an endless iteration } mreporto = solve(tmreport); } } //if (mreporto!="") uid.note->setText("Theoretical Curve: "+mreporto); if (!mreporto.isEmpty()) { uid.note->setText(i18n("Theoretical curve") + ": " + mreporto); for (int i = int(xmin); i < int(xmax); ++i) { double id = i; QScriptEngine myEngine; QByteArray ban = mreporto.toLatin1(); char *tmreporto = ban.data(); QString istr; istr.append(QString("%1").arg((id))); //now i'm using QScript language to solve the expression //in a future we can consider to change it supporting some backends, but it's really complex QString myscript = solvex(tmreporto,istr); QScriptValue three = myEngine.evaluate(myscript); double tvalue = three.toNumber(); kpor->addPoint(id, tvalue); redplot = redplot + ' ' + QString::number((id * 10) + 5).replace(QChar(','), QChar('.')) + ',' + QString::number((ymax - tvalue) * 10).replace(QChar(','), QChar('.')); } } temponu = 0; } //here ends the equations mode //uid.tableWidget_2->sortItems(1, Qt::AscendingOrder); //seems that the sorting doesn't work correctly if (!uid.tableWidget_2->item(0, 0) || uid.tableWidget_2->item(0, 0)->text().isEmpty()) { //go on } else { //now we can plot the values double a, b, c, d, xval; QVarLengthArray<double, 64> px(uid.tableWidget_2->rowCount()); QVarLengthArray<double, 64> py(uid.tableWidget_2->rowCount()); int totaldata = 0; for (int i = 0; i < uid.tableWidget_2->rowCount(); ++i) { if (!uid.tableWidget_2->item(i,0) || uid.tableWidget_2->item(i, 0)->text().isEmpty()) { break; } else { ++totaldata; kpob->addPoint(uid.tableWidget_2->item(i,1)->data(Qt::DisplayRole).toDouble(), uid.tableWidget_2->item(i,0)->data(Qt::DisplayRole).toDouble()); py[i] = uid.tableWidget_2->item(i,0)->data(Qt::DisplayRole).toDouble(); px[i] = uid.tableWidget_2->item(i,1)->data(Qt::DisplayRole).toDouble(); blueplot = blueplot + ' ' + QString::number((uid.tableWidget_2->item(i,1)->data(Qt::DisplayRole).toDouble() * 10) + 5).replace(QChar(','), QChar('.')) + ',' + QString::number((ymax-uid.tableWidget_2->item(i, 0)->data(Qt::DisplayRole).toDouble()) * 10).replace(QChar(','), QChar('.')); } } a = py[totaldata - 1] - py[0]; b = 4 / (px[totaldata - 1] - px[0]); d = 0; if (a > 0) { d = py[0] + (a / 2); } else if (a < 0) { d = py[totaldata - 1] - (a / 2); } double cn = 0.0; int th = 0; for (int i = 1; i < (totaldata - 1); ++i) { //now i'm using the value of the points to fit the curve double ci = ((setttanh((py[i] - d) / a)) / b) - px[i]; if ((ci * 0) == 0) { cn = cn + ci; ++th; } } //c = cn/(th); it doesn't wok, but i found out this little hack. The strange thing is that in the standalone application it works fine. c = cn / (th * 2); //THIS IS THE PLOT OF APPROXIMATED CURVE for (int i = int(xmin); i < (int(xmax)); ++i) { double id = i; xval = (a * tanh(b * (id + c))) + d; kpog->addPoint(id, xval); greenplot = greenplot + ' ' + QString::number((id * 10) + 5).replace(QChar(','), QChar('.')) + ',' + QString::number((ymax-xval) * 10).replace(QChar(','), QChar('.')); } //THIS IS THE EQUIVALENCE POINT (THE INFLECTION OF THE CURVE) QString es = QString::number(-c); QString as = QString::number(a); QString bs = QString::number(b); QString cs = QString::number(c); QString ds = QString::number(d); QString tempon = uid.note->toPlainText()+QChar('\n'); if (temponu != 0) { tempon = ""; } uid.note->setText(tempon + '\n' + i18n("Approximated curve") + ": " + as + "*tanh(" + bs + "*(x+"+cs+"))+" + ds +'\n' + i18n("Equivalence point") + ": " + es); } //here ends the experimental values mode uid.kplotwidget->addPlotObject(kpor); uid.kplotwidget->addPlotObject(kpog); uid.kplotwidget->addPlotObject(kpob); redplot = redplot + "\" style=\"stroke:red;fill:none\"/> "; blueplot = blueplot + "\" style=\"stroke:blue;fill:none\"/> "; greenplot = greenplot + "\" style=\"stroke:green;fill:none\"/> "; }
void Focus::autoFocusAbs(double currentHFR) { static int initHFRPos=0, lastHFRPos=0, minHFRPos=0, initSlopePos=0, initPulseDuration=0, focusOutLimit=0, focusInLimit=0, minPos=1e6, maxPos=0; static double initHFR=0, minHFR=0, maxHFR=1,initSlopeHFR=0; double targetPulse=0, delta=0; QString deltaTxt = QString("%1").arg(fabs(currentHFR-minHFR)*100.0, 0,'g', 2); QString HFRText = QString("%1").arg(currentHFR, 0,'g', 3); //qDebug() << "Current HFR: " << currentHFR << " Current Position: " << pulseStep << endl; //qDebug() << "minHFR: " << minHFR << " MinHFR Pos: " << minHFRPos << endl; //qDebug() << "Delta: " << deltaTxt << endl; if (minHFR) appendLogText(i18n("FITS received. HFR %1 @ %2. Delta (%3%)", HFRText, pulseStep, deltaTxt)); else appendLogText(i18n("FITS received. HFR %1 @ %2.", HFRText, pulseStep)); if (++absIterations > MAXIMUM_ABS_ITERATIONS) { appendLogText(i18n("Autofocus failed to reach proper focus. Try increasing tolerance value.")); stopFocus(); return; } // No stars detected, try to capture again if (currentHFR == -1) { appendLogText(i18n("No stars detected, capturing again...")); capture(); return; } if (currentHFR > maxHFR || HFRPoints.empty()) { maxHFR = currentHFR; if (HFRPoints.empty()) { maxPos=1; minPos=1e6; } } if (pulseStep > maxPos) maxPos = pulseStep; if (pulseStep < minPos) minPos = pulseStep; HFRPoint *p = new HFRPoint(); p->HFR = currentHFR; p->pos = pulseStep; HFRPoints.append(p); HFRPlot->removeAllPlotObjects(); //HFRPlot->setLimits(pulseStep-pulseDuration*5, pulseStep+pulseDuration*5, currentHFR/1.5, currentHFR*1.5 ); HFRPlot->setLimits(minPos-pulseDuration, maxPos+pulseDuration, currentHFR/1.5, maxHFR ); KPlotObject *hfrObj = new KPlotObject( Qt::red, KPlotObject::Points, 2 ); foreach(HFRPoint *p, HFRPoints) hfrObj->addPoint(p->pos, p->HFR); HFRPlot->addPlotObject(hfrObj); HFRPlot->update(); switch (lastFocusDirection) { case FOCUS_NONE: HFR = currentHFR; initHFRPos = pulseStep; initHFR=HFR; minHFR=currentHFR; minHFRPos=pulseStep; HFRDec=0; HFRInc=0; focusOutLimit=0; focusInLimit=0; initPulseDuration=pulseDuration; FocusIn(pulseDuration); break; case FOCUS_IN: case FOCUS_OUT: if (reverseDir && focusInLimit && focusOutLimit && fabs(currentHFR - minHFR) < (toleranceIN->value()/100.0) && HFRInc == 0 ) { if (absIterations <= 2) appendLogText(i18n("Change in HFR is too small. Try increasing the step size or decreasing the tolerance.")); else appendLogText(i18n("Autofocus complete.")); stopFocus(); break; } else if (currentHFR < HFR) { double slope=0; // Let's try to calculate slope of the V curve. if (initSlopeHFR == 0 && HFRInc == 0 && HFRDec >= 1) { initSlopeHFR = HFR; initSlopePos = lastHFRPos; } // Let's now limit the travel distance of the focuser if (lastFocusDirection == FOCUS_OUT && lastHFRPos < focusInLimit) focusInLimit = lastHFRPos; else if (lastFocusDirection == FOCUS_IN && lastHFRPos > focusOutLimit) focusOutLimit = lastHFRPos; // If we have slope, get next target position if (initSlopeHFR) { slope = (currentHFR - initSlopeHFR) / (pulseStep - initSlopePos); targetPulse = pulseStep + (currentHFR*0.5 - currentHFR)/slope; } // Otherwise proceed iteratively else { if (lastFocusDirection == FOCUS_IN) targetPulse = pulseStep + pulseDuration; else targetPulse = pulseStep - pulseDuration; } HFR = currentHFR; // Let's keep track of the minimum HFR if (HFR < minHFR) { minHFR = HFR; minHFRPos = pulseStep; } lastHFRPos = pulseStep; // HFR is decreasing, we are on the right direction HFRDec++; HFRInc=0; } else { // HFR increased, let's deal with it. HFRInc++; HFRDec=0; reverseDir = true; // Reality Check: If it's first time, let's capture again and see if it changes. if (HFRInc <= 1) { capture(); return; } // Looks like we're going away from optimal HFR else { HFR = currentHFR; lastHFRPos = pulseStep; initSlopeHFR=0; HFRInc=0; // Let's set new limits if (lastFocusDirection == FOCUS_IN) focusInLimit = pulseStep; else focusOutLimit = pulseStep; // Decrease pulse pulseDuration = pulseDuration * 0.75; // Let's get close to the minimum HFR position so far detected if (lastFocusDirection == FOCUS_OUT) targetPulse = minHFRPos+pulseDuration/2; else targetPulse = minHFRPos-pulseDuration/2; } } // Limit target Pulse to algorithm limits if (focusInLimit != 0 && lastFocusDirection == FOCUS_IN && targetPulse > focusInLimit) targetPulse = focusInLimit; else if (focusOutLimit != 0 && lastFocusDirection == FOCUS_OUT && targetPulse < focusOutLimit) targetPulse = focusOutLimit; // Limit target pulse to focuser limits if (targetPulse < absMotionMin) targetPulse = absMotionMin; else if (targetPulse > absMotionMax) targetPulse = absMotionMax; // Ops, we can't go any further, we're done. if (targetPulse == pulseStep) { appendLogText(i18n("Autofocus complete.")); stopFocus(); return; } // Ops, deadlock if (focusOutLimit && focusOutLimit == focusInLimit) { appendLogText(i18n("Deadlock reached. Please try again with different settings.")); stopFocus(); return; } // Get delta for next move delta = (targetPulse - pulseStep); // Now cross your fingers and wait if (delta > 0) FocusIn(delta); else FocusOut(fabs(delta)); break; } }