VEXPController.cpp 12.6 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"
ics's avatar
ics committed
21
22
23
24
25
#include "contrib/rapidjson/document.h"
#include "contrib/rapidjson/reader.h"
#include "contrib/rapidjson/writer.h"
#include "contrib/rapidjson/stringbuffer.h"
#include "contrib/rapidjson/prettywriter.h"
legoc's avatar
legoc committed
26

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

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

const string VEXPController::TYPE = "vexp_controller";

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

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

legoc's avatar
legoc committed
39
40
41
42
43
44
45
46
47
48
49
50
	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
51
52
53
	u.init(this, NOSAVE, "Umatrix");
	b.init(this, NOSAVE, "Bmatrix");

legoc's avatar
legoc committed
54
55
56
57
58
	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");
59
	fx.init(this, NOSAVE, "fx");
60
	ss.init(this, NOSAVE, "ss");
legoc's avatar
legoc committed
61
62
63
64
65
66
67

	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
68
	a3p.init(this, NOSAVE, "a3p");
legoc's avatar
legoc committed
69
70
71
72
	a4.init(this, NOSAVE, "a4");
	a5.init(this, NOSAVE, "a5");
	a6.init(this, NOSAVE, "a6");

ics's avatar
ics committed
73
74
75
76
77
	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
78
	calca3p.init(this, NOSAVE, "calca3p");
ics's avatar
ics committed
79
80
81
82
	calca4.init(this, NOSAVE, "calca4");
	calca5.init(this, NOSAVE, "calca5");
	calca6.init(this, NOSAVE, "calca6");

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

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

89
90
91
92
93
94
95
96
97
98
99
100
101
	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");

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

legoc's avatar
legoc committed
102
103
104
105
106
	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
107
108
109
110

	a1Controller.init(this, "A1");
	a2Controller.init(this, "A2");
	a3Controller.init(this, "A3");
yannick legoc's avatar
yannick legoc committed
111
	a3pController.init(this, "A3P");
legoc's avatar
legoc committed
112
113
114
	a4Controller.init(this, "A4");
	a5Controller.init(this, "A5");
	a6Controller.init(this, "A6");
115
116

	scanController.init(this, "scan");
legoc's avatar
legoc committed
117
118
119
}

VEXPController::VEXPController(const VEXPController& controller) :
120
	ExperimentController(controller) {
legoc's avatar
legoc committed
121
122
123
}

VEXPController::~VEXPController() {
124
}
legoc's avatar
legoc committed
125
126
127
128

void VEXPController::updateUMatrix() {
	u.update(sample->uRef());
	u.setSize(sample->uRef.getSize());
129
	u.sendEvent();
legoc's avatar
legoc committed
130
131
132
133
134
}

void VEXPController::updateBMatrix() {
	b.update(tasSettings->b());
	b.setSize(tasSettings->b.getSize());
135
	b.sendEvent();
legoc's avatar
legoc committed
136
137
}

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

140
	//cout << "refreshCalcParameters " << value << endl;
141

ics's avatar
ics committed
142
143
144
	// Parse the values.
	rapidjson::Document document;
	document.Parse(value.c_str());
145

ics's avatar
ics committed
146
147
148
149
150
	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"];
151
	rapidjson::Value& fx = document["fx"];
152
	rapidjson::Value& ss = document["ss"];
153

ics's avatar
ics committed
154
	// Calculate the angles and the status.
155
	calculate(ki.GetDouble(), kf.GetDouble(), qh.GetDouble(), qk.GetDouble(), ql.GetDouble(), fx.GetInt(), ss.GetInt());
156
157
}

158
double toDouble(double value) {
ics's avatar
ics committed
159

160
161
162
	if (isinf(value)) {
		return numeric_limits<double>::max();
	}
ics's avatar
ics committed
163

164
165
166
	if (isnan(value)) {
		return 0.0;
	}
legoc's avatar
legoc committed
167

168
169
	return value;
}
ics's avatar
ics committed
170

171
void VEXPController::refreshFloat64Property(SimpleProperty<float64>& property, float64 value) {
legoc's avatar
legoc committed
172
173
174

	// Update the value.
	property = value;
legoc's avatar
legoc committed
175
176
}

