15 #include "ui_nmrfspectrumform.h"
16 #include "nmrfspectrum.h"
17 #include "signalgenerator.h"
18 #include "nmrspectrumbase_impl.h"
19 #include "autolctuner.h"
20 #include "pulserdriver.h"
22 REGISTER_TYPE(
XDriverList, NMRFSpectrum,
"NMR frequency-swept spectrum measurement");
25 XNMRFSpectrum::XNMRFSpectrum(
const char *name,
bool runtime,
26 Transaction &tr_meas,
const shared_ptr<XMeasure> &meas)
29 "SG1", false, ref(tr_meas), meas->drivers(), true)),
31 "AutoTuner", false, ref(tr_meas), meas->drivers(), true)),
33 "Pulser", false, ref(tr_meas), meas->drivers(), true)),
34 m_sg1FreqOffset(create<
XDoubleNode>(
"SG1FreqOffset", false)),
35 m_centerFreq(create<
XDoubleNode>(
"CenterFreq", false)),
38 m_active(create<
XBoolNode>(
"Active", true)),
39 m_tuneCycleStep(create<
XDoubleNode>(
"TuneCycleStep", false)),
40 m_tuneCycleStrategy(create<
XComboNode>(
"TuneCycleStrategy", false, true)) {
46 m_form->setWindowTitle(i18n(
"NMR Spectrum (Freq. Sweep) - ") + getLabel() );
49 tr[ *m_spectrum].setLabel(0,
"Freq [MHz]");
50 tr[ *tr[ *m_spectrum].axisx()->label()] = i18n(
"Freq [MHz]");
52 tr[ *centerFreq()] = 20;
53 tr[ *sg1FreqOffset()] = 0;
54 tr[ *freqSpan()] = 200;
57 for(
auto &&x: {
"As is",
"Await Manual Tune",
"Auto Tune",
"Cyclic Avg. BPSK",
"Cyclic Avg. QPSK",
"Cyclic Avg. QPSKxP.I"})
58 tr[ *tuneCycleStrategy()].add(x);
59 tr[ *tuneCycleStrategy()] = STRATEGY_ASIS;
63 xqcon_create<XQLineEditConnector>(m_sg1FreqOffset, m_form->m_edSG1FreqOffset),
64 xqcon_create<XQLineEditConnector>(m_centerFreq, m_form->m_edCenterFreq),
65 xqcon_create<XQLineEditConnector>(m_freqSpan, m_form->m_edFreqSpan),
66 xqcon_create<XQLineEditConnector>(m_freqStep, m_form->m_edFreqStep),
67 xqcon_create<XQComboBoxConnector>(m_sg1, m_form->m_cmbSG1, ref(tr_meas)),
68 xqcon_create<XQComboBoxConnector>(m_autoTuner, m_form->m_cmbAutoTuner, ref(tr_meas)),
69 xqcon_create<XQComboBoxConnector>(m_pulser, m_form->m_cmbPulser, ref(tr_meas)),
70 xqcon_create<XQToggleButtonConnector>(m_active, m_form->m_ckbActive),
71 xqcon_create<XQLineEditConnector>(m_tuneCycleStep, m_form->m_edTuneCycleStep),
72 xqcon_create<XQComboBoxConnector>(m_tuneCycleStrategy, m_form->m_cmbTuneCycleStrategy,
Snapshot( *m_tuneCycleStrategy))
76 m_lsnOnActiveChanged = tr[ *active()].onValueChanged().connectWeakly(
77 shared_from_this(), &XNMRFSpectrum::onActiveChanged);
78 tr[ *centerFreq()].onValueChanged().connect(m_lsnOnCondChanged);
79 tr[ *freqSpan()].onValueChanged().connect(m_lsnOnCondChanged);
80 tr[ *freqStep()].onValueChanged().connect(m_lsnOnCondChanged);
87 if(shot_this[ *active()]) {
88 switch(shot_this[ *tuneCycleStrategy()]) {
91 case STRATEGY_CYCLE_DBL:
92 case STRATEGY_CYCLE_QUAD:
93 case STRATEGY_CYCLE_OCT:
95 double x = shot_this[ *tuneCycleStep()] / shot_this[ *freqStep()];
96 if((x < 0.9) || (fabs(x - lrint(x)) > 0.003 * x))
97 gErrPrint(i18n(
"Invalid cyclic step."));
99 case STRATEGY_TUNE_AWAIT:
100 case STRATEGY_AUTOTUNE:
102 shared_ptr<XPulser> pulser__ = shot_this[ *pulser()];
104 gErrPrint(i18n(
"Pulser should be selected."));
106 tr[ *pulser__->firstPhase()] = 0;
107 tr[ *pulser__->invertPhase()] =
false;
110 if(shot_this[ *tuneCycleStep()] <= 0.0)
111 gErrPrint(i18n(
"Invalid tuning/cyclic step."));
115 onClear(shot_this, clear().
get());
116 m_lastFreqAcquired = -1000.0;
117 m_tunedFreq = -1000.0;
119 double newf = getMinFreq(shot_this) * 1e-6;
120 performTuning(shot_this, newf);
121 newf += shot_this[ *sg1FreqOffset()];
122 shared_ptr<XSG> sg1__ = shot_this[ *sg1()];
124 trans( *sg1__->freq()) = newf;
127 m_lsnOnTuningChanged.reset();
134 XNMRFSpectrum::checkDependencyImpl(
const Snapshot &shot_this,
137 shared_ptr<XSG> sg1__ = shot_this[ *sg1()];
138 if( !sg1__)
return false;
139 shared_ptr<XNMRPulseAnalyzer> pulse__ = shot_this[ *pulse()];
140 if(emitter != pulse__.get())
return false;
141 if(shot_emitter[ *pulse__].timeAwared() < shot_others[ *sg1__].time())
return false;
142 double freq = getCurrentCenterFreq(shot_this, shot_others);
143 if(m_lastFreqAcquired == freq) {
146 m_lastFreqAcquired = freq;
151 double cfreq = shot_this[ *centerFreq()];
152 double freq_span = shot_this[ *freqSpan()] * 1e-3;
153 return (cfreq - freq_span/2) * 1e6;
157 double cfreq = shot_this[ *centerFreq()];
158 double freq_span = shot_this[ *freqSpan()] * 1e-3;
159 return (cfreq + freq_span/2) * 1e6;
167 shared_ptr<XSG> sg1__ = shot_this[ *sg1()];
169 assert(shot_others[ *sg1__].time() );
170 double freq = shot_others[ *sg1__].freq() - shot_this[ *sg1FreqOffset()];
174 XNMRFSpectrum::performTuning(
const Snapshot &shot_this,
double newf) {
175 if((shot_this[ *tuneCycleStrategy()] != STRATEGY_AUTOTUNE) ||
176 (shot_this[ *tuneCycleStrategy()] != STRATEGY_TUNE_AWAIT))
179 if(fabs(m_tunedFreq - newf) <= shot_this[ *tuneCycleStep()] / 2 * 1e-3)
182 newf += shot_this[ *tuneCycleStep()] / 2 * 1e-3;
184 shared_ptr<XPulser> pulser__ = shot_this[ *pulser()];
186 gWarnPrint(i18n(
"Pulser should be selected."));
190 trans( *pulser__->output()) =
false;
191 shared_ptr<XNMRPulseAnalyzer> pulse__ = shot_this[ *pulse()];
193 trans( *pulse__->avgClear()).touch();
195 if((shot_this[ *tuneCycleStrategy()] == STRATEGY_TUNE_AWAIT)) {
196 g_statusPrinter->printMessage(getLabel() +
" " + i18n(
"Tune it by yourself to") +
197 formatString(
" %.3f~MHz", newf) + i18n(
", and turn pulse on again."),
true, __FILE__, __LINE__,
true);
199 if((shot_this[ *tuneCycleStrategy()] == STRATEGY_AUTOTUNE)) {
200 shared_ptr<XAutoLCTuner> autotuner = shot_this[ *autoTuner()];
202 gWarnPrint(i18n(
"AutoTuner should be selected."));
206 m_lsnOnTuningChanged = tr[ *autotuner->tuning()].onValueChanged().connectWeakly(
208 tr[ *autotuner->target()] = newf;
214 XNMRFSpectrum::rearrangeInstrum(
const Snapshot &shot_this) {
215 m_lsnOnTuningChanged.reset();
217 if(shot_this[ *active()]) {
218 shared_ptr<XSG> sg1__ = shot_this[ *sg1()];
222 if( !shot_sg[ *sg1__].time())
225 double freq = getCurrentCenterFreq(shot_this, shot_sg) * 1e-6;
227 double cfreq = shot_this[ *centerFreq()];
228 double freq_span = shot_this[ *freqSpan()] * 1e-3;
229 if(cfreq <= freq_span / 2) {
230 throw XRecordError(i18n(
"Invalid center freq."), __FILE__, __LINE__);
233 double freq_step = shot_this[ *tuneCycleStep()] * 1e-3;
234 int num_psk_cycles = 0;
235 switch(shot_this[ *tuneCycleStrategy()]) {
237 freq_step = shot_this[ *freqStep()] * 1e-3;
239 case STRATEGY_CYCLE_DBL:
240 num_psk_cycles = 2;
break;
241 case STRATEGY_CYCLE_QUAD:
242 num_psk_cycles = 4;
break;
243 case STRATEGY_CYCLE_OCT:
244 num_psk_cycles = 8;
break;
246 if(freq_span < freq_step * 1.5) {
247 throw XRecordError(i18n(
"Too large freq. step."), __FILE__, __LINE__);
253 if(newf >= getMaxFreq(shot_this) * 1e-6) {
254 double x = (newf - getMinFreq(shot_this) * 1e-6) / freq_step;
255 newf -= floor(x + 0.01) * freq_step;
257 if(m_lastCycle >= num_psk_cycles) {
259 newf += shot_this[ *freqStep()] * 1e-3;
260 if((newf - getMinFreq(shot_this) * 1e-6) / freq_step > 0.99) {
261 trans( *active()) =
false;
265 shared_ptr<XPulser> pulser__ = shot_this[ *pulser()];
267 throw XRecordError(i18n(
"Pulser should be selected."), __FILE__, __LINE__);
268 if( ***pulser__->rtime() < 1000)
269 throw XRecordError(i18n(
"Too short repetition period."), __FILE__, __LINE__);
271 tr[ *pulser__->firstPhase()] = m_lastCycle % 4;
272 tr[ *pulser__->invertPhase()] = (m_lastCycle / 4) ?
true :
false;
276 newf = round(newf * 1e8) / 1e8;
278 performTuning(shot_this, newf);
280 newf += shot_this[ *sg1FreqOffset()];
282 trans( *sg1__->freq()) = newf;
288 shared_ptr<XPulser> pulser__ = shot_this[ *pulser()];
289 if( !pulser__)
return;
292 shared_ptr<XAutoLCTuner> autotuner = shot_this[ *autoTuner()];
295 if(shot_tuner[ *autotuner->tuning()])
297 if( !shot_tuner[ *autotuner->succeeded()])
301 m_lsnOnTuningChanged.reset();
302 if(shot_this[ *active()]) {
304 trans( *pulser__->output()) =
true;
308 XNMRFSpectrum::getValues(
const Snapshot &shot_this, std::vector<double> &values)
const {
309 int wave_size = shot_this[ *
this].wave().size();
310 double min__ = shot_this[ *
this].min();
311 double res = shot_this[ *
this].res();
312 values.resize(wave_size);
313 for(
unsigned int i = 0; i < wave_size; i++) {
314 double freq = min__ + i * res;
315 values[i] = freq * 1e-6;