VEXPController.cpp 13.1 KB
Newer Older
legoc's avatar
legoc committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * 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 "VEXPController.h"
#include "controllers/common/family/Families.h"
yannick legoc's avatar
yannick legoc committed
21
22
23
24
25
26

#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
#include <rapidjson/reader.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
legoc's avatar
legoc committed
27

legoc's avatar
legoc committed
28
using namespace boost;
ics's avatar
ics committed
29
using namespace std;
legoc's avatar
legoc committed
30

legoc's avatar
legoc committed
31
32
33
34
35
namespace vexp {

const string VEXPController::TYPE = "vexp_controller";

VEXPController::VEXPController(const string& name) :
36
	ExperimentController(name) {
37

legoc's avatar
legoc committed
38
39
	setFamily(family::HIDDEN);

legoc's avatar
legoc committed
40
41
42
43
44
45
46
47
48
49
50
51
	as.init(this, NOSAVE, "as");
	bs.init(this, NOSAVE, "bs");
	cs.init(this, NOSAVE, "cs");
	aa.init(this, NOSAVE, "aa");
	bb.init(this, NOSAVE, "bb");
	cc.init(this, NOSAVE, "cc");
	ax.init(this, NOSAVE, "ax");
	ay.init(this, NOSAVE, "ay");
	az.init(this, NOSAVE, "az");
	bx.init(this, NOSAVE, "bx");
	by.init(this, NOSAVE, "by");
	bz.init(this, NOSAVE, "bz");
legoc's avatar
legoc committed
52
53
54
	u.init(this, NOSAVE, "Umatrix");
	b.init(this, NOSAVE, "Bmatrix");

legoc's avatar
legoc committed
55
56
57
58
59
	qh.init(this, NOSAVE, "qh");
	qk.init(this, NOSAVE, "qk");
	ql.init(this, NOSAVE, "ql");
	en.init(this, NOSAVE, "en");
	qm.init(this, NOSAVE, "qm");
60
	fx.init(this, NOSAVE, "fx");
61
	ss.init(this, NOSAVE, "ss");
legoc's avatar
legoc committed
62
63
64
65
66
67
68

	ki.init(this, NOSAVE, "ki");
	kf.init(this, NOSAVE, "kf");

	a1.init(this, NOSAVE, "a1");
	a2.init(this, NOSAVE, "a2");
	a3.init(this, NOSAVE, "a3");
yannick legoc's avatar
yannick legoc committed
69
	a3p.init(this, NOSAVE, "a3p");
legoc's avatar
legoc committed
70
71
72
73
	a4.init(this, NOSAVE, "a4");
	a5.init(this, NOSAVE, "a5");
	a6.init(this, NOSAVE, "a6");

ics's avatar
ics committed
74
75
76
77
78
	calcvalues.init(this, NOSAVE, "calcvalues");

	calca1.init(this, NOSAVE, "calca1");
	calca2.init(this, NOSAVE, "calca2");
	calca3.init(this, NOSAVE, "calca3");
yannick legoc's avatar
yannick legoc committed
79
	calca3p.init(this, NOSAVE, "calca3p");
ics's avatar
ics committed
80
81
82
83
	calca4.init(this, NOSAVE, "calca4");
	calca5.init(this, NOSAVE, "calca5");
	calca6.init(this, NOSAVE, "calca6");

84
	calculationStatus.init(this, NOSAVE, "calculation_status");
85
86
	calculationError.init(this, NOSAVE, "calculation_error");

legoc's avatar
legoc committed
87
	errorMessage.init(this, NOSAVE, "error_message");
88
	moveModel.init(this, SAVE, "move_model");
legoc's avatar
legoc committed
89

90
91
92
93
94
95
96
97
98
99
	qhScan.init(this, NOSAVE, "qh_scan");
	qkScan.init(this, NOSAVE, "qk_scan");
	qlScan.init(this, NOSAVE, "ql_scan");
	enScan.init(this, NOSAVE, "en_scan");

	dqhScan.init(this, NOSAVE, "dqh_scan");
	dqkScan.init(this, NOSAVE, "dqk_scan");
	dqlScan.init(this, NOSAVE, "dql_scan");
	denScan.init(this, NOSAVE, "den_scan");

100
101
102
103
104
	kiScan.init(this, NOSAVE, "ki_scan");
	kfScan.init(this, NOSAVE, "kf_scan");
	fxScan.init(this, NOSAVE, "fx_scan");
	ssScan.init(this, NOSAVE, "ss_scan");

105
106
107
	nbPointsScan.init(this, NOSAVE, "nb_points_scan");
	runningScan.init(this, NOSAVE, "running_scan");

legoc's avatar
legoc committed
108
109
110
111
112
	tasSettings.init(this, "tas_settings");
	sample.init(this, "sample");
	scattering.init(this, "scattering");
	incidentBeam.init(this, "incident_beam");
	scatteredBeam.init(this, "scattered_beam");
legoc's avatar
legoc committed
113
114
115
116

	a1Controller.init(this, "A1");
	a2Controller.init(this, "A2");
	a3Controller.init(this, "A3");
yannick legoc's avatar
yannick legoc committed
117
	a3pController.init(this, "A3P");
legoc's avatar
legoc committed
118
119
120
	a4Controller.init(this, "A4");
	a5Controller.init(this, "A5");
	a6Controller.init(this, "A6");
121
122

	scanController.init(this, "scan");
legoc's avatar
legoc committed
123
124
125
}

VEXPController::VEXPController(const VEXPController& controller) :
126
	ExperimentController(controller) {
legoc's avatar
legoc committed
127
128
129
}

VEXPController::~VEXPController() {
130
}
legoc's avatar
legoc committed
131
132
133
134

void VEXPController::updateUMatrix() {
	u.update(sample->uRef());
	u.setSize(sample->uRef.getSize());
135
	u.sendEvent();
legoc's avatar
legoc committed
136
137
138
139
140
}

void VEXPController::updateBMatrix() {
	b.update(tasSettings->b());
	b.setSize(tasSettings->b.getSize());
141
	b.sendEvent();
legoc's avatar
legoc committed
142
143
}

ics's avatar
ics committed
144
void VEXPController::refreshCalcParameters(const std::string& value) {
145

146
	//cout << "refreshCalcParameters " << value << endl;
147

ics's avatar
ics committed
148
149
150
	// Parse the values.
	rapidjson::Document document;
	document.Parse(value.c_str());
151

ics's avatar
ics committed
152
153
154
155
156
	rapidjson::Value& ki = document["ki"];
	rapidjson::Value& kf = document["kf"];
	rapidjson::Value& qh = document["qh"];
	rapidjson::Value& qk = document["qk"];
	rapidjson::Value& ql = document["ql"];
157
	rapidjson::Value& fx = document["fx"];
158
	rapidjson::Value& ss = document["ss"];
159

ics's avatar
ics committed
160
	// Calculate the angles and the status.
161
	calculate(ki.GetDouble(), kf.GetDouble(), qh.GetDouble(), qk.GetDouble(), ql.GetDouble(), fx.GetInt(), ss.GetInt());
162
163
}

164
double toDouble(double value) {
ics's avatar
ics committed
165

166
167
168
	if (isinf(value)) {
		return numeric_limits<double>::max();
	}
ics's avatar
ics committed
169

170
171
172
	if (isnan(value)) {
		return 0.0;
	}
legoc's avatar
legoc committed
173

174
175
	return value;
}
ics's avatar
ics committed
176

177
void VEXPController::refreshFloat64Property(SimpleProperty<float64>& property, float64 value) {
legoc's avatar
legoc committed
178
179
180

	// Update the value.
	property = value;
legoc's avatar
legoc committed
181
182
}

183
184
185
186
187
188
189
190
void VEXPController::refreshFloat64PropertyToMoveModel(SimpleProperty<float64>& property, float64 value) {

	// Update the value only in case moveModel is true.
	if (moveModel()) {
		property = value;
	}
}

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
void VEXPController::updateScanReference(int index) {

	if (index == 0) {
		qhScan.update(scanController->reference.get(0));
	}
	else if (index == 1) {
		qkScan.update(scanController->reference.get(1));
	}
	else if (index == 2) {
		qlScan.update(scanController->reference.get(2));
	}
	else if (index == 3) {
		enScan.update(scanController->reference.get(3));
	}
}

void VEXPController::updateScanDelta(int index) {

	if (index == 0) {
		dqhScan.update(scanController->delta.get(0));
	}
	else if (index == 1) {
		dqkScan.update(scanController->delta.get(1));
	}
	else if (index == 2) {
		dqlScan.update(scanController->delta.get(2));
	}
	else if (index == 3) {
		denScan.update(scanController->delta.get(3));
	}
}

223
224
225
226
void VEXPController::updateNbPoints(int index) {
	nbPointsScan.update(scanController->nSteps.get(0));
}

227
void VEXPController::updateScanStatus() {
228
229
230
231
232
233
234
235
236
237
238

	bool running = scanController->commandStatus.isRunning();
	runningScan.update(running);

	if (running) {
		// Get ki, kf, fixed, ss when the scan is starting.
		kiScan = ki();
		kfScan = kf();
		fxScan = fx();
		ssScan = ss();
	}
239
240
}

ics's avatar
ics committed
241
void VEXPController::updateProperties() {
legoc's avatar
legoc committed
242

legoc's avatar
legoc committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	// Copy the values.
	as.update(tasSettings->as());
	bs.update(tasSettings->bs());
	cs.update(tasSettings->cs());
	aa.update(tasSettings->aa());
	bb.update(tasSettings->bb());
	cc.update(tasSettings->cc());
	ax.update(tasSettings->ax());
	ay.update(tasSettings->ay());
	az.update(tasSettings->az());
	bx.update(tasSettings->bx());
	by.update(tasSettings->by());
	bz.update(tasSettings->bz());

	updateUMatrix();
	updateBMatrix();

ics's avatar
ics committed
260
261
262
263
264
	qh.update(scattering->qh());
	qk.update(scattering->qk());
	ql.update(scattering->ql());
	en.update(scattering->en());
	qm.update(scattering->qm());
265
	fx.update(scattering->fx());
266
	ss.update(scattering->sens());
ics's avatar
ics committed
267
268
269
270
271
272
273

	ki.update(incidentBeam->ki());
	kf.update(scatteredBeam->kf());

	a1.update(a1Controller->position());
	a2.update(a2Controller->position());
	a3.update(a3Controller->position());
yannick legoc's avatar
yannick legoc committed
274
	a3p.update(a3pController->position());
ics's avatar
ics committed
275
276
277
	a4.update(a4Controller->position());
	a5.update(a5Controller->position());
	a6.update(a6Controller->position());
278
279
280
281
282
283
284
285
286
287
288
289
290

	qhScan.update(scanController->reference.get(0));
	qkScan.update(scanController->reference.get(1));
	qlScan.update(scanController->reference.get(2));
	enScan.update(scanController->reference.get(3));

	dqhScan.update(scanController->delta.get(0));
	dqkScan.update(scanController->delta.get(1));
	dqlScan.update(scanController->delta.get(2));
	denScan.update(scanController->delta.get(3));

	nbPointsScan.update(scanController->nSteps.get(0));
	runningScan.update(scanController->commandStatus.isRunning());
ics's avatar
ics committed
291
292
293
}

void VEXPController::postConfiguration() {
294
295
296
297
298
299
300
301
302
303
304
305
306
307

	// Register the property updaters.
	registerPropertyCopierByUpdate(tasSettings->as, as);
	registerPropertyCopierByUpdate(tasSettings->bs, bs);
	registerPropertyCopierByUpdate(tasSettings->cs, cs);
	registerPropertyCopierByUpdate(tasSettings->aa, aa);
	registerPropertyCopierByUpdate(tasSettings->bb, bb);
	registerPropertyCopierByUpdate(tasSettings->cc, cc);
	registerPropertyCopierByUpdate(tasSettings->ax, ax);
	registerPropertyCopierByUpdate(tasSettings->ay, ay);
	registerPropertyCopierByUpdate(tasSettings->az, az);
	registerPropertyCopierByUpdate(tasSettings->bx, bx);
	registerPropertyCopierByUpdate(tasSettings->by, by);
	registerPropertyCopierByUpdate(tasSettings->bz, bz);
legoc's avatar
legoc committed
308
309
310
311

	registerUpdater(sample->uRef, &VEXPController::updateUMatrix, this);
	registerUpdater(sample->b, &VEXPController::updateBMatrix, this);

ics's avatar
ics committed
312
313
314
315
316
	registerPropertyCopierByUpdate(scattering->qh, qh);
	registerPropertyCopierByUpdate(scattering->qk, qk);
	registerPropertyCopierByUpdate(scattering->ql, ql);
	registerPropertyCopierByUpdate(scattering->en, en);
	registerPropertyCopierByUpdate(scattering->qm, qm);
317
	registerPropertyCopierByUpdate(scattering->fx, fx);
318
	registerPropertyCopierByUpdate(scattering->sens, ss);
ics's avatar
ics committed
319
320
321
322
323
324
325

	registerPropertyCopierByUpdate(incidentBeam->ki, ki);
	registerPropertyCopierByUpdate(scatteredBeam->kf, kf);

	registerPropertyCopierByUpdate(a1Controller->position, a1);
	registerPropertyCopierByUpdate(a2Controller->position, a2);
	registerPropertyCopierByUpdate(a3Controller->position, a3);
yannick legoc's avatar
yannick legoc committed
326
	registerPropertyCopierByUpdate(a3pController->position, a3p);
ics's avatar
ics committed
327
328
329
330
331
332
333
334
335
	registerPropertyCopierByUpdate(a4Controller->position, a4);
	registerPropertyCopierByUpdate(a5Controller->position, a5);
	registerPropertyCopierByUpdate(a6Controller->position, a6);


	// To calculate the angles.
	registerRefresher(calcvalues, &VEXPController::refreshCalcParameters, this);

	// To move the model.
336
337
338
	registerRefresher(calca1, &VEXPController::refreshFloat64PropertyToMoveModel, this, a1Controller->position);
	registerRefresher(calca2, &VEXPController::refreshFloat64PropertyToMoveModel, this, a2Controller->position);
	registerRefresher(calca3, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3Controller->position);
yannick legoc's avatar
yannick legoc committed
339
	registerRefresher(calca3p, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3pController->position);
340
341
342
	registerRefresher(calca4, &VEXPController::refreshFloat64PropertyToMoveModel, this, a4Controller->position);
	registerRefresher(calca5, &VEXPController::refreshFloat64PropertyToMoveModel, this, a5Controller->position);
	registerRefresher(calca6, &VEXPController::refreshFloat64PropertyToMoveModel, this, a6Controller->position);
ics's avatar
ics committed
343

344
345
346
	// Scan properties.
	registerUpdater(scanController->reference, &VEXPController::updateScanReference, this);
	registerUpdater(scanController->delta, &VEXPController::updateScanDelta, this);
347
	registerUpdater(scanController->nSteps, &VEXPController::updateNbPoints, this);
348
349
	registerStatus(scanController, &VEXPController::updateScanStatus, this);

ics's avatar
ics committed
350
351
352
	updateProperties();
}

353
void VEXPController::calculate(float64 ki, float64 kf, float64 qh, float64 qk, float64 ql, int32 fx, int32 ss) {
ics's avatar
ics committed
354
355
356

	// Reset status.
	calculationStatus.setIdle();
357
	calculationError = 0;
ics's avatar
ics committed
358

ics's avatar
ics committed
359
360
361
362
363
364
365
366
367
368
369
370
371
	try {
		// Ki.
		incidentBeam->calcki = ki;

		// calca1, calca2, calcStatus are calculated.
		incidentBeam->calculate(tas::Beam::K_MODE);

		calca1 = toDouble(incidentBeam->calca1());
		calca2 = toDouble(incidentBeam->calca2());

		// Manage the status.
		if (incidentBeam->calcStatus.isError()) {
			calculationStatus.setError();
372
			calculationError = incidentBeam->calcError();
ics's avatar
ics committed
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
		}
		else if (incidentBeam->calcStatus.isWarning()) {
			calculationStatus.setWarning();
		}

		//cout << "Ki -> status " << incidentBeam->calcStatus() << endl;

		// Kf.
		scatteredBeam->calckf = kf;

		// calca1, calca2, calcStatus are calculated.
		scatteredBeam->calculate(tas::Beam::K_MODE);

		calca5 = toDouble(scatteredBeam->calca5());
		calca6 = toDouble(scatteredBeam->calca6());

		// Manage the status.
		if (scatteredBeam->calcStatus.isError()) {
			calculationStatus.setError();
392
			calculationError = scatteredBeam->calcError();
ics's avatar
ics committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
		}
		else if (scatteredBeam->calcStatus.isWarning() && !calculationStatus.isError()) {
			calculationStatus.setWarning();
		}

		//cout << "Kf -> status " << scatteredBeam->calcStatus() << endl;

		// Q.
		scattering->calcqh = qh;
		scattering->calcqk = qk;
		scattering->calcql = ql;
		scattering->calcen = 2.072 * (ki * ki - kf * kf);
		scattering->calcki = ki;
		scattering->calckf = kf;
407
		scattering->calcsens = ss;
ics's avatar
ics committed
408
409

		// Calculate by fixing Ki.
410
		scattering->calculate(tas::Beam::K_MODE, fx);
ics's avatar
ics committed
411
412
413
414
415

		calca3 = toDouble(scattering->calca3());
		calca3p = toDouble(scattering->calca3p());
		calca4 = toDouble(scattering->calca4());

416
417
418
419
420
421
422
//		cout << "calc A1 " << calca1() << endl;
//		cout << "calc A2 " << calca2() << endl;
//		cout << "calc A3 " << calca3() << endl;
//		cout << "calc A3P " << calca3p() << endl;
//		cout << "calc A4 " << calca4() << endl;
//		cout << "calc A5 " << calca5() << endl;
//		cout << "calc A6 " << calca6() << endl << endl;
ics's avatar
ics committed
423
424
425
426
427


		// Manage the status.
		if (scattering->calcStatus.isError()) {
			calculationStatus.setError();
428
			calculationError = scattering->calcError();
ics's avatar
ics committed
429
430
431
432
433
		}
		else if (scattering->calcStatus.isWarning() && !calculationStatus.isError()) {
			calculationStatus.setWarning();
			cerr << "Warning: Calculated Kf are different" << endl;
		}
ics's avatar
ics committed
434
	}
ics's avatar
ics committed
435
	catch (...) {
ics's avatar
ics committed
436
		calculationStatus.setError();
437
		calculationError = 0;
ics's avatar
ics committed
438
439
	}

440
441
442
//	if (calculationError() != 0) {
//		cout << "VEXP error " << calculationError() << endl;
//	}
legoc's avatar
legoc committed
443
444
445
}

}