qub_idlstim.cpp.html |
mathcode2html
|
Source file: qub_idlstim.cpp
|
Converted: Thu Feb 26 2015 at 13:39:00
|
This documentation file will
not reflect any later changes in the source file.
|
$$\phantom{******** If you see this on the webpage then the
browser could not locate *********}$$
$$\phantom{******** jsMath/easy/load.js or the variable root
is set wrong in this file *********}$$
$$\newcommand{\vector}[1]{\left[\begin{array}{c} #1 \end{array}\right]}$$
$$\newenvironment{matrix}{\left[\begin{array}{cccccccccc}} {\end{array}\right]}$$
$$\newcommand{\A}{{\cal A}}$$
$$\newcommand{\W}{{\cal W}}$$
/* Copyright 2008-2015 Research Foundation State University of New York */
/* This file is part of QUB Express. */
/* QUB Express 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 3 of the License, or */
/* (at your option) any later version. */
/* QUB Express 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, */
/* named LICENSE.txt, in the QUB Express program directory. If not, see */
/* <http://www.gnu.org/licenses/>. */
/*
*/
#ifdef _WIN32
#include <windows.h>
#include <time.h>
#define sleep Sleep
#else
#include <stdlib.h>
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <math.h>
#include <string.h>
#include "qub_idlstim.h"
#include "qub_eventmaker.h"
class qub_idlstim
{
public:
int add_deltas;
double amp_delta;
double min_dur_ms;
double sampling_ms;
std::vector<double> known;
EventMaker eventMaker;
qub_idlstim(double *_amps, int _amp_count, int _add_deltas, double _amp_delta, double _min_dur_ms, double _sampling_ms)
: add_deltas(_add_deltas), amp_delta(_amp_delta), min_dur_ms(_min_dur_ms), sampling_ms(_sampling_ms)
{
for (int i=0; i<_amp_count; ++i)
known.push_back(_amps[i]);
}
~qub_idlstim()
{}
void add(float *samples, int sample_count)
{
std::vector<double> pageAmps(sample_count);
std::vector<int> pageAmpAssigned(sample_count);
// set pageAmps to nearest known, with pageAmpAssigned telling if it's within delta
if ( known.size() )
for (int i=0; i<sample_count; ++i)
pageAmpAssigned[i] = FindKnownAmp(known, samples[i], amp_delta, pageAmps[i]);
// set the rest of the pageamps to delta-separated levels if requested
double amp = 0.0;
int count = 0;
if ( add_deltas ) {
for ( int i=0; i < sample_count; ++i ) {
// end-of-event ?
if ( (count==0) || pageAmpAssigned[i] || (fabs(amp - samples[i]) >= amp_delta) ) {
// assign pageAmps for last event
if ( count ) {
double avg = 0.0;
for ( int j=count; j>0; --j )
avg += samples[i-j];
avg /= count;
for ( int j=count; j>0; --j )
pageAmps[i-j] = avg;
}
// setup next event, ignoring assigned (known)
if ( pageAmpAssigned[i] ) {
count = 0;
} else {
count = 1;
amp = samples[i];
}
}
else {
++count;
}
}
// assign pageAmps for last event (last count points of page)
if ( count ) {
double avg = 0.0;
for ( int j=count; j>0; --j )
avg += samples[sample_count-j];
avg /= count;
for ( int j=count; j>0; --j )
pageAmps[sample_count-j] = avg;
}
}
// generate events
amp = pageAmps[0];
count = 1;
for ( int i=1; i<sample_count; ++i ) {
if ( amp != pageAmps[i] ) {
eventMaker.add(amp, count);
amp = pageAmps[i];
count = 1;
}
else {
++count;
}
}
if ( count ) {
eventMaker.add(amp, count);
}
}
void done_add()
{
int StopFlag = 0; // bogus
eventMaker.consolidate(amp_delta, known, StopFlag);
}
int get_amp_count()
{
return (int) eventMaker.ampOfCls.size();
}
int get_amps(double *amps)
{
int n = (int) eventMaker.ampOfCls.size();
memcpy(amps, &(eventMaker.ampOfCls[0]), n*sizeof(double));
return n;
}
int get_next_dwells(int offset_in_data, int sample_count, int *firsts, int *lasts, int *classes, float *durations)
{
int last = offset_in_data - 1;
int ndwt = 0;
int cls, count;
while ( sample_count ) {
eventMaker.nextEvent(cls, count, sample_count);
if ( ! count )
break; // should never happen if add's counts match get_next_dwells's
sample_count -= count;
firsts[ndwt] = last + 1;
last += count;
lasts[ndwt] = last;
classes[ndwt] = cls;
++ndwt;
}
if ( min_dur_ms > 0.0 ) {
ndwt = delete_short_events(ndwt, firsts, lasts, classes, int(ceil(min_dur_ms / sampling_ms)));
}
if ( durations ) {
for (int i=0; i<ndwt; ++i)
durations[i] = (float) ((lasts[i] - firsts[i] + 1) * sampling_ms);
}
return ndwt;
}
};
QUBFAST_API void* qub_idlstim_create(double *amps, int amp_count, int add_deltas, double amp_delta, double min_dur_ms, double sampling_ms)
{
return new qub_idlstim(amps, amp_count, add_deltas, amp_delta, min_dur_ms, sampling_ms);
}
QUBFAST_API void qub_idlstim_destroy(void *idlstim)
{
delete (qub_idlstim*) idlstim;
}
QUBFAST_API void qub_idlstim_add(void *idlstim, float *samples, int count)
{
((qub_idlstim*) idlstim)->add(samples, count);
}
QUBFAST_API void qub_idlstim_done_add(void *idlstim)
{
((qub_idlstim*) idlstim)->done_add();
}
QUBFAST_API int qub_idlstim_get_amp_count(void *idlstim)
{
return ((qub_idlstim*) idlstim)->get_amp_count();
}
QUBFAST_API int qub_idlstim_get_amps(void *idlstim, double *amps)
{
return ((qub_idlstim*) idlstim)->get_amps(amps);
}
QUBFAST_API int qub_idlstim_get_next_dwells(void *idlstim, int offset_in_data, int sample_count,
int *firsts, int *lasts, int *classes, float *durations)
{
return ((qub_idlstim*) idlstim)->get_next_dwells(offset_in_data, sample_count, firsts, lasts, classes, durations);
}