cassinitools.cpp
346 lines
| 11.5 KiB
| text/x-c
|
CppLexer
r11 | /*------------------------------------------------------------------------------ | |||
-- This file is a part of the QLop Software | ||||
-- Copyright (C) 2015, Plasma Physics Laboratory - CNRS | ||||
-- | ||||
-- 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 | ||||
-------------------------------------------------------------------------------*/ | ||||
/*-- Author : Alexis Jeandet | ||||
-- Mail : alexis.jeandet@member.fsf.org | ||||
----------------------------------------------------------------------------*/ | ||||
r5 | #include "cassinitools.h" | |||
#include <qlopplots.h> | ||||
#include <QPen> | ||||
r6 | #include <QAction> | |||
r9 | #include <fftw3.h> | |||
r11 | #include <omp.h> | |||
r14 | #include <qlopdatabase.h> | |||
r5 | ||||
CassiniTools* CassiniTools::_self=NULL; | ||||
QDockWidget* CassiniTools::m_gui=NULL; | ||||
CassiniToolsGUI* CassiniTools::m_CassiniToolsGUI=NULL; | ||||
CassiniDataFile* CassiniTools::m_dataFile=NULL; | ||||
r6 | int CassiniTools::m_defaultPlot=-1; | |||
r9 | int CassiniTools::m_fftPlot=-1; | |||
r10 | SocExplorerPlotActions* CassiniTools::ExportAction=NULL; | |||
r5 | ||||
r14 | ||||
r5 | Qt::GlobalColor QLopColours[]= {Qt::black, | |||
Qt::red, | ||||
Qt::blue, | ||||
Qt::green, | ||||
Qt::darkGreen, | ||||
Qt::cyan, | ||||
Qt::darkRed, | ||||
Qt::gray, | ||||
Qt::yellow, | ||||
Qt::darkBlue, | ||||
Qt::darkCyan, | ||||
Qt::magenta, | ||||
Qt::darkMagenta, | ||||
Qt::darkYellow, | ||||
Qt::darkGray, | ||||
Qt::lightGray}; | ||||
int QLopColoursCount=16; | ||||
#define _INIT() if(Q_UNLIKELY(_self==NULL)){init();} | ||||
CassiniTools::CassiniTools(bool noGUI,QObject *parent) : QLopService(parent) | ||||
{ | ||||
m_dataFile = new CassiniDataFile(); | ||||
connect(m_dataFile,SIGNAL(dataReady(QLopDataList)),this,SLOT(dataReady(QLopDataList))); | ||||
r14 | connect(m_dataFile,SIGNAL(fileWritten()),this,SLOT(fileWritten())); | |||
r5 | m_serviceName="CassiniTools"; | |||
m_noGui=noGUI; | ||||
r11 | fftw_init_threads(); | |||
r5 | } | |||
CassiniTools::~CassiniTools() | ||||
{ | ||||
delete m_dataFile; | ||||
delete m_CassiniToolsGUI; | ||||
delete m_gui; | ||||
} | ||||
r6 | void CassiniTools::makePlot() | |||
{ | ||||
m_defaultPlot = QLopPlots::addPlot(); | ||||
r9 | m_fftPlot = QLopPlots::addPlot(); | |||
r6 | SocExplorerPlot* plot=QLopPlots::getPlot(m_defaultPlot); | |||
if(plot) | ||||
{ | ||||
plot->setTitle(_self->m_serviceName + " plot"); | ||||
plot->setXaxisTickLabelType(QCPAxis::ltDateTime); | ||||
plot->setXaxisDateTimeFormat("hh:mm:ss.zzz"); | ||||
plot->setContextMenuPolicy(Qt::ActionsContextMenu); | ||||
r7 | SocExplorerPlotActions* action=new SocExplorerPlotActions("export view",plot->PID(),_self); | |||
r6 | plot->addAction(action); | |||
r8 | QObject::connect(action,SIGNAL(triggered(int)),_self,SLOT(export_view(int))); | |||
r13 | QString fileName = QString(plot->title()).replace(".TAB",""); | |||
fileName = generateFileName(fileName,".TAB"); | ||||
ExportAction=new SocExplorerPlotActions("export view to "+fileName,plot->PID(),_self); | ||||
r10 | plot->addAction(ExportAction); | |||
QObject::connect(ExportAction,SIGNAL(triggered(int)),_self,SLOT(export_view_Predefined_FileName(int))); | ||||
r9 | action=new SocExplorerPlotActions("FFT of the current view",plot->PID(),_self); | |||
plot->addAction(action); | ||||
QObject::connect(action,SIGNAL(triggered(int)),_self,SLOT(compute_fft_on_view(int))); | ||||
r6 | } | |||
} | ||||
r5 | void CassiniTools::init(bool noGUI, QObject *parent) | |||
{ | ||||
if(Q_UNLIKELY(_self==NULL)) | ||||
{ | ||||
_self=new CassiniTools(noGUI,parent); | ||||
} | ||||
} | ||||
CassiniTools *CassiniTools::self() | ||||
{ | ||||
_INIT(); | ||||
return _self; | ||||
} | ||||
void CassiniTools::decodeFGMData(const QString &file) | ||||
{ | ||||
_INIT(); | ||||
m_dataFile->parseFile(file); | ||||
} | ||||
void CassiniTools::plotFile(const QString &File) | ||||
{ | ||||
r9 | if(!m_dataFile->isRunning()) | |||
r5 | { | |||
r9 | m_dataFile->parseFile(File); | |||
// TODO fixme | ||||
SocExplorerPlot* plot = QLopPlots::getPlot(m_defaultPlot); | ||||
if(plot==NULL) | ||||
{ | ||||
makePlot(); | ||||
plot = QLopPlots::getPlot(m_defaultPlot); | ||||
} | ||||
if(plot) | ||||
r10 | { | |||
r9 | plot->setTitle(File); | |||
r13 | QString fileName = QString(File).replace(".TAB","-part"); | |||
fileName = generateFileName(fileName,".TAB"); | ||||
ExportAction->setText("export view to "+fileName); | ||||
r10 | } | |||
r9 | } | |||
r5 | } | |||
void CassiniTools::plot_TAB_File(const QString &fileName) | ||||
{ | ||||
r6 | //TODO fix: accent not accepted | |||
plotFile(fileName); | ||||
} | ||||
r5 | ||||
r7 | void CassiniTools::export_view(int PID) | |||
r6 | { | |||
r7 | SocExplorerPlot* plot = QLopPlots::getPlot(PID); | |||
r6 | if(plot==NULL) | |||
r7 | return; | |||
r6 | { | |||
r10 | QString fileName = plot->title(); | |||
fileName = QFileDialog::getSaveFileName(0,tr("Set filename"),fileName.replace(".TAB","-part.TAB")); | ||||
if(fileName!="") | ||||
{ | ||||
QLopDataList vectors; | ||||
for(int i=0;i<plot->graphCount();i++) | ||||
{ | ||||
r13 | QLopQCPDataVector* vect = new QLopQCPDataVector(); | |||
r10 | vect->data = plot->getVisibleData(i); | |||
vectors.append(vect); | ||||
} | ||||
m_dataFile->saveFile(fileName,vectors); | ||||
} | ||||
} | ||||
} | ||||
void CassiniTools::export_view_Predefined_FileName(int PID) | ||||
{ | ||||
SocExplorerPlot* plot = QLopPlots::getPlot(PID); | ||||
if(plot==NULL) | ||||
return; | ||||
{ | ||||
r13 | QString fileName = QString(plot->title()).replace(".TAB","-part"); | |||
fileName = generateFileName(fileName,".TAB"); | ||||
r8 | if(fileName!="") | |||
{ | ||||
QLopDataList vectors; | ||||
for(int i=0;i<plot->graphCount();i++) | ||||
{ | ||||
r13 | QLopQCPDataVector* vect = new QLopQCPDataVector(); | |||
r8 | vect->data = plot->getVisibleData(i); | |||
vectors.append(vect); | ||||
} | ||||
m_dataFile->saveFile(fileName,vectors); | ||||
} | ||||
r6 | } | |||
r5 | } | |||
r9 | void CassiniTools::compute_fft_on_view(int PID) | |||
{ | ||||
r11 | ||||
QElapsedTimer timr; | ||||
r9 | SocExplorerPlot* plot = QLopPlots::getPlot(PID); | |||
if(plot==NULL) | ||||
return; | ||||
{ | ||||
r11 | timr.start(); | |||
r9 | QLopDataList vectors; | |||
for(int i=0;i<plot->graphCount();i++) | ||||
{ | ||||
r13 | QLopQCPDataVector* vect = new QLopQCPDataVector(); | |||
r9 | vect->data = plot->getVisibleData(i); | |||
vectors.append(vect); | ||||
} | ||||
if(vectors.count()==3) | ||||
{ | ||||
r13 | QLopQCPDataVector* ch1V=(QLopQCPDataVector*)vectors.at(0); | |||
QLopQCPDataVector* ch2V=(QLopQCPDataVector*)vectors.at(1); | ||||
QLopQCPDataVector* ch3V=(QLopQCPDataVector*)vectors.at(2); | ||||
QLopQCPDataVector* FFTout=new QLopQCPDataVector(); | ||||
r9 | if(ch1V->data->count()==ch2V->data->count() && ch1V->data->count()==ch3V->data->count()) | |||
{ | ||||
double* in; | ||||
fftw_complex *out; | ||||
fftw_plan p; | ||||
FFTout->data = new QVector<QCPData>(ch1V->data->count()/2); | ||||
in = (double*) fftw_malloc(sizeof(double) * ch1V->data->count()); | ||||
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * ch1V->data->count()); | ||||
double av=0; | ||||
for(int i=0;i<ch1V->data->count();i++) | ||||
{ | ||||
in[i]=sqrt((ch1V->data->at(i).value*ch1V->data->at(i).value) + (ch2V->data->at(i).value*ch2V->data->at(i).value) + (ch3V->data->at(i).value*ch3V->data->at(i).value)); | ||||
av = av+in[i]; | ||||
} | ||||
av/=ch1V->data->count(); | ||||
for(int i=0;i<ch1V->data->count();i++) | ||||
{ | ||||
in[i]=in[i]-av; | ||||
} | ||||
r11 | fftw_plan_with_nthreads(4); | |||
r9 | p = fftw_plan_dft_r2c_1d(ch1V->data->count(),in, out,FFTW_ESTIMATE); | |||
fftw_execute(p); /* repeat as needed */ | ||||
fftw_destroy_plan(p); | ||||
fftw_free(in); | ||||
for(int i=0;i<ch1V->data->count()/2;i++) | ||||
{ | ||||
r14 | // (*FFTout->data)[i].value=sqrt((out[i][0] * out[i][0]) + (out[i][1] * out[i][1]))/ch1V->data->count(); | |||
r9 | (*FFTout->data)[i].value=((out[i][0] * out[i][0]) + (out[i][1] * out[i][1]))/(ch1V->data->count()); | |||
(*FFTout->data)[i].key = i; | ||||
} | ||||
fftw_free(out); | ||||
SocExplorerPlot* plot = QLopPlots::getPlot(m_fftPlot); | ||||
if(plot==NULL) | ||||
return; | ||||
plot->removeAllGraphs(); | ||||
plot->addGraph(); | ||||
plot->setXaxisLog(); | ||||
plot->setYaxisLog(); | ||||
plot->setAdaptativeSampling(0,true); | ||||
QPen pen = plot->getGraphPen(0); | ||||
pen.setColor(QLopColours[0%QLopColoursCount]); | ||||
plot->setGraphPen(0,pen); | ||||
plot->setGraphData(0,FFTout->data,false); | ||||
plot->rescaleAxis(); | ||||
plot->replot(); | ||||
r11 | qDebug()<< ch1V->data->count() <<" Points loaded in "<< timr.elapsed()<<"ms"; | |||
r9 | } | |||
} | ||||
} | ||||
} | ||||
r13 | QString CassiniTools::generateFileName(const QString &baseName, const QString &extension) | |||
{ | ||||
QString fileName = baseName+extension; | ||||
int i=0; | ||||
while(QFile::exists(fileName)) | ||||
{ | ||||
fileName = baseName+QString::number(i++)+extension; | ||||
} | ||||
return fileName; | ||||
} | ||||
r5 | QDockWidget *CassiniTools::getGUI() | |||
{ | ||||
if(!m_noGui && (m_gui==NULL)) | ||||
{ | ||||
m_gui=new QDockWidget("Cassini Tools"); | ||||
m_CassiniToolsGUI = new CassiniToolsGUI(); | ||||
m_gui->setWidget(m_CassiniToolsGUI); | ||||
m_gui->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); | ||||
} | ||||
return m_gui; | ||||
} | ||||
const QString &CassiniTools::serviceName() | ||||
{ | ||||
_INIT(); | ||||
return m_serviceName; | ||||
} | ||||
void CassiniTools::dataReady(QLopDataList data) | ||||
{ | ||||
r14 | static QLopDataList prevData=QLopDataList(); | |||
r6 | SocExplorerPlot* plot = QLopPlots::getPlot(m_defaultPlot); | |||
if(plot==NULL) | ||||
{ | ||||
r9 | makePlot(); | |||
plot = QLopPlots::getPlot(m_defaultPlot); | ||||
r6 | } | |||
if(plot) | ||||
{ | ||||
r14 | QLopDataBase::removeData(prevData); | |||
r9 | plot->removeAllGraphs(); | |||
r14 | // QLopDataBase::re | |||
r9 | for(int i=0;i<data.count();i++) | |||
{ | ||||
plot->addGraph(); | ||||
plot->setAdaptativeSampling(i,true); | ||||
plot->setUseFastVector(i,true); | ||||
QPen pen = plot->getGraphPen(i); | ||||
pen.setColor(QLopColours[i%QLopColoursCount]); | ||||
plot->setGraphPen(i,pen); | ||||
plot->setGraphName(i,data.at(i)->name+"("+data.at(i)->unit+")"); | ||||
r13 | plot->setGraphData(i,((QLopQCPDataVector*)data.at(i))->data,false); | |||
r9 | } | |||
plot->rescaleAxis(); | ||||
plot->replot(); | ||||
r14 | prevData = data; | |||
QLopDataBase::addData(data); | ||||
r6 | } | |||
r5 | } | |||
r14 | void CassiniTools::fileWritten() | |||
{ | ||||
SocExplorerPlot* plot = QLopPlots::getPlot(m_defaultPlot); | ||||
if(plot==NULL) | ||||
{ | ||||
makePlot(); | ||||
plot = QLopPlots::getPlot(m_defaultPlot); | ||||
} | ||||
if(plot) | ||||
{ | ||||
QString fileName = QString(plot->title()).replace(".TAB","-part"); | ||||
fileName = generateFileName(fileName,".TAB"); | ||||
ExportAction->setText("export view to "+fileName); | ||||
} | ||||
} | ||||