SpectroSampleSequencer.cpp 13.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
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
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/*
 * Nomad Instrument Control Software
 *
 * Copyright 2011 Institut Laue-Langevin
 *
 * Licensed under the EUPL, Version 1.1 only (the "License");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 */

#include "SpectroSampleSequencer.h"
#include "controllers/common/datafile/NexusDataFile.h"

using namespace boost;

namespace d22special {

const std::string SpectroSampleSequencer::TYPE = "spectroSampleSequencer";
const int32 SpectroSampleSequencer::ONLY_SPECTRO = 0;
const int32 SpectroSampleSequencer::ONLY_SANS = 1;
const int32 SpectroSampleSequencer::BOTH_SANS_SPECTRO = 2;

SpectroSampleSequencer::SpectroSampleSequencer(const std::string& name) :
		lss::SampleSequencer(name) {
	// Reuse the super class constructor but initialize the countWithSpectro controller specifically
	spectro.init(this, "spectro");

	useCountWithSpectro.init(this, SAVE, "use_countWithSpectro");
	integrationTime.init(this, SAVE, "integration_time"); //in microseconds!
	scansToAverage.init(this, SAVE, "scans_average");
	spectrumDataForActualSlot.init(this, NOSAVE, "spectrum_data");

	m_CountStarted = false;
	m_ChangerStarted = false;
	m_yDataArray = nullptr;
}

SpectroSampleSequencer::SpectroSampleSequencer(const SpectroSampleSequencer& controller) :
		lss::SampleSequencer(controller) {

	spectro.copy(controller.spectro);

	useCountWithSpectro.copy(this, controller.useCountWithSpectro);
	integrationTime.copy(this, controller.integrationTime); //in microseconds!
	scansToAverage.copy(this, controller.scansToAverage);
	spectrumDataForActualSlot.copy(this, controller.spectrumDataForActualSlot);

	m_CountStarted = false;
	m_ChangerStarted = false;
	m_yDataArray = nullptr;
}

SpectroSampleSequencer::~SpectroSampleSequencer() {

}

void SpectroSampleSequencer::postConfiguration() {
	lss::SampleSequencer::postConfiguration();
}

void SpectroSampleSequencer::start() {
	if (useCountWithSpectro()) {
		startUsingCountWithSpectro();
	} else {
		lss::SampleSequencer::start();
	}
}

void SpectroSampleSequencer::stop() {
	if (useCountWithSpectro()) {
		stopUsingCountWithSpectro();
	} else {
		lss::SampleSequencer::stop();
	}
}

void SpectroSampleSequencer::pause() {
	if (useCountWithSpectro()) {
		pauseUsingCountWithSpectro();
	} else {
		lss::SampleSequencer::pause();
	}
}

void SpectroSampleSequencer::resume() {
	if (useCountWithSpectro()) {
		resumeUsingCountWithSpectro();
	} else {
		lss::SampleSequencer::resume();
	}
}

void SpectroSampleSequencer::updateIntegrationTime() {
	std::cout << "updating integration time " << spectro->integrationTime() << std::endl;
	integrationTime = spectro->integrationTime();
}

void SpectroSampleSequencer::updateScansToAverage() {
	scansToAverage = spectro->scansToAverage();
}

void SpectroSampleSequencer::startUsingCountWithSpectro() {
	commandStatus.setRunning();

	// Load data
	int32 apply_nbSlot = slot.setpoint();
	std::string apply_timeType = timeType();
	int32 apply_samplePosition[apply_nbSlot];
	float64 apply_acquisitionTime[apply_nbSlot];
	float64 apply_Transmission[apply_nbSlot];
	float64 apply_Thickness[apply_nbSlot];
	std::string apply_acquisitionTitle[apply_nbSlot];

	for (int32 i = 0; i < apply_nbSlot; i++) {
		apply_samplePosition[i] = samplePosition.get(i);
		apply_acquisitionTime[i] = acquisitionTime.get(i);
		apply_Transmission[i] = transmission.get(i);
		apply_Thickness[i] = thickness.get(i);
		apply_acquisitionTitle[i] = acquisitionTitle.get(i);
	}

	obtainSlotsAndActions();

	// configure countWithSpectro
	bool countControllerOk = true;
	commandProgression = 0;
	try {
		count->mode = BaseCount::TIME_MODE;
		count->saveData = true;
		count->timeType = apply_timeType;

	} catch (CannotSetValue &e) {
		log(Level::s_Error) << name << emptycursor << "Cannot set value for acquisition controller" << endlog;
		countControllerOk = false;
	}
	log(Level::s_Info) << name << cursor << apply_nbSlot << " slots" << endlog;

	// Common stuff for each position
	sampleChanger->useAdjust = false;
	sampleChanger->changer = changer();

	for (int32 i = 0; i < m_executionOrder.size(); i++) {
		std::list<std::pair<int32, int32>> pointsToExecute = m_executionOrder[i];
		for (std::list<std::pair<int32, int32>>::const_iterator it = pointsToExecute.begin(); it != pointsToExecute.end(); ++it) {
			int32 slotPosition = it->first;
			int32 slotAction = it->second;

			std::cout << "-> Executing slot at index " << i << std::endl;

			// (1) Only load count parameters if a SANS measure is going to be taken
			if (slotAction != ONLY_SPECTRO) {
				// Obtain index related of the position ! -> WE ASUME A POSITION IS NOT REPEATED! ASK! IS IT LOGIC TO HAVE REPEATED SLOTS WITH DIFFERENT params?
				currentAcquisitionTime = apply_acquisitionTime[i];

				try {
					count->time.setpoint = apply_acquisitionTime[i];
					count->subtitle = apply_acquisitionTitle[i];
					// Set total repetition to 1 by default
					count->totalReps = 1;
				} catch (CannotSetValue&) {
					log(Level::s_Error) << name << emptycursor << "Cannot set value for acquisition controller" << endlog;
					countControllerOk = false;
				}

				// Set values for transmission and thickness
//				try {
//					dataParams->setValue(dataparamsTransmission(), apply_Transmission[i]);
//					dataParams->setValue(dataparamsThickness(), apply_Thickness[i]);
//				} catch (...) {
//					std::cerr << "error in setting dataParams properties" << std::endl;
//				}
			}

			std::cout << "-> Changer in position " << slotPosition << std::endl;

			// (2) Move sampleChanger
			// Move changer to position
			sampleChanger->slot.setpoint = slotPosition;
			m_ChangerStarted = true;
			sampleChanger->startCommand();
			m_ChangerStarted = false;

			if (commandStatus.isWarning()) {
				//the state warning means the controller has been stopped during its execution
				break;
			}

			// (3) Do SANS and/or spectro measure
			if (slotAction == ONLY_SPECTRO) {

				std::cout << "--> measuring only spectro " << std::endl;
				// Position the spectro
				spectro->startCommand();

				// Store spectro measured
				storeSpectrum(i);

			} else if (slotAction == ONLY_SANS) {
				std::cout << "--> measuring only SANS " << std::endl;

				// Move changer to slotPOsition but ONLY do a SANS measure
				count->startCommand();

				// Store the slot index and its related numor
				std::cout << "    numor " << count->numor() << std::endl;
				m_numors[i] = count->numor();
			} else {

				std::cout << "--> measuring both SANS and spectro " << std::endl;

				// Do both measures
				startSpectroAndCount();

				// Store spectro measured but first get the correct slot index for the spectro done in this slot (remember shift of +2)
				int32 slotValueAtCurrentIndex = samplePosition.get(i);
				int32 realSlotValueOfSpectrumData = slotValueAtCurrentIndex + 2;
				// Get closest slot index (not executed yet) where we find "realSlotValueOfSpectrumData"
				bool found = false;
				int32 index;
				for (int32 j = i; j < slot.setpoint(); j++) {
					if (!found && samplePosition.get(j) == realSlotValueOfSpectrumData) {
						found = true;
						index = j;
					}
				}
				if (found) {
					storeSpectrum(index);
				}

				// Store the slot index and its related numor
				std::cout << "    numor " << count->numor() << std::endl;
				m_numors[i] = count->numor();
			}
		}
	}

	// At the very end do all needed appends of spectrum data
	appendSpectrumInDataFile();

	// log stuff

	log(Level::s_Info) << name << emptycursor << apply_nbSlot << " slots" << endlog;
	commandStatus.setIdle();
	commandProgression = 100;
}

void SpectroSampleSequencer::stopUsingCountWithSpectro() {
	commandStatus.setWarning();

	if (count->commandStatus.isRunning()) { //verify we set the commandStatus property
		count->stopCommand();
	} else if (sampleChanger->commandStatus.isRunning()) {
		sampleChanger->stopCommand();
	}

	log(Level::s_Info) << name << emptycursor << "stopped" << endlog;
}

void SpectroSampleSequencer::pauseUsingCountWithSpectro() {
	// TODO
}

void SpectroSampleSequencer::resumeUsingCountWithSpectro() {
	//TODO
}

void SpectroSampleSequencer::startSpectroAndCount() {
	// Like in CountWithSpectro
	//Launch count and spectro at the same time
	// Run the threads in parallel in a group
	boost::thread_group group;

	group.create_thread(boost::bind(&SpectroSampleSequencer::startCount, this));
	group.create_thread(boost::bind(&SpectroSampleSequencer::startSpectro, this));

	// Wait for the termination of the threads
	group.join_all();
}

void SpectroSampleSequencer::startCount() {
	count->startCommand();
}

void SpectroSampleSequencer::startSpectro() {
	// TO ASK! NO MULTIPLE SPECTRA MEASURES IN THIS MODE but average is possible
	if (commandStatus.isRunning()) {
		spectro->startCommand();
//		m_yDataArray = spectro->yData();
	}

	// Store it using as index the slot position
//	m_spectrum[slot()] = m_yDataArray;

}

void SpectroSampleSequencer::obtainSlotsAndActions() {
	// Clean former sequencer
	m_executionOrder.clear();

	// The slot position refers to the slot where a SANS measure is going to be taken
	for (int32 i = 0; i < slot.setpoint(); i++) { //slot.setpoint == number of lines to execute
		std::list<std::pair<int32, int32>> positionsToExecuteForLine;
		int32 slotPosition = samplePosition.get(i);
		int32 slotPositionMinusTwo = slotPosition - 2;
		int32 slotPositionPlusTwo = slotPosition + 2;

		// We can do both SANS and spectro if we found the (slotPosition + 2) value if the sequence not yet executed
		// We should validate than the characteristics are the same
		bool foundPlusTwo = false;
		for (int32 j = i; j < slot.setpoint(); j++) {
			if (slotPositionPlusTwo == samplePosition.get(j)) {
				foundPlusTwo = true;
			}
		}

		// Maybe we cannot do both measures at the same time but we can do a spectro measure previously but moving the sampler two positions to the left
		if (slotPositionMinusTwo > 0 && !checkPositionIsHasNotBeenAlreadyMeasured(slotPositionMinusTwo)) {
			positionsToExecuteForLine.push_back(std::pair<int32, int32>(slotPositionMinusTwo, ONLY_SPECTRO)); // extra position added!
		}
		if (slotPosition > 2) {
			if (foundPlusTwo) {
				positionsToExecuteForLine.push_back(std::pair<int32, int32>(slotPosition, BOTH_SANS_SPECTRO));
			} else {
				positionsToExecuteForLine.push_back(std::pair<int32, int32>(slotPosition, ONLY_SANS));
			}
		}
		m_executionOrder[i] = positionsToExecuteForLine;
	}

	// Verify content
	for (int32 i = 0; i < m_executionOrder.size(); i++) {
		std::list<std::pair<int32, int32>> pointsToExecute = m_executionOrder[i];
		for (std::list<std::pair<int32, int32>>::const_iterator it = pointsToExecute.begin(); it != pointsToExecute.end(); ++it) {
		}
	}
}

bool SpectroSampleSequencer::checkPositionIsHasNotBeenAlreadyMeasured(int32 slotPositionMinusTwo) {

//	std::cout << "has position " << slotPositionMinusTwo << "been already measured? " << std::endl;
	for (int32 i = 0; i < m_executionOrder.size(); i++) {
		std::list<std::pair<int32, int32>> pointsToExecute = m_executionOrder[i];
		for (std::list<std::pair<int32, int32>>::const_iterator it = pointsToExecute.begin(); it != pointsToExecute.end(); ++it) {
			int32 slotToMeasure = it->first;
			int32 typeOfMeasureToDoInSlot = it->second;
			if ((slotToMeasure == slotPositionMinusTwo) && (typeOfMeasureToDoInSlot == BOTH_SANS_SPECTRO)) {
//				std::cout << "yes!" << std::endl;
				return true;
			}
		}
	}
//	std::cout << "no!" << std::endl;
	return false;
}

void SpectroSampleSequencer::storeSpectrum(int32 executionLine) {
//	int32 expectedNumorForSpectrum = count->numor() + 2;
	float64* spectrum = spectro->yData();

	std::cout << "Saving locally spectrum for execution slot " << executionLine << std::endl;
	m_spectrum.insert(std::pair<int32, float64*>(executionLine, spectrum));
}

void SpectroSampleSequencer::appendSpectrumInDataFile() {

	for (int32 i = 0; i < slot.setpoint(); i++) {
		// If we have same slot in both maps
		if ((m_numors.find(i) != m_numors.end()) && (m_spectrum.find(i) != m_spectrum.end())) {
			int32 numor = m_numors[i];
			spectrumDataForActualSlot.update(m_spectrum.at(i));
			spectrumDataForActualSlot.setSize(1044);
			NexusDataFile::appendTo(numor, "NxD22SpecialServerFile.xml", "NxD22SpecialClientFile.xml");
			std::cout << "appending spectrum related to numor " << numor << " related to execution line " << i << std::endl;
		} else {
			// Error? Or it is just a special case
		}
	}
}

/*
 * setEnabled
 */
void SpectroSampleSequencer::setEnabledForLoading(bool all, bool postconf) {
	if (useCountWithSpectro()) {
		addExcludeSetEnableController(dataParams.getRole());
		addExcludeSetEnableController(count.getRole());
		ExperimentController::setEnabledForLoading(all, postconf);
	} else {
		lss::SampleSequencer::setEnabledForLoading(all, postconf);
	}
}

/*
 * setDisabled
 */
void SpectroSampleSequencer::setDisabled(bool all) {
	if (useCountWithSpectro()) {
		addExcludeSetEnableController(dataParams.getRole());
		addExcludeSetEnableController(count.getRole());
		ExperimentController::setDisabled(all);
	} else {
		lss::SampleSequencer::setDisabled(all);
	}
}

}