RemoteDPPCoincidence.cpp 8.24 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
/*
 * 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 "RemoteDPPCoincidence.h"
#include <common/base/ServerProperties.h>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
24
#include <boost/property_tree/json_parser.hpp>
25
26
27
28
29
30
31
#include <cstdlib>

namespace npp {

using namespace std;
using namespace common;
using namespace boost;
yannick legoc's avatar
yannick legoc committed
32
using namespace cameo;
33
using namespace lstdpp128;
34
35

using boost::property_tree::ptree;
36
37
38
39

const std::string RemoteDPPCoincidence::TYPE = "remote_dpp_coincidence";

RemoteDPPCoincidence::RemoteDPPCoincidence(const std::string& name) :
40
	RemoteDPPLiveProcess(name) {
41
42
43

	dT.init(this, SAVE, "dT");
	cleanDT.init(this, SAVE, "clean_dT");
44
45
46
47
	numberOfDetectorChannels.init(this, SAVE, "number_of_detector_channels");
	detectorChannel.init(this, SAVE, "detector_channel");
	coincidenceResolution.init(this, SAVE, "coincidence_resolution");
	maxBlock.init(this, SAVE, "max_block");
48
	refreshTimeS.init(this, SAVE, "refresh_time_s");
49
50
51
	totalNumberOfChannels.init(this, NOSAVE, "total_number_of_channels");

	nOrder.init(this, NOSAVE, "n_order");
52
53
54
55
56
	order.init(this, NOSAVE, "order");
	globalRate.init(this, NOSAVE, "global_rate");
	globalCleanRate.init(this, NOSAVE, "global_clean_rate");
	detectorRate.init(this, NOSAVE, "detector_rate");
	detectorCleanRate.init(this, NOSAVE, "detector_clean_rate");
57
58
59
60
61
62
63

	crateId.init(this, NOSAVE, "crate_id");
	boardId.init(this, NOSAVE, "board_id");
	channelId.init(this, NOSAVE, "channel_id");
	channelRate.init(this, NOSAVE, "channel_rate");

	registerRefresher(numberOfDetectorChannels, &RemoteDPPCoincidence::refreshNumberOfDetectorChannels, this);
64
65
66
}

RemoteDPPCoincidence::RemoteDPPCoincidence(const RemoteDPPCoincidence& controller) :
67
	RemoteDPPLiveProcess(controller) {
68
69
70
71
72
73
74
}

RemoteDPPCoincidence::~RemoteDPPCoincidence() {
}

void RemoteDPPCoincidence::postConfiguration() {

75
	RemoteDPPLiveProcess::postConfiguration();
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

	// order
	nOrder.set(7);

	order.resize(7);
	globalRate.resize(7);
	globalCleanRate.resize(7);
	detectorRate.resize(7);
	detectorCleanRate.resize(7);

	// properties
	for (int32 i = 0; i < 7; i++) {
		order.set(i, i + 2);
	}

	resetData();
}

void RemoteDPPCoincidence::setDetectorControllers(const std::vector<ControllerPtr<acquisition::DetectorController> > & detectorControllers) {

	DPPLiveProcess::setDetectorControllers(detectorControllers);

	// register the list mode data
	int32 index = 0;
	for (vector<ControllerPtr<acquisition::DetectorController> >::const_iterator c = detectorControllers.begin(); c != detectorControllers.end(); ++c) {
		registerUpdater((*c)->listModeData, &RemoteDPPCoincidence::updateListModeData, this, index);
		index++;
	}
}

void RemoteDPPCoincidence::start() {

108
109
110
	// Need a mutex to avoid having two start at the same time.
	{
		boost::mutex::scoped_lock lock(m_mutex);
111

112
113
		initFileReading();
		resetData();
114

115
116
117
		// Numor
		string numor;
		size_t size = fileName().size();
118

119
120
121
122
123
124
		if (size < 6) {
			string prefix(6 - size, '0');
			numor = prefix + fileName();
		} else {
			numor = fileName();
		}
125

126
127
		// Setting the parameters
		ptree parameters;
128

129
130
131
		parameters.put("numor", numor);
		parameters.put("dT", dT() / 10);
		parameters.put("cleanDT", cleanDT() / 10);
132

133
134
135
136
137
138
139
140
141
		// detector channels
		ptree detectorChannelArray;
		ptree channel;
		int32 detectorChannelSize = detectorChannel.getSize();
		for (int32 i = 0; i < detectorChannelSize; ++i) {
			channel.put("", detectorChannel(i));
			detectorChannelArray.push_back(std::make_pair("", channel));
		}
		parameters.put_child("detectorChannels", detectorChannelArray);
142

143
144
145
146
		parameters.put("matrixResolution", coincidenceResolution());
		parameters.put("maxBlocks", maxBlock());
		parameters.put("blockSize", blockSize());
		parameters.put("refreshTime", refreshTimeS());
147

148
		ptree context = writeListModeContextToPropertyTree(listModeContext);
149

150
		parameters.put_child("context", context);
151

152
153
154
		// Serialize the parameters
		stringstream os;
		write_json(os, parameters, false);
155

156

157
158
		// Kill the application if one remains
		m_server->killAllAndWaitFor("ncoincidence");
159

160
161
		vector<string> args;
		args.push_back(os.str());
162

163
164
		// Start the application
		m_coincidenceApplication = m_server->start("ncoincidence", args);
165

166
167
168
169
170
		// Test if application started
		if (!m_coincidenceApplication->exists()) {
			log(Level::s_Error) << "cannot start coincidence application" << endlog;
			return;
		}
171

172
173
174
		// Create the publisher after the start of the application, because it is a blocking call
		m_publisher.reset();
		m_publisher = application::Publisher::create("dpp_publisher", 1);
175

176
		cout << "publisher " << *m_publisher << endl;
177

178
179
		// Wait for the subscriber
		bool sync = m_publisher->waitForSubscribers();
180

181
182
183
		// Create the subscriber after the publisher
		auto_ptr<cameo::application::Subscriber> subscriber = application::Subscriber::create(*m_coincidenceApplication, "dpp_coincidence_results");
		cout << "subscriber " << *subscriber << endl;
184

185
186
		// Start the test thread if necessary
		auto_ptr<boost::thread> thread = startFileReading();
187

188
189
190
191
192
193
194
		// Listen to the result stream
		vector<double> channelRates;
		while (subscriber->receive(channelRates)) {
			// copying the rates
			for (int32 i = 0; i < totalNumberOfChannels(); i++) {
				channelRate.set(i, channelRates[i]);
			}
195

196
197
198
			vector<double> coincidenceRates;
			if (!subscriber->receive(coincidenceRates)) {
				break;
199
200
			}

201
202
203
204
205
206
207
208
209
210
211
212
			if (coincidenceRates.size() <= 4 * 7) {
				// Copying values
				for (int32 i = 0; i < 7; ++i) {
					globalRate.set(i, coincidenceRates[i]);
					globalCleanRate.set(i, coincidenceRates[7 + i]);
					detectorRate.set(i, coincidenceRates[7 * 2 + i]);
					detectorCleanRate.set(i, coincidenceRates[7 * 3 + i]);
				}

			} else {
				cerr << "problem with coincidence rates size" << endl;
			}
213
214
		}

215
216
		// Wait for the termination of the application
		application::State state = m_coincidenceApplication->waitFor();
217

218
219
		// Join the test thread
		finishFileReading(thread);
220

221
		cout << "coincidence application terminated with state " << state << endl;
222
223
224
225
226
227
228
	}
}

void RemoteDPPCoincidence::raz() {
	resetData();
}

229
230
231
232
void RemoteDPPCoincidence::refreshNumberOfDetectorChannels(int32 value) {
	detectorChannel.resize(value);
}

233
234
void RemoteDPPCoincidence::updateListModeData(int index) {

235
	if (m_publisher.get() != 0 && !m_publisher->hasEnded()) {
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
		int32 size = detectorControllers[index]->listModeData.getSize();
		int32 * memoryBlock = detectorControllers[index]->listModeData();

		// put the array into a string
		string data(reinterpret_cast<char *>(memoryBlock), sizeof(int32) * size);

		// send the data
		m_publisher->send(data);

		cout << "updateListModeData " << index << " size " << size << endl;
	}
}

void RemoteDPPCoincidence::resetData() {

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	// Calculate the total number of channels
	BoardIterator b;

	if (b.end()) {
		totalNumberOfChannels = 0;

	} else {
		int32_t currentNbChannels = (*b).nbChannels;

		++b;
		while (!b.end()) {
			currentNbChannels += (*b).nbChannels;
			++b;
		}

		totalNumberOfChannels = currentNbChannels;
	}

	cout << "totalNumberOfChannels " << totalNumberOfChannels() << endl;

271
272
273
274
275
276
277
278
	// resetting values
	for (int32 i = 0; i < 7; ++i) {
		globalRate.set(i, 0.0);
		globalCleanRate.set(i, 0.0);
		detectorRate.set(i, 0.0);
		detectorCleanRate.set(i, 0.0);
	}

279
280
281
282
283
284
285
286
287
288
289
	crateId.resize(totalNumberOfChannels());
	boardId.resize(totalNumberOfChannels());
	channelId.resize(totalNumberOfChannels());
	channelRate.resize(totalNumberOfChannels());

	int32 i = 0;

	// Set the ids
	BoardIterator bc;
	while (!bc.end()) {

290
291
292
293
		if (boardHasEnergy((*bc).boardType)) {

			int32 nbChannels = (*bc).nbChannels;
			int32 histogramSize = (1 << boardEnergyResolution((*bc).boardType));
294

295
296
297
298
299
300
301
302
			for (int32 j = 0; j < nbChannels; ++j) {
				crateId.set(i, bc.crate());
				boardId.set(i, bc.board());
				channelId.set(i, j);
				channelRate.set(i, 0.0);

				++i;
			}
303
304
305
		}

		++bc;
306
307
308
309
	}
}

}