void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd( SyntaxHighlighter *highlighter, const QFuture<HighlightingResult> &future) { // find block number of last result int lastBlockNumber = 0; for (int i = future.resultCount() - 1; i >= 0; --i) { const HighlightingResult &result = future.resultAt(i); if (result.line) { lastBlockNumber = result.line - 1; break; } } QTextDocument *doc = highlighter->document(); const int firstBlockToClear = lastBlockNumber + 1; if (firstBlockToClear <= doc->blockCount()) return; QTextBlock b = doc->findBlockByNumber(firstBlockToClear); while (b.isValid()) { QVector<QTextLayout::FormatRange> noFormats; highlighter->setExtraFormats(b, noFormats); b = b.next(); } }
/* Test that results reported after finished are ignored. */ void tst_QFuture::resultsAfterFinished() { { IntResult a; a.reportStarted(); QFuture<int> f = a.future(); int result; QCOMPARE(f.resultCount(), 0); result = 1; a.reportResult(&result); QCOMPARE(f.resultAt(0), 1); a.reportFinished(); QCOMPARE(f.resultAt(0), 1); QCOMPARE(f.resultCount(), 1); result = 2; a.reportResult(&result); QCOMPARE(f.resultCount(), 1); } // cancel it { IntResult a; a.reportStarted(); QFuture<int> f = a.future(); int result; QCOMPARE(f.resultCount(), 0); result = 1; a.reportResult(&result); QCOMPARE(f.resultAt(0), 1); QCOMPARE(f.resultCount(), 1); a.reportCanceled(); QCOMPARE(f.resultAt(0), 1); QCOMPARE(f.resultCount(), 1); result = 2; a.reportResult(&result); a.reportFinished(); } }
void BCI::run() { while(m_bIsRunning) { // Wait for fiff Info if not yet received - this is needed because we have to wait until the buffers are firstly initiated in the update functions while(!m_pFiffInfo_Sensor) msleep(10); // Start filling buffers with data from the inputs m_bProcessData = true; // Sensor level: Fill matrices with data if(m_bFillSensorWindowFirstTime) // Sensor level: Fill m_matSlidingWindowSensor with data for the first time { if(m_iTBWIndexSensor < m_matSlidingWindowSensor.cols()) { //cout<<"About to pop matrix"<<endl; MatrixXd t_mat = m_pBCIBuffer_Sensor->pop(); //cout<<"poped matrix"<<endl; // Get only the rows from the matrix which correspond with the selected features, namely electrodes on sensor level and destrieux clustered regions on source level for(int i = 0; i < m_matSlidingWindowSensor.rows(); i++) m_matSlidingWindowSensor.block(i, m_iTBWIndexSensor, 1, t_mat.cols()) = t_mat.block(m_mapElectrodePinningScheme[m_slChosenFeatureSensor.at(i)], 0, 1, t_mat.cols()); m_matStimChannelSensor.block(0, m_iTBWIndexSensor, 1, t_mat.cols()) = t_mat.block(136, 0, 1, t_mat.cols()); m_iTBWIndexSensor = m_iTBWIndexSensor + t_mat.cols(); } else // m_matSlidingWindowSensor is full for the first time { m_iTBWIndexSensor = 0; m_bFillSensorWindowFirstTime = false; } } else // Sensor level: Fill m_matTimeBetweenWindowsSensor matrix until full -> Then -> recalculate m_matSlidingWindowSensor, calculate features and classify { if(m_iTBWIndexSensor < m_matTimeBetweenWindowsSensor.cols()) { //cout<<"About to pop matrix"<<endl; MatrixXd t_mat = m_pBCIBuffer_Sensor->pop(); //cout<<"poped matrix"<<endl; // Get only the rows from the matrix which correspond with the selected features, namely electrodes on sensor level and destrieux clustered regions on source level for(int i = 0; i < m_matTimeBetweenWindowsSensor.rows(); i++) m_matTimeBetweenWindowsSensor.block(i, m_iTBWIndexSensor, 1, t_mat.cols()) = t_mat.block(m_mapElectrodePinningScheme[m_slChosenFeatureSensor.at(i)], 0, 1, t_mat.cols()); m_matTimeBetweenWindowsStimSensor.block(0, m_iTBWIndexSensor, 1, t_mat.cols()) = t_mat.block(136, 0, 1, t_mat.cols()); m_iTBWIndexSensor = m_iTBWIndexSensor + t_mat.cols(); } else // Recalculate m_matSlidingWindowSensor -> Calculate features, classify and store results { // ----1---- Recalculate m_matSlidingWindowSensor //cout<<"----1----"<<endl; //Move block from the right to the left -> use eval() to resolve Eigens aliasing problem m_matSlidingWindowSensor.block(0, 0, m_matSlidingWindowSensor.rows(), m_matSlidingWindowSensor.cols()-m_matTimeBetweenWindowsSensor.cols()) = m_matSlidingWindowSensor.block(0, m_matTimeBetweenWindowsSensor.cols(), m_matSlidingWindowSensor.rows(), m_matSlidingWindowSensor.cols()-m_matTimeBetweenWindowsSensor.cols()).eval(); m_matStimChannelSensor.block(0, 0, m_matStimChannelSensor.rows(), m_matStimChannelSensor.cols()-m_matTimeBetweenWindowsStimSensor.cols()) = m_matStimChannelSensor.block(0, m_matTimeBetweenWindowsStimSensor.cols(), m_matStimChannelSensor.rows(), m_matStimChannelSensor.cols()-m_matTimeBetweenWindowsStimSensor.cols()).eval(); // push m_matTimeBetweenWindowsSensor from the right m_matSlidingWindowSensor.block(0, m_matSlidingWindowSensor.cols()-m_matTimeBetweenWindowsSensor.cols(), m_matTimeBetweenWindowsSensor.rows(), m_matTimeBetweenWindowsSensor.cols()) = m_matTimeBetweenWindowsSensor; m_matStimChannelSensor.block(0, m_matStimChannelSensor.cols()-m_matTimeBetweenWindowsStimSensor.cols(), m_matTimeBetweenWindowsStimSensor.rows(), m_matTimeBetweenWindowsStimSensor.cols()) = m_matTimeBetweenWindowsStimSensor; //cout<<m_matStimChannelSensor; // Test if data is correctly streamed to this plugin if(m_slChosenFeatureSensor.contains("TEST")) { cout<<"Recalculate matrix"<<endl; for(int i = 0; i<m_matSlidingWindowSensor.cols() ; i++) cout << m_matSlidingWindowSensor(m_matSlidingWindowSensor.rows()-1,i) <<endl; // for(int i = 1; i<m_matSlidingWindowSensor.cols() ; i++) // { // cout << m_matSlidingWindowSensor(m_matSlidingWindowSensor.rows()-1,i-1) <<endl; // if(m_matSlidingWindowSensor(m_matSlidingWindowSensor.rows()-1,i) - m_matSlidingWindowSensor(m_matSlidingWindowSensor.rows()-1,i-1) != 1) // cout<<"Sequence error while streaming from tmsi plugin at position: "<<i<<endl; // } } // ----2---- Transform matrix into QList structure, so that QTConcurrent can handle it properly //cout<<"----2----"<<endl; QList< QPair<int,RowVectorXd> > qlMatrixRows; for(int i = 0; i< m_matSlidingWindowSensor.rows(); i++) qlMatrixRows << QPair<int,RowVectorXd>(i, m_matSlidingWindowSensor.row(i)); int iNumberOfFeatures = qlMatrixRows.size(); // ----3---- Subtract mean in m_matSlidingWindowSensor concurrently using map() //cout<<"----3----"<<endl; if(m_bSubtractMean) { QFuture<void> futureMean = QtConcurrent::map(qlMatrixRows,[this](QPair<int,RowVectorXd>& rowdata) { applyMeanCorrectionConcurrently(rowdata); }); futureMean.waitForFinished(); } // ----4---- Do simple threshold artefact reduction //cout<<"----4----"<<endl; if(hasThresholdArtefact(qlMatrixRows) == false) { // Look for trigger flag if(lookForTrigger(m_matStimChannelSensor) && !m_bTriggerActivated) { // cout << "Trigger activated" << endl; //QFuture<void> future = QtConcurrent::run(Beep, 450, 700); m_bTriggerActivated = true; } // ----5---- Filter data in m_matSlidingWindowSensor concurrently using map() //cout<<"----5----"<<endl; // TODO: work only on qlMatrixRows -> filteredRows doesnt need to be created -> more efficient QList< QPair<int,RowVectorXd> > filteredRows = qlMatrixRows; if(m_bUseFilter) { QFuture<void> futureFilter = QtConcurrent::map(filteredRows,[this](QPair<int,RowVectorXd>& chdata) { applyFilterOperatorConcurrently(chdata); }); futureFilter.waitForFinished(); } // // Write data before and after filtering to debug file // for(int i=0; i<qlMatrixRows.size(); i++) // m_outStreamDebug << "qlMatrixRows at row " << i << ": " << qlMatrixRows.at(i).second << "\n"; // m_outStreamDebug<<endl; // for(int i=0; i<filteredRows.size(); i++) // m_outStreamDebug << "filteredRows at row " << i << ": " << filteredRows.at(i).second << "\n"; // m_outStreamDebug << endl << "---------------------------------------------------------" << endl << endl; // // Write filtered data continously to file // for(int i = 0; i<filteredRows.at(0).second.size() ;i++) // m_outStreamDebug << filteredRows.at(0).second(i)<<endl; // ----6---- Calculate features concurrently using mapped() //cout<<"----6----"<<endl; std::function< QPair<int,QList<double> > (QPair<int,RowVectorXd>&)> applyOpsFeatures = [this](QPair<int,RowVectorXd>& chdata) -> QPair< int,QList<double> > { return applyFeatureCalcConcurrentlyOnSensorLevel(chdata); }; QFuture< QPair< int,QList<double> > > futureCalculatedFeatures = QtConcurrent::mapped(filteredRows.begin(), filteredRows.end(), applyOpsFeatures); futureCalculatedFeatures.waitForFinished(); m_iNumberOfCalculatedFeatures++; // ----7---- Store features //cout<<"----7----"<<endl; m_lFeaturesSensor.append(futureCalculatedFeatures.results()); // ----8---- If enough features (windows) have been calculated (processed) -> classify all features and average results //cout<<"----8----"<<endl; if(m_iNumberOfCalculatedFeatures == m_iNumberFeatures) { // Transform m_lFeaturesSensor into an easier file structure -> create feature points QList< QList<double> > lFeaturesSensor_new; for(int i = 0; i<m_lFeaturesSensor.size()-iNumberOfFeatures+1; i = i + iNumberOfFeatures) // iterate over QPair feature List for(int z = 0; z<m_lFeaturesSensor.at(0).second.size(); z++) // iterate over number of sub signals { QList<double> temp; for(int t = 0; t<iNumberOfFeatures; t++) // iterate over chosen features (electrodes) temp.append(m_lFeaturesSensor.at(i+t).second.at(z)); lFeaturesSensor_new.append(temp); } // //Check sizes // cout<<"lFeaturesSensor_new.size()"<<lFeaturesSensor_new.size()<<endl; // cout<<"lFeaturesSensor_new.at(0).size()"<<lFeaturesSensor_new.at(0).size()<<endl; // cout<<"m_lFeaturesSensor.size()"<<m_lFeaturesSensor.size()<<endl; // Display features if(m_bDisplayFeatures) emit paintFeatures((MyQList)lFeaturesSensor_new, m_bTriggerActivated); // Reset trigger m_bTriggerActivated = false; // ----9---- Classify features concurrently using mapped() ---------- //cout<<"----9----"<<endl; std::function<double (QList<double>&)> applyOpsClassification = [this](QList<double>& featData){ return applyClassificationCalcConcurrentlyOnSensorLevel(featData); }; QFuture<double> futureClassificationResults = QtConcurrent::mapped(lFeaturesSensor_new.begin(), lFeaturesSensor_new.end(), applyOpsClassification); futureClassificationResults.waitForFinished(); // ----10---- Generate final classification result -> average all classification results //cout<<"----10----"<<endl; double dfinalResult = 0; for(int i = 0; i<futureClassificationResults.resultCount() ;i++) dfinalResult += futureClassificationResults.resultAt(i); dfinalResult = dfinalResult/futureClassificationResults.resultCount(); //cout << "dfinalResult" << dfinalResult << endl << endl; // ----11---- Store final result //cout<<"----11----"<<endl; m_lClassResultsSensor.append(dfinalResult); // ----12---- Send result to the output stream, i.e. which is connected to the triggerbox //cout<<"----12----"<<endl; VectorXd variances(iNumberOfFeatures); variances.setZero(); for(int i = 0; i<lFeaturesSensor_new.size(); i++) for(int t = 0; t<iNumberOfFeatures; t++) variances(t) = variances(t) + lFeaturesSensor_new.at(i).at(t); variances = variances/lFeaturesSensor_new.size(); m_pBCIOutputOne->data()->setValue(dfinalResult); m_pBCIOutputTwo->data()->setValue(variances(0)); m_pBCIOutputThree->data()->setValue(variances(1)); for(int i = 0; i<filteredRows.at(0).second.cols() ; i++) { m_pBCIOutputFour->data()->setValue(filteredRows.at(0).second(0,i)); m_pBCIOutputFive->data()->setValue(filteredRows.at(1).second(0,i)); } // Clear classifications clearFeatures(); // Reset counter m_iNumberOfCalculatedFeatures = 0; } // End if enough features (windows) have been calculated (processed) } // End if artefact reduction else { // If trial has been rejected -> plot zeros as result and the filtered electrode channel m_pBCIOutputOne->data()->setValue(0); m_pBCIOutputTwo->data()->setValue(0); m_pBCIOutputThree->data()->setValue(0); QList< QPair<int,RowVectorXd> > filteredRows = qlMatrixRows; if(m_bUseFilter) { QFuture<void> futureFilter = QtConcurrent::map(filteredRows,[this](QPair<int,RowVectorXd>& chdata) { applyFilterOperatorConcurrently(chdata); }); futureFilter.waitForFinished(); } for(int i = 0; i<filteredRows.at(0).second.cols() ; i++) { m_pBCIOutputFour->data()->setValue(filteredRows.at(0).second(0,i)); m_pBCIOutputFive->data()->setValue(filteredRows.at(1).second(0,i)); } } m_iTBWIndexSensor = 0; } } } }