Newer
Older
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <numeric>
ArrayWaveform::~ArrayWaveform() { unbindBuffer(); }
void* ArrayWaveform::getDataBuffer() { return this->pDataBuffer; }
int64_t ArrayWaveform::getDataLen() { return this->dataLen; }
void ArrayWaveform::setSamplingRate(ulong sr) {
this->wfmParam.samplingRate = sr;
ulong ArrayWaveform::getSamplingRate() { return this->wfmParam.samplingRate; }
void ArrayWaveform::setFreqResolution(ulong fr) {
this->wfmParam.freqResolution = fr;
ulong ArrayWaveform::getFreqResolution() { return this->wfmParam.freqResolution; }
void ArrayWaveform::setFreqTone(
int centerFreq,
int freqSpacing,
int numTones
) {
int freqStart = centerFreq -
freqSpacing * int(std::floor(numTones / 2));
numTones,
freqStart,
freqStart + freqSpacing * (numTones-1)
);
}
void ArrayWaveform::setFreqTone(const std::vector<int>& tones) {
this->wfmParam.freqTones.resize(tones.size());
for (auto i = 0; i < tones.size(); i++) {
this->wfmParam.freqTones[i] = tones[i];
}
std::vector<double> ArrayWaveform::getFreqTone() {
std::vector<double> v(
this->wfmParam.freqTones.data(),
this->wfmParam.freqTones.data() + this->wfmParam.freqTones.size()
);
return v;
void ArrayWaveform::setPhase(const std::vector<double>& phases) {
this->wfmParam.phases.resize(phases.size());
for (auto i = 0; i < phases.size(); i++) {
this->wfmParam.phases[i] = phases[i];
}
std::vector<double> ArrayWaveform::getPhase() {
std::vector<double> v(
this->wfmParam.phases.data(),
this->wfmParam.phases.data() + this->wfmParam.phases.size()
);
return v;
void ArrayWaveform::setAmplitude(const std::vector<double>& amplitudes) {
this->wfmParam.amplitudes.resize(amplitudes.size());
for (auto i = 0; i < amplitudes.size(); i++) {
this->wfmParam.amplitudes[i] = amplitudes[i];
}
std::vector<double> ArrayWaveform::getAmplitude() {
std::vector<double> v(
this->wfmParam.amplitudes.data(),
this->wfmParam.amplitudes.data() + this->wfmParam.amplitudes.size()
);
return v;
void ArrayWaveform::setDefaultParam() {
if (this->wfmParam.freqTones.size() == 0) {return;}
auto numTones = this->wfmParam.freqTones.size();
this->setPhase(std::vector(numTones, 0.0));
this->wfmParam.samplingRate = 614.4e6;
this->wfmParam.freqResolution = 1e3;
const static Eigen::IOFormat csvFormat(
Eigen::FullPrecision,
Eigen::DontAlignCols,
",",
",",
""
);
std::ofstream saveFile(fileName);
if (saveFile.is_open()) {
saveFile << this->wfmParam.samplingRate << "\n";
saveFile << this->wfmParam.freqResolution << "\n";
saveFile
if (!file.is_open()) {
std::cout << fileName
<< " does not exists in loadParam()"
<< std::endl;
return;
}
int lineCounter = 0;
for (auto& line : CSVRange(file)) {
std::vector<int> lineDataI;
std::vector<double> lineDataD;
switch (lineCounter) {
case 0:
for (auto i = 0; i < line.size(); i++) {
lineDataI.push_back(std::stoi(std::string(line[i])));
}
for (auto i = 0; i < line.size(); i++) {
lineDataD.push_back(std::stod(std::string(line[i])));
}
for (auto i = 0; i < line.size(); i++) {
lineDataD.push_back(std::stod(std::string(line[i])));
}
break;
}
lineCounter++;
}
}
std::cout << "sampling rate: "
<< this->wfmParam.samplingRate << "\n";
std::cout << "frequency resolution: "
<< this->wfmParam.freqResolution << "\n";
std::cout << "frequency tones (MHz): "
<< this->wfmParam.freqTones.transpose() / int(1e6)
<< "\n";
std::cout << "phases: "
<< this->wfmParam.phases.transpose() << "\n";
std::cout << "amplitudes: "
<< this->wfmParam.amplitudes.transpose() << "\n";
void ArrayWaveform::bindBuffer(int64_t bytes) {
this->unbindBuffer();
int fd = open("/dev/zero", O_RDONLY);
this->pDataBuffer = mmap(
NULL,
bytes,
PROT_READ | PROT_WRITE,
MAP_PRIVATE,
fd,
0
);
if (this->pDataBuffer != MAP_FAILED) {
memset(this->pDataBuffer, 0, bytes);
this->dataLen = bytes / 2;
int16_t* pData = (int16_t*) this->pDataBuffer;
}
close(fd);
}
void ArrayWaveform::unbindBuffer() {
if (this->dataLen != 0 and this->pDataBuffer != nullptr) {
munmap(this->pDataBuffer, this->dataLen * 2);
this->pDataBuffer = nullptr;
this->dataLen = 0;
}
}
ulong ArrayWaveform::getMinSampleLen(ulong samplingRate, ulong freqResolution) {
return 2 * samplingRate / std::gcd(samplingRate, freqResolution);
}
ulong ArrayWaveform::getSampleLen(
double tau,
ulong samplingRate,
ulong freqResolution
) {
ulong sampleLen = ulong(tau * samplingRate);
ulong minLen = getMinSampleLen(samplingRate, freqResolution);
return sampleLen % minLen == 0 ? sampleLen : (sampleLen / minLen + 1) * minLen;
}
double ArrayWaveform::setStaticSegment(
Eigen::Ref<Eigen::VectorXd> timeSeries,
double f,
double initPhase,
double amp
Eigen::Ref<Eigen::ArrayXd> t = timeSeries.array();
t -= t(0);
double nextPhase = 2 * M_PI * f * (t(t.size() - 1) + t(1)) + initPhase;
timeSeries.array() = amp * Eigen::sin(2 * M_PI * f * t + initPhase);
return nextPhase;
double ArrayWaveform::setMovingSegment(
Eigen::Ref<Eigen::VectorXd> timeSeries,
double fInit,
double fFinal,
double initPhase,
double amp
auto df = (fFinal - fInit) * 2 * M_PI;
auto sampleLen = timeSeries.size();
auto dt = timeSeries(1) - timeSeries(0);
auto tau = timeSeries(sampleLen - 1) - timeSeries(0) + dt;
auto accel = 4 * df / (tau * tau);
unsigned int midIdx = int(sampleLen / 2.0);
Eigen::Ref<Eigen::ArrayXd> segl = timeSeries(Eigen::seq(0, midIdx));
Eigen::Ref<Eigen::ArrayXd> segr = timeSeries(Eigen::seq(midIdx+1, sampleLen-1));
segr -= segl(0) + tau / 2; // it may seem more intuitive to use
// segr -= segr(0) here, but doing so
// will cause phase jump
segl -= segl(0);
segl = initPhase
+ 2 * M_PI * fInit * segl
+ accel / 6 * Eigen::pow(segl,3);
segr = segl(segl.size()-1)
+ (
2 * M_PI * fInit + accel / 2 * std::pow((tau / 2),2)
) * segr
+ accel / 2 * tau / 2 * Eigen::pow(segr, 2)
- accel / 6 * Eigen::pow(segr, 3);
double nextPhase = segr(segr.size() - 1) + dt * 2*M_PI * fFinal;
timeSeries = amp * Eigen::sin(timeSeries.array());
std::pair<void*, int64_t> ArrayWaveform::getStaticWaveform() {
auto minSampleLen = 2 * this->wfmParam.samplingRate
/ std::gcd(
this->wfmParam.samplingRate,
this->wfmParam.freqResolution
);
Eigen::VectorXd t = Eigen::VectorXd::LinSpaced(
minSampleLen,
0,
minSampleLen - 1
) / this->wfmParam.samplingRate;
Eigen::MatrixXd wfmMatrixrix = Eigen::sin(
(
(this->wfmParam.freqTones * t.transpose() * M_PI * 2)
.array().colwise()
+ this->wfmParam.phases.array())
).array().colwise() * this->wfmParam.amplitudes.array();
bindBuffer(minSampleLen * 2); // bytes
Eigen::Map<EigenVectorXi16, Eigen::Aligned16> dataMap(pData, minSampleLen);
return std::pair(this->pDataBuffer, int64_t(minSampleLen));
std::pair<void*, int64_t> ArrayWaveform::getTrickWaveform(
std::set<int> siteIndex,
double df,
double tauMove,
double tauStay
) {
if ((tauMove == 0 and tauStay == 0)
or siteIndex.empty()) {
}
if (tauMove != 0 and tauStay != 0) {
tauStay = std::ceil((tauMove + tauStay) * df) / df - tauMove;
} else if (tauMove != 0) {
tauMove = std::ceil(tauMove * df) / df;
} else {
tauStay = std::ceil(tauStay * df) / df;
}
auto tauTotal = tauMove * 2 + tauStay;
ulong sampleLen = getSampleLen(
tauTotal,
this->wfmParam.samplingRate,
this->wfmParam.freqResolution
);
ulong moveLen = tauMove * this->wfmParam.samplingRate;
ulong stayLen = tauStay * this->wfmParam.samplingRate;
auto idxSeg0 = moveLen;
auto idxSeg1 = moveLen + stayLen;
auto idxSeg2 = moveLen + stayLen + moveLen;
auto t = Eigen::ArrayXd::LinSpaced(sampleLen, 0, sampleLen - 1) / this->wfmParam.samplingRate;
Eigen::MatrixXd wfmMatrix(sampleLen, this->wfmParam.freqTones.size()); // site wfm stored column by column
for (auto i = 0; i < this->wfmParam.freqTones.size(); i++) {
wfmMatrix.col(i) = t;
Eigen::Ref<Eigen::ArrayXd> siteWfm = wfmMatrix.col(i);
auto fInit = this->wfmParam.freqTones[i];
auto phi = this->wfmParam.phases[i];
auto amp = this->wfmParam.amplitudes[i];
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
if (siteIndex.contains(i)) {
if (tauMove != 0) {
phi = setMovingSegment(
siteWfm(Eigen::seq(0, idxSeg0 - 1)),
fInit, fFinal, phi, amp
);
}
if (tauStay != 0) {
phi = setStaticSegment(
siteWfm(Eigen::seq(idxSeg0, idxSeg1 - 1)),
fFinal, phi, amp
);
}
if (tauMove != 0) {
phi = setMovingSegment(
siteWfm(Eigen::seq(idxSeg1, idxSeg2 - 1)),
fFinal, fInit, phi, amp
);
}
setStaticSegment(
siteWfm(Eigen::seq(idxSeg2, siteWfm.size() - 1)),
fInit, phi, amp
);
} else {
setStaticSegment(siteWfm, fInit, phi, amp);
}
}
Eigen::Map<EigenVectorXi16, Eigen::Aligned16> dataMap(pData, sampleLen);
return std::pair(this->pDataBuffer, int64_t(sampleLen));
const static Eigen::IOFormat csvFormat(
Eigen::FullPrecision,
Eigen::DontAlignCols,
"",
",",
""
);
auto pData = (int16_t*) this->pDataBuffer;
auto wfm = Eigen::Map<EigenVectorXi16>(pData, this->dataLen);
std::ofstream saveFile(fileName);
if (saveFile.is_open()) {
saveFile << wfm.format(csvFormat);
saveFile.close();
}