177
178
179
180
181
182
183
184
void VEXPController::refreshFloat64PropertyToMoveModel(SimpleProperty<float64>& property, float64 value) {

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

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
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));
	}
}

void VEXPController::updateScanStatus() {
	runningScan.update(scanController->commandStatus.isRunning());
}

ics's avatar
ics committed
221
void VEXPController::updateProperties() {
legoc's avatar
legoc committed
222

legoc's avatar
legoc committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	// 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
240
241
242
243
244
	qh.update(scattering->qh());
	qk.update(scattering->qk());
	ql.update(scattering->ql());
	en.update(scattering->en());
	qm.update(scattering->qm());
245
	fx.update(scattering->fx());
246
	ss.update(scattering->sens());
ics's avatar
ics committed
247
248
249
250
251
252
253

	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
254
	a3p.update(a3pController->position());
ics's avatar
ics committed
255
256
257
	a4.update(a4Controller->position());
	a5.update(a5Controller->position());
	a6.update(a6Controller->position());
258
259
260
261
262
263
264
265
266
267
268
269
270

	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
271
272
273
}

void VEXPController::postConfiguration() {
274
275
276
277
278
279
280
281
282
283
284
285
286
287

	// 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
288
289
290
291

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

ics's avatar
ics committed
292
293
294
295
296
	registerPropertyCopierByUpdate(scattering->qh, qh);
	registerPropertyCopierByUpdate(scattering->qk, qk);
	registerPropertyCopierByUpdate(scattering->ql, ql);
	registerPropertyCopierByUpdate(scattering->en, en);
	registerPropertyCopierByUpdate(scattering->qm, qm);
297
	registerPropertyCopierByUpdate(scattering->fx, fx);
298
	registerPropertyCopierByUpdate(scattering->sens, ss);
ics's avatar
ics committed
299
300
301
302
303
304
305

	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
306
	registerPropertyCopierByUpdate(a3pController->position, a3p);
ics's avatar
ics committed
307
308
309
310
311
312
313
314
315
	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.
316
317
318
	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
319
	registerRefresher(calca3p, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3pController->position);
320
321
322
	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
323

324
325
326
327
328
	// Scan properties.
	registerUpdater(scanController->reference, &VEXPController::updateScanReference, this);
	registerUpdater(scanController->delta, &VEXPController::updateScanDelta, this);
	registerStatus(scanController, &VEXPController::updateScanStatus, this);

ics's avatar
ics committed
329
330
331
	updateProperties();
}

332
void VEXPController::calculate(float64 ki, float64 kf, float64 qh, float64 qk, float64 ql, int32 fx, int32 ss) {
ics's avatar
ics committed
333
334
335

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

ics's avatar
ics committed
338
339
340
341
342
343
344
345
346
347
348
349
350
	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();
351
			calculationError = incidentBeam->calcError();
ics's avatar
ics committed
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
		}
		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();
371
			calculationError = scatteredBeam->calcError();
ics's avatar
ics committed
372
373
374
375
376
377
378
379
380
381
382
383
384
385
		}
		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;
386
		scattering->calcsens = ss;
ics's avatar
ics committed
387
388

		// Calculate by fixing Ki.
389
		scattering->calculate(tas::Beam::K_MODE, fx);
ics's avatar
ics committed
390
391
392
393
394

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

395
396
397
398
399
400
401
//		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
402
403
404
405
406


		// Manage the status.
		if (scattering->calcStatus.isError()) {
			calculationStatus.setError();
407
			calculationError = scattering->calcError();
ics's avatar
ics committed
408
409
410
411
412
		}
		else if (scattering->calcStatus.isWarning() && !calculationStatus.isError()) {
			calculationStatus.setWarning();
			cerr << "Warning: Calculated Kf are different" << endl;
		}
ics's avatar
ics committed
413
	}
ics's avatar
ics committed
414
	catch (...) {
ics's avatar
ics committed
415
		calculationStatus.setError();
416
		calculationError = 0;
ics's avatar
ics committed
417
418
	}

419
420
421
//	if (calculationError() != 0) {
//		cout << "VEXP error " << calculationError() << endl;
//	}
legoc's avatar
legoc committed
422
423
424
}

}