Commit 732afa8f authored by yannick legoc's avatar yannick legoc
Browse files

Starting with mantid reduction

parent dda6a36c
/RequestMessages.pb.cc
/RequestMessages.pb.h
<module name="mantidreduction">
<controller class="mantid::ReductionController"/>
<include path="$(NOMAD_HOME)/../NomadModules/src"/>
<script exec="protoc --cpp_out=. RequestMessages.proto"/>
</module>
/*
* 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 "ReductionController.h"
#include "controllers/common/family/Families.h"
#include "InstrumentManager/InstrumentManager.h"
#include "RequestMessages.pb.h"
#include <boost/lexical_cast.hpp>
#include <common/base/Date.h>
#include <fstream>
#include <iostream>
#include <nexus/napi.h>
namespace mantid {
using namespace std;
using namespace common;
using namespace boost;
using namespace cameo;
const std::string ReductionController::TYPE = "mantid_reduction";
const std::string ReductionController::REMOTE_APPLICATION = "madmanserver";
const std::string ReductionController::RESPONDER = "responder";
const std::string ReductionController::PUBLISHER = "publisher";
const std::string ReductionController::PROCESSED_FILE = "processed.nxs";
ReductionController::ReductionController(const std::string& name) :
ExperimentController(name) {
setFamily(family::ACQUISITION, family::COUNT);
serverEndpoint.init(this, SAVE, "cameo_server");
initialized.init(this, NOSAVE, "initialized");
fileDirectory.init(this, SAVE, "file_directory");
filename.init(this, SAVE, "filename");
x.init(this, NOSAVE, "x");
data.init(this, NOSAVE, "data");
}
ReductionController::ReductionController(const ReductionController& controller) :
ExperimentController(controller) {
}
ReductionController::~ReductionController() {
if (m_subscriberThread.get() != nullptr) {
m_subscriber->cancel();
m_subscriberThread->join();
}
if (m_remoteApplication.get() != nullptr) {
// Stop the remote application.
m_remoteApplication->stop();
// Wait for the termination
application::State state = m_remoteApplication->waitFor();
cout << "Remote application " << m_remoteApplication->getName() << " terminated with state " << application::toString(state) << endl;
}
}
void ReductionController::postConfiguration() {
if (serverEndpoint() == "") {
m_server.reset(new Server(application::This::getServer().getEndpoint()));
} else {
m_server.reset(new Server(serverEndpoint()));
}
initialized = initApplication();
registerControllers();
for (uint32 i = 0; i < m_scanControllers.size(); ++i) {
registerUpdater(m_scanControllers[i]->serializerEvent, &ReductionController::updateScanSerializerEvent, this, i);
}
}
void ReductionController::registerControllers() {
map<string, ExperimentController*> experimentControllersMap = InstrumentManager::getInstance()->getAllInstalledExperimentControllersMap();
map<string, ExperimentController*>::iterator it;
for (it = experimentControllersMap.begin(); it != experimentControllersMap.end(); it++) {
if (dynamic_cast<scan::GenericScan1D*>(it->second) != 0) {
scan::GenericScan1D* scan1D = dynamic_cast<scan::GenericScan1D*>(it->second);
scan1D->attach(this); //Attach it in order to be able to receive propertyChange events
m_scanControllers.push_back(scan1D);
cout << "Attached " << scan1D->getName() << endl;
}
}
}
void ReductionController::updateScanSerializerEvent(int32 i) {
if (m_scanControllers[i]->serializerEvent() == true) {
cout << "Scan numor " << m_scanControllers[i]->numor() << endl;
}
}
bool ReductionController::initApplication() {
// Do not initialize if it is already done
if (initialized()) {
return true;
}
// Start the remote server
if (!m_server->isAvailable(1000)) {
cout << "Remote server is not available" << endl;
return false;
}
cout << "Remote server is connected" << endl;
m_remoteApplication = m_server->connect(REMOTE_APPLICATION);
if (m_remoteApplication->exists()) {
// The application exists from a previous server session
m_remoteApplication->kill();
application::State state = m_remoteApplication->waitFor();
cout << "Terminated remote application with state " << application::toString(state) << endl;
}
m_remoteApplication = m_server->start(REMOTE_APPLICATION);
if (!m_remoteApplication->exists()) {
cout << "No remote application" << endl;
return false;
}
// Create the requester
m_requester = application::Requester::create(*m_remoteApplication, RESPONDER);
if (m_requester.get() == 0) {
cout << "requester error" << endl;
return false;
}
// Create the subscriber.
m_subscriber = application::Subscriber::create(*m_remoteApplication, "publisher");
m_subscriberThread.reset(new std::thread([this] {
string result;
while (m_subscriber->receiveBinary(result)) {
// Parse the response.
madman::Result fileResult;
fileResult.ParseFromString(result);
// Write the file to disk.
writeFile(PROCESSED_FILE, fileResult.content());
// Read the file.
readProcessedFile();
// Remove the file.
remove(PROCESSED_FILE.c_str());
cout << "Result size " << fileResult.content().size() << endl;
}
}));
// Application initialized
initialized = true;
return true;
}
void ReductionController::readFile(const std::string& nexusFileName, std::string& fileContent) {
streampos size;
ifstream file(nexusFileName.c_str(), ios::in | ios::binary | ios::ate);
if (file.is_open()) {
size = file.tellg();
// Reserve the string.
fileContent.resize(size);
// Get the allocated array.
char * array = (char *) fileContent.data();
file.seekg(0, ios::beg);
file.read(array, size);
file.close();
} else {
cerr << "File " << nexusFileName << " cannot be read." << endl;
}
}
void ReductionController::writeFile(const std::string& nexusFileName, const std::string& fileContent) {
ofstream file;
file.open(nexusFileName, ios::binary);
file << fileContent;
file.close();
}
void ReductionController::readProcessedFile() {
NXhandle fileId;
// Open the file.
int res = NXopen(PROCESSED_FILE.c_str(), NXACC_RDWR, &fileId);
if (res != NX_OK) {
cerr << "Cannot open processed.nxs." << endl;
return;
}
res = NXopengroup(fileId, "mantid_workspace_1", "NXentry");
if (res != NX_OK) {
cerr << "Cannot open group mantid_workspace_1." << endl;
return;
}
res = NXopengroup(fileId, "workspace", "NXdata");
if (res != NX_OK) {
cerr << "Cannot open group workspace" << endl;
return;
}
// Read X data.
int rank = 1;
int dims[2];
int dataType;
NXopendata(fileId, "axis1");
NXgetinfo(fileId, &rank, dims, &dataType);
if (dataType != NX_FLOAT64) {
cerr << "Problem with the type of data of axis1." << endl;
return;
}
int xSize = dims[0];
delete [] x.get();
double * xData = new double[xSize];
NXgetdata(fileId, xData);
x.set(xData);
// We set the size - 1 to have the same size than the data.
x.setSize(xSize - 1);
// Close the data.
NXclosedata(fileId);
// Read values data.
rank = 2;
NXopendata(fileId, "values");
NXgetinfo(fileId, &rank, dims, &dataType);
if (dataType != NX_FLOAT64) {
cerr << "Problem with the type of data of values." << endl;
return;
}
if (dims[1] + 1 != xSize) {
cerr << "Problem with the size " << dims[1] << " of values." << endl;
return;
}
int dataSize = dims[1];
delete [] data.get();
double * values = new double[dataSize];
NXgetdata(fileId, values);
data.set(values);
data.setSize(dataSize);
NXclosedata(fileId);
NXclosegroup(fileId);
NXclosegroup(fileId);
NXclose(&fileId);
cout << "Data size " << dataSize << endl;
// Check the data.
int index = 0;
while (index < dataSize) {
if (!isfinite(values[index])) {
break;
}
++index;
}
cout << "Forced size to " << index << endl;
x.setSize(index);
data.setSize(index);
/* int fixedSize = 280;
x.setSize(index < fixedSize ? index : fixedSize);
data.setSize(index < fixedSize ? index : fixedSize);*/
x.sendEvent();
data.sendEvent();
cout << "Processing finished." << endl;
}
void ReductionController::startReduction() {
if (!initApplication()) {
return;
}
// Send a simple message with the content of the Nexus data file.
string fileContent;
// Read the file.
readFile(fileDirectory() + "/" + filename(), fileContent);
// Request type.
madman::Request type;
// Set the type.
type.set_type(madman::Request::File);
// Create the file request.
madman::FileRequest request;
request.set_content(fileContent);
// Send the file content to the server.
m_requester->sendTwoBinaryParts(type.SerializeAsString(), request.SerializeAsString());
// Wait for the response from the server.
string response;
m_requester->receive(response);
}
}
/*
* 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.
*/
#ifndef MANTID_REDUCTIONCONTROLLER_H
#define MANTID_REDUCTIONCONTROLLER_H
#include <controllers/common/scanlegacy/GenericScan1D.h>
#include <cameo/cameo.h>
namespace mantid {
class ReductionController : public ExperimentController {
public:
//! Type of controller
static const std::string TYPE;
ReductionController(const std::string& name);
ReductionController(const ReductionController& controller);
virtual ~ReductionController();
virtual void postConfiguration();
void startReduction();
Property<std::string> serverEndpoint;
Property<bool> initialized;
Property<std::string> fileDirectory;
Property<std::string> filename;
ArrayProperty<float64> x;
ArrayProperty<float64> data;
private:
void registerControllers();
void updateScanSerializerEvent(int32 i);
bool initApplication();
void readFile(const std::string& nexusFileName, std::string& fileContent);
void writeFile(const std::string& nexusFileName, const std::string& fileContent);
void readProcessedFile();
static const std::string REMOTE_APPLICATION;
static const std::string RESPONDER;
static const std::string PUBLISHER;
static const std::string PROCESSED_FILE;
std::unique_ptr<cameo::Server> m_server;
std::unique_ptr<cameo::application::Instance> m_remoteApplication;
std::unique_ptr<cameo::application::Requester> m_requester;
std::unique_ptr<cameo::application::Subscriber> m_subscriber;
std::unique_ptr<std::thread> m_subscriberThread;
std::vector<scan::GenericScan1D*> m_scanControllers;
};
}
#endif
package madman;
option optimize_for = LITE_RUNTIME;
message Request {
enum Type {
Reset = 1;
File = 2;
}
required Type type = 1;
}
message FileRequest {
required bytes content = 1;
}
message EmptyRequest {
}
message Result {
required bytes content = 1;
}
<plotdatas>
<plotdata key="data" color="1F96C0" plugins="SETUP">
<dataX p_role="mantid_reduction1" p_name="x"/>
<dataY p_role="mantid_reduction1" p_name="data"/>
</plotdata>
</plotdatas>
<controller_plugin_config type="mantid_reduction">
<image key="ACQUISITION"/>
<settings view="mantid_reductionView.xml"/>
<command view="mantid_reductionCommandView.xml"/>
</controller_plugin_config>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<controller type="mantid_reduction">
<property name="x" type="doublearray">
</property>
<property name="data" type="doublearray">
</property>
</controller>
<plugin>
<controller type="mantid_reduction" role="mantid_reduction1"/>
<text role="mantid_reduction1" property="filename" prefix="Filename"/>
<newLine/>
<plot_launcher role="mantid_reduction1" data="data" title="data" height="20"/>
</plugin>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment