Logo Search packages:      
Sourcecode: kboincspy version File versions  Download package

kbssetisignalplot.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Roberto Virga                                   *
 *   rvirga@users.sf.net                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <math.h>

#include <qpainter.h>
#include <qpixmap.h>

#include <kglobal.h>
#include <klocale.h>

#include <boincdata.h>

#include <setidata.h>

#include "kbssetisignalplot.h"

const unsigned KBSSETISignalPlot::s_margin = 5;

KBSSETISignalPlot::KBSSETISignalPlot(QWidget *parent, const char *name)
                 : QWidget(parent, name), type(NoData)
{
  // optimize redrawing
  setBackgroundMode(NoBackground);
}

QPixmap KBSSETISignalPlot::pixmap()
{
  return QPixmap::grabWidget(this);
}

const QSize KBSSETISignalPlot::defaultSize(345, 170);

const QSize KBSSETISignalPlot::setiSize(414, 97);

void KBSSETISignalPlot::clearData()
{
  if(type == NoData) return;
  type = NoData;
  
  repaint();
}

void KBSSETISignalPlot::setData(const SETIWorkunitHeader &workunit, const SETIGaussian &gaussian)
{
  if(Gaussian == type
     && gaussian.ra == m_gaussian.ra
     && gaussian.decl == m_gaussian.decl) return;
  
  if(gaussian.score() > 0) {
    type = Gaussian;
    m_gaussian = SETIGaussian(gaussian);
    m_start = workunit.group_info.data_desc.time_recorded_jd;
  } else if(type != NoData)
    type = NoData;
  else
    return;

  repaint();
}

void KBSSETISignalPlot::setData(const SETIWorkunitHeader &workunit, const SETIPulse &pulse)
{
  if(Pulse == type
     && pulse.ra == m_pulse.ra
     && pulse.decl == m_pulse.decl) return;
  
  if(pulse.score() > 0) {
    type = Pulse;
    m_pulse = SETIPulse(pulse);
    m_start = workunit.group_info.data_desc.time_recorded_jd;
  } else if(type != NoData)
    type = NoData;
  else
    return;

  repaint();
}

void KBSSETISignalPlot::setData(const SETIWorkunitHeader &workunit)
{
  if(TelescopePath == type
     && workunit.group_info.data_desc.start.ra == m_data_desc.start.ra
     && workunit.group_info.data_desc.start.dec == m_data_desc.start.dec
     && workunit.group_info.data_desc.end.ra == m_data_desc.end.ra
     && workunit.group_info.data_desc.end.dec == m_data_desc.end.dec) return;
  
  type = TelescopePath;
  m_data_desc = SETIDataDesc(workunit.group_info.data_desc);
  m_start = m_data_desc.time_recorded_jd;
  
  repaint();
}

void KBSSETISignalPlot::paintEvent(QPaintEvent *)
{
  QPixmap buffer(size());
  buffer.fill(black);
  
  QPainter painter(&buffer);

  const QString noDataMsg = (type == NoData)       ? i18n("No data")
                          : (type == Gaussian)     ? i18n("No gaussian data")
                          : (type == Pulse)        ? i18n("No pulse data")
                          :/*type == TelescopePath*/ i18n("No telescope path data");

  if(type != NoData)
  {
    QRect headerRect = QRect(s_margin, s_margin,
                             width() - 2 * s_margin, 3 * fontMetrics().lineSpacing());
    
    QRect plotRect = QRect(s_margin, headerRect.bottom() + s_margin,
                           width() - 2 * s_margin, height() - headerRect.bottom() - 2 * s_margin);
    
    KLocale *locale = KGlobal::locale();

    QString header;
    
    switch(type) {
      case Gaussian:
        {
          const double secs = fabs(m_gaussian.time_jd - m_start) * 24 * 60 * 60;
          
          header = i18n("Peak power %1, fit %2, score %3")
                     .arg(locale->formatNumber(m_gaussian.peak_power, 3))
                     .arg(locale->formatNumber(m_gaussian.chisqr, 3))
                     .arg(locale->formatNumber(m_gaussian.score(), 3))
                 + "\n" +
                   i18n("Resolution %1 Hz, signal ratio %2")
                     .arg(locale->formatNumber(m_gaussian.resolution(), 3))
                     .arg(locale->formatNumber(m_gaussian.signal_ratio(), 3))
                 + "\n" +
                   i18n("(%1 Hz at %2 s, %3 Hz/s drift)")
                     .arg(locale->formatNumber(m_gaussian.freq, 2))
                     .arg(locale->formatNumber(secs, 2))
                     .arg(locale->formatNumber(m_gaussian.chirp_rate, 4));
        }
        break;
      case Pulse:
        {
          const double secs = (m_pulse.time_jd - m_start) * 24 * 60 * 60;
          
          header = i18n("Power %1, score %2")
                     .arg(locale->formatNumber(m_pulse.peak_power, 3))
                     .arg(locale->formatNumber(m_pulse.score(), 3))
                 + "\n" +
                   i18n("Resolution %1 Hz, period %2")
                     .arg(locale->formatNumber(m_pulse.resolution(), 3))
                     .arg(locale->formatNumber(m_pulse.period, 3))
                 + "\n" +
                   i18n("(%1 Hz at %2 s, %3 Hz/s drift)")
                     .arg(locale->formatNumber(m_pulse.freq, 2))
                     .arg(locale->formatNumber(secs, 2))
                     .arg(locale->formatNumber(m_pulse.chirp_rate, 4));
        }
        break;
      default:
        {
          double min_ra, max_ra;
          if(m_data_desc.start.ra > m_data_desc.end.ra) {
            min_ra = m_data_desc.end.ra;
            max_ra = m_data_desc.start.ra;
          } else {
            min_ra = m_data_desc.start.ra;
            max_ra = m_data_desc.end.ra;
          }
          double ra_diff = max_ra - min_ra; if(ra_diff > 12.0) ra_diff = 24.0 - ra_diff;

          double min_dec, max_dec;
          if(m_data_desc.start.dec > m_data_desc.end.dec) {
            min_dec = m_data_desc.end.dec;
            max_dec = m_data_desc.start.dec;
          } else {
            min_dec = m_data_desc.start.dec;
            max_dec = m_data_desc.end.dec;
          }
          double dec_diff = max_dec - min_dec;

          header = i18n("RA range: %1 to %2 (%3)")
                     .arg(formatRA(min_ra))
                     .arg(formatRA(max_ra))
                     .arg(formatRA(ra_diff))
                 + "\n" +
                   i18n("Dec range: %1 to %2 (%3)")
                     .arg(formatDec(min_dec))
                     .arg(formatDec(max_dec))
                     .arg(formatDec(dec_diff, false))
                 + "\n" +
                   i18n("Angle range: %1")
                     .arg(locale->formatNumber(m_data_desc.true_angle_range, 3));
        }
        break;
    }
    painter.setPen(white);
    painter.drawText(headerRect, AlignLeft, header);
    
    if(type != TelescopePath)
    {
      QValueList<unsigned> pot = (type == Gaussian) ? m_gaussian.pot : m_pulse.pot;

      if(pot.count() > 0)
      {
        unsigned min, max;

        min = max = pot.first();
        for(QValueList<unsigned>::iterator it = pot.begin(); it != pot.end(); ++it)
        {
          if(*it < min) min = *it;
          if(*it > max) max = *it;
        }

        const double unit = plotRect.width() / double(pot.count());
        const double scale = plotRect.height() / double(max - min + 1);

        painter.translate(plotRect.x(), plotRect.bottom());
        painter.setPen(red);
        painter.moveTo(0, 0);

        for(unsigned i = 0; i < pot.count(); i++)
        {
          const int y = - int(scale * (pot[i] - min) + 1);

          painter.lineTo(int(unit * i), y);
          painter.lineTo(int(unit * (i+1)), y);
        }

        if(type == Gaussian)
        {
          const double secs = fabs(m_gaussian.time_jd - m_start) * 24 * 60 * 60;

          const int base = int(255 * m_gaussian.mean_power / m_gaussian.max_power);
          const double offset_scale = 255 * m_gaussian.peak_power / m_gaussian.max_power;

          const double mu = secs * m_gaussian.resolution();
          const double sigma = m_gaussian.sigma;

          painter.setPen(white);

          painter.moveTo(0, -int(scale * (base - min) + 1));
          for(int i = 0; i < plotRect.width() / 3; i++)
          {
            const int offset = int(offset_scale * exp(-0.5 * pow((3 * i / unit - mu) / sigma, 2)));
            const int y = -int(scale * (base + offset - min) + 1);

            if(i == 0) painter.moveTo(3 * i, y);
            else painter.lineTo(3 * i, y);
          }
        }
      } else {
        painter.setPen(gray);
        painter.drawText(plotRect, AlignCenter, noDataMsg);
      }
    } else {
      unsigned n_points = m_data_desc.coords.coordinate_t.count();
      double minX, maxX, minY, maxY;

      if(n_points > 1)
      {
        minX = maxX = m_data_desc.coords.coordinate_t.first().ra;
        minY = maxY = m_data_desc.coords.coordinate_t.first().dec;
        for(QValueList<SETICoordinateT>::const_iterator it = m_data_desc.coords.coordinate_t.begin();
            it != m_data_desc.coords.coordinate_t.end(); ++it)
        {
          const double x = (*it).ra;
          if(x < minX) minX = x;
          if(x > maxX) maxX = x;
          
          const double y = (*it).dec;
          if(y < minY) minY = y;
          if(y > maxY) maxY = y;
        }
      } else
        minX = maxX = minY = maxY = 0.0;

      if(minX != maxX || minY != maxY) {
        painter.translate(plotRect.x(), plotRect.y());
        painter.setPen(red);

        int oldX, oldY;
        oldX = oldY = 0;
        for(unsigned i = 0; i < n_points; i++)
        {
          double normX = 0.5;
          if(minX != maxX)
            normX = (m_data_desc.coords.coordinate_t[i].ra - minX) / (maxX - minX);
          
          double normY = 0.5;
          if(minY != maxY)
            normY = (m_data_desc.coords.coordinate_t[i].dec - minY) / (maxY - minY);

          int newX;
          if(m_data_desc.start.ra < m_data_desc.end.ra)
            newX = int(plotRect.width() * (1.0 - normX));
          else
            newX = int(plotRect.width() * normX);
          
          int newY;
          if(m_data_desc.start.dec < m_data_desc.end.dec)
            newY = int(plotRect.height() * normY);
          else
            newY = int(plotRect.height() * (1.0 - normY));

          if(newX == oldX && newY == oldY) continue;

          if(i > 0) arrow(painter, oldX, oldY, newX, newY);

          oldX = newX;
          oldY = newY;
        }
      } else {
        painter.setPen(gray);
        painter.drawText(plotRect, AlignCenter, noDataMsg);
      }
    }
  } else {
    painter.setPen(gray);
    painter.drawText(rect(), AlignCenter, noDataMsg);
  }
  
  painter.end();
  
  painter.begin(this);
  painter.drawPixmap(0, 0, buffer);
}

void KBSSETISignalPlot::arrow(QPainter &painter, int x1, int y1, int x2, int y2)
{
  painter.moveTo(x1, y1);
  painter.lineTo(x2, y2);

  double ang = (x1 == x2) ? ((y2 > y1) ? -90 : 90)
                          : (180 * atan((y2 - y1)/double(x2 - x1)) / M_PI);
  int x0 = (x2 > x1) ? -3 : 3;

  painter.save();
  painter.translate(x2, y2);
  painter.rotate(ang);
  painter.moveTo(0, 0);
  painter.lineTo(x0, 3);
  painter.moveTo(0, 0);
  painter.lineTo(x0, -3);
  painter.restore();
}

#include "kbssetisignalplot.moc"

Generated by  Doxygen 1.6.0   Back to index