InstrumentWidgetDecoder.cpp 15.4 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
#include "MantidQtWidgets/InstrumentView/InstrumentWidgetDecoder.h"
Samuel Jones's avatar
Samuel Jones committed
8
9
10
11

#include "MantidQtWidgets/InstrumentView/ColorBar.h"
#include "MantidQtWidgets/InstrumentView/InstrumentActor.h"
#include "MantidQtWidgets/InstrumentView/InstrumentTreeWidget.h"
12
#include "MantidQtWidgets/InstrumentView/InstrumentWidget.h"
Samuel Jones's avatar
Samuel Jones committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "MantidQtWidgets/InstrumentView/InstrumentWidgetMaskTab.h"
#include "MantidQtWidgets/InstrumentView/InstrumentWidgetPickTab.h"
#include "MantidQtWidgets/InstrumentView/InstrumentWidgetRenderTab.h"
#include "MantidQtWidgets/InstrumentView/InstrumentWidgetTreeTab.h"
#include "MantidQtWidgets/InstrumentView/MaskBinsData.h"
#include "MantidQtWidgets/InstrumentView/ProjectionSurface.h"
#include "MantidQtWidgets/InstrumentView/Shape2D.h"
#include "MantidQtWidgets/InstrumentView/Shape2DCollection.h"

#include <QAction>
#include <QCheckBox>
#include <QComboBox>
#include <QList>
#include <QMap>
#include <QObject>
#include <QPushButton>
#include <QRadioButton>
#include <QString>

namespace MantidQt {
namespace MantidWidgets {
34
35

InstrumentWidgetDecoder::InstrumentWidgetDecoder()
36
    : m_projectPath(""), m_workspaceName(""), m_loadMask(true) {}
37

Samuel Jones's avatar
Samuel Jones committed
38
39
void InstrumentWidgetDecoder::decode(const QMap<QString, QVariant> &map,
                                     InstrumentWidget &obj,
40
41
                                     const QString &projectPath,
                                     const bool loadMask) {
42
  m_projectPath = projectPath;
43
  m_loadMask = loadMask;
44
45
46

  m_workspaceName = map[QString("workspaceName")].toString();

47
  const auto surfaceType = map[QString("surfaceType")].toInt();
48
49
50
51
52
53
  obj.setSurfaceType(surfaceType);

  const auto currentTab = map[QString("currentTab")].toInt();
  obj.selectTab(currentTab);

  const auto energyTransferList = map[QString("energyTransfer")].toList();
Samuel Jones's avatar
Samuel Jones committed
54
55
  const auto min = energyTransferList[0].toDouble();
  const auto max = energyTransferList[1].toDouble();
56
57
  if (energyTransferList.size() == 3) {
    const bool isIntegrable = energyTransferList[2].toBool();
58
59
60
61
62
63
    if (isIntegrable) {
      obj.setBinRange(min, max);
    }
  } else {
    obj.setBinRange(min, max);
  }
64

Samuel Jones's avatar
Samuel Jones committed
65
66
67
  this->decodeSurface(map[QString("surface")].toMap(), obj.getSurface());
  this->decodeActor(map[QString("actor")].toMap(), obj.m_instrumentActor);
  this->decodeTabs(map[QString("tabs")].toMap(), obj);
68
69
70
71
}

void InstrumentWidgetDecoder::decodeTabs(const QMap<QString, QVariant> &map,
                                         InstrumentWidget &obj) {
Samuel Jones's avatar
Samuel Jones committed
72
73
74
75
  this->decodeMaskTab(map[QString("maskTab")].toMap(), obj.m_maskTab);
  this->decodeRenderTab(map[QString("renderTab")].toMap(), obj.m_renderTab);
  this->decodeTreeTab(map[QString("treeTab")].toMap(), obj.m_treeTab);
  this->decodePickTab(map[QString("pickTab")].toMap(), obj.m_pickTab);
76
77
78
}

void InstrumentWidgetDecoder::decodeMaskTab(const QMap<QString, QVariant> &map,
Samuel Jones's avatar
Samuel Jones committed
79
80
81
82
83
84
85
86
87
88
89
90
                                            InstrumentWidgetMaskTab *obj) {
  const auto activeTools = map[QString("activeTools")].toMap();
  const auto activeType = map[QString("activeType")].toMap();

  // Decode the active tools
  obj->m_move->setChecked(activeTools["moveButton"].toBool());
  obj->m_pointer->setChecked(activeTools["pointerButton"].toBool());
  obj->m_ellipse->setChecked(activeTools["ellipseButton"].toBool());
  obj->m_ring_ellipse->setChecked(activeTools["ringEllipseButton"].toBool());
  obj->m_ring_rectangle->setChecked(
      activeTools["ringRectangleButton"].toBool());
  obj->m_free_draw->setChecked(activeTools["freeFrawButton"].toBool());
91
92
  obj->m_pixel->setChecked(activeTools["pixelButton"].toBool());
  obj->m_tube->setChecked(activeTools["tubeButton"].toBool());
Samuel Jones's avatar
Samuel Jones committed
93
94
95
96
97
98
99
100
101

  // Decode the active type
  obj->m_masking_on->setChecked(activeType["maskingOn"].toBool());
  obj->m_grouping_on->setChecked(activeType["groupingOn"].toBool());
  obj->m_roi_on->setChecked(activeType["roiOn"].toBool());

  // Load the masks applied to view but not saved to a workspace (But also
  // including those saved to the workspace)
  const auto success = map["maskWorkspaceSaved"].toBool();
102
  if (success && m_loadMask) {
Samuel Jones's avatar
Samuel Jones committed
103
104
105
106
    const auto wsName = map["maskWorkspaceName"].toString().toStdString();
    obj->loadMaskViewFromProject(wsName);
  }
}
107
108

void InstrumentWidgetDecoder::decodeRenderTab(
Samuel Jones's avatar
Samuel Jones committed
109
110
111
112
113
114
115
116
117
118
119
120
    const QMap<QString, QVariant> &map, InstrumentWidgetRenderTab *obj) {
  // Load buttons/settings
  obj->mAxisCombo->setCurrentIndex(map[QString("axesView")].toInt());
  obj->m_autoscaling->setChecked(map[QString("autoScaling")].toBool());
  obj->m_displayAxes->setChecked(map[QString("displayAxis")].toBool());
  obj->m_flipCheckBox->setChecked(map[QString("flipView")].toBool());
  obj->m_displayDetectorsOnly->setChecked(
      map[QString("displayDetectorsOnly")].toBool());
  obj->m_wireframe->setChecked(map[QString("displayWireframe")].toBool());
  obj->m_lighting->setChecked(map[QString("displayLighting")].toBool());
  obj->m_GLView->setChecked(map[QString("useOpenGL")].toBool());
  obj->m_UCorrection->setChecked(map[QString("useUCorrection")].toBool());
121
  obj->m_freezeRotation->setChecked(map[QString("freezeRotation")].toBool());
Samuel Jones's avatar
Samuel Jones committed
122
123
124
125
126

  // Load the surface
  auto surface = obj->getSurface();
  surface->setShowPeakLabelsFlag(map[QString("showLabels")].toBool());
  surface->setShowPeakRowsFlag(map[QString("showRows")].toBool());
Samuel Jones's avatar
Samuel Jones committed
127
  surface->setPeakLabelPrecision(map[QString("labelPrecision")].toInt());
Samuel Jones's avatar
Samuel Jones committed
128
129
130
131
  surface->setShowPeakRelativeIntensityFlag(
      map[QString("showRelativeIntensity")].toBool());

  // Load color bar
132
  this->decodeColorBar(map[QString("colorBar")].toMap(), obj->m_colorBarWidget);
Samuel Jones's avatar
Samuel Jones committed
133
}
134

Samuel Jones's avatar
Samuel Jones committed
135
136
void InstrumentWidgetDecoder::decodeColorBar(const QMap<QString, QVariant> &map,
                                             ColorBar *bar) {
137
138
139
140
141
142
143
144
  const auto scaleType = map[QString("scaleType")].toInt();
  const auto power = map[QString("power")].toString().toDouble();
  const auto min = map[QString("min")].toString().toDouble();
  const auto max = map[QString("max")].toString().toDouble();

  bar->setScaleType(scaleType);
  try {
    bar->setNthPower(power);
Samuel Jones's avatar
Samuel Jones committed
145
  } catch (const std::runtime_error &) {
146
147
148
149
150
    // Do nothing, because this is where the power was loaded in as 0.
  }

  bar->setMinValue(min);
  bar->setMaxValue(max);
151
152
153
154
155
}

void InstrumentWidgetDecoder::decodeTreeTab(const QMap<QString, QVariant> &map,
                                            InstrumentWidgetTreeTab *obj) {
  auto names = map[QString("expandedItems")].toList();
156
  if (names.size() > 0) {
157
    for (const auto &name : names) {
158
159
160
161
      auto index = obj->m_instrumentTree->findComponentByName(name.toString());
      obj->m_instrumentTree->setExpanded(index, true);
    }
    obj->selectComponentByName(map[QString("selectedComponent")].toString());
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  }
}

void InstrumentWidgetDecoder::decodePickTab(const QMap<QString, QVariant> &map,
                                            InstrumentWidgetPickTab *obj) {
  obj->m_zoom->setChecked(map[QString("zoom")].toBool());
  obj->m_edit->setChecked(map[QString("edit")].toBool());
  obj->m_ellipse->setChecked(map[QString("ellipse")].toBool());
  obj->m_rectangle->setChecked(map[QString("rectangle")].toBool());
  obj->m_ring_ellipse->setChecked(map[QString("ringEllipse")].toBool());
  obj->m_ring_rectangle->setChecked(map[QString("ringRectangle")].toBool());
  obj->m_free_draw->setChecked(map[QString("freeDraw")].toBool());
  obj->m_one->setChecked(map[QString("one")].toBool());
  obj->m_tube->setChecked(map[QString("tube")].toBool());
176
  obj->m_peakAdd->setChecked(map[QString("peakAdd")].toBool());
177
  obj->m_peakErase->setChecked(map[QString("peakErase")].toBool());
178
179
180
}

void InstrumentWidgetDecoder::decodeActor(
Samuel Jones's avatar
Samuel Jones committed
181
182
    const QMap<QString, QVariant> &map, std::unique_ptr<InstrumentActor> &obj) {
  obj->loadColorMap(map[QString("fileName")].toString());
183

Samuel Jones's avatar
Samuel Jones committed
184
  this->decodeBinMasks(map[QString("binMasks")].toList(), obj->m_maskBinsData);
185
186
187
188
189
}

void InstrumentWidgetDecoder::decodeBinMasks(const QList<QVariant> &list,
                                             MaskBinsData &obj) {
  for (const auto &item : list) {
Samuel Jones's avatar
Samuel Jones committed
190
191
192
193
    const auto itemMap = item.toMap();
    const auto range = itemMap[QString("range")].toList();
    double start = range[0].toDouble();
    double end = range[1].toDouble();
194

Samuel Jones's avatar
Samuel Jones committed
195
    const auto spectraList = itemMap["spectra"].toList();
196
    std::vector<size_t> spectra;
197
    spectra.reserve(static_cast<size_t>(spectraList.size()));
198
    for (const auto &spec : spectraList) {
Samuel Jones's avatar
Samuel Jones committed
199
      spectra.emplace_back(spec.value<size_t>());
200
201
202
203
204
    }
    obj.addXRange(start, end, spectra);
  }
}

Samuel Jones's avatar
Samuel Jones committed
205
206
void InstrumentWidgetDecoder::decodeSurface(
    const QMap<QString, QVariant> &map,
207
    std::shared_ptr<ProjectionSurface> obj) {
208

209
  auto projection3D = std::dynamic_pointer_cast<Projection3D>(obj);
210
211
  // Decide Projection3D stuff
  if (map[QString("projection3DSuccess")].toBool() && projection3D) {
Samuel Jones's avatar
Samuel Jones committed
212
213
    this->decodeProjection3D(map[QString("projection3D")].toMap(),
                             *projection3D);
214
215
  }

Samuel Jones's avatar
Samuel Jones committed
216
  QMap<QString, QVariant> color = map[QString("backgroundColor")].toMap();
217
  QColor qColor(color[QString("red")].toInt(), color[QString("green")].toInt(),
Samuel Jones's avatar
Samuel Jones committed
218
219
                color[QString("blue")].toInt(),
                color[QString("alpha")].toInt());
220
221
222

  obj->m_backgroundColor = qColor;

Samuel Jones's avatar
Samuel Jones committed
223
224
  this->decodeMaskShapes(map[QString("shapes")].toList(), obj->m_maskShapes);
  this->decodeAlignmentInfo(map[QString("alignmentInfo")].toList(), obj);
225
226
}

227
228
void InstrumentWidgetDecoder::decodeProjection3D(
    const QMap<QString, QVariant> &map, Projection3D &obj) {
Samuel Jones's avatar
Samuel Jones committed
229
230
  this->decodeViewPort(map[QString("viewport")].toMap(), obj.m_viewport);
}
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

void InstrumentWidgetDecoder::decodeViewPort(const QMap<QString, QVariant> &map,
                                             Viewport &obj) {
  auto translationMap = map[QString("translation")].toMap();
  auto rotationList = map[QString("rotation")].toList();

  obj.m_xTrans = translationMap[QString("xTrans")].toDouble();
  obj.m_yTrans = translationMap[QString("yTrans")].toDouble();
  obj.m_zoomFactor = map[QString("zoom")].toDouble();

  // Sort out the rotation
  double w, a, b, c;
  w = rotationList[0].toDouble();
  a = rotationList[1].toDouble();
  b = rotationList[2].toDouble();
  c = rotationList[3].toDouble();
  Mantid::Kernel::Quat quat(w, a, b, c);
  obj.setRotation(quat);
}

251
void InstrumentWidgetDecoder::decodeMaskShapes(const QList<QVariant> &list,
Samuel Jones's avatar
Samuel Jones committed
252
                                               Shape2DCollection &obj) {
253
  connect(this, SIGNAL(shapeCreated()), &obj, SIGNAL(shapeCreated()));
254
  for (const auto &shape : list) {
255
    auto created_shape = this->decodeShape(shape.toMap());
Samuel Jones's avatar
Samuel Jones committed
256
    obj.m_shapes.push_back(created_shape);
257
258
259
260
    emit shapeCreated();
  }
}

Samuel Jones's avatar
Samuel Jones committed
261
Shape2D *
262
263
264
InstrumentWidgetDecoder::decodeShape(const QMap<QString, QVariant> &map) {
  const auto type = map[QString("type")].toString().toStdString();

265
266
267
268
269
270
271
  auto shape = [&]() {
    if (type == "ellipse") {
      return this->decodeEllipse(map[QString("subShapeMap")].toMap());
    } else if (type == "rectangle") {
      return this->decodeRectangle(map[QString("subShapeMap")].toMap());
    } else if (type == "ring") {
      return this->decodeRing(map[QString("subShapeMap")].toMap());
272
273
    } else if (type == "sector") {
      return this->decodeSector(map[QString("subShapeMap")].toMap());
274
275
276
277
278
279
    } else if (type == "free") {
      return this->decodeFree(map[QString("subShapeMap")].toMap());
    } else {
      throw std::runtime_error("InstrumentView - Could not decode shape");
    }
  }();
280

281
282
283
284
285
286
  // Set the properties of the overall shape object from the properties map.
  auto properties = map[QString("properties")].toMap();
  shape->setScalable(properties[QString("visible")].toBool());
  shape->setVisible(properties[QString("scalable")].toBool());
  shape->edit(properties[QString("editing")].toBool());
  shape->setSelected(properties[QString("selected")].toBool());
287

Samuel Jones's avatar
Samuel Jones committed
288
289
290
291
  QMap<QString, QVariant> color1 = map[QString("color")].toMap();
  QColor qColor(
      color1[QString("red")].toInt(), color1[QString("green")].toInt(),
      color1[QString("blue")].toInt(), color1[QString("alpha")].toInt());
292
293
294

  shape->setColor(qColor);

Samuel Jones's avatar
Samuel Jones committed
295
  QMap<QString, QVariant> color2 = map[QString("fillColor")].toMap();
296
  QColor qFillColor(
Samuel Jones's avatar
Samuel Jones committed
297
298
      color2[QString("red")].toInt(), color2[QString("green")].toInt(),
      color2[QString("blue")].toInt(), color2[QString("alpha")].toInt());
299
300
301
302
303
  shape->setFillColor(qFillColor);

  return shape;
}

Samuel Jones's avatar
Samuel Jones committed
304
Shape2D *
305
306
307
308
309
InstrumentWidgetDecoder::decodeEllipse(const QMap<QString, QVariant> &map) {
  const auto radius1 = map[QString("radius1")].toDouble();
  const auto radius2 = map[QString("radius2")].toDouble();
  const auto x = map[QString("x")].toDouble();
  const auto y = map[QString("y")].toDouble();
310
  const auto rot = map[QString("rotation")].toDouble();
311

312
313
314
  auto shape = new Shape2DEllipse(QPointF(x, y), radius1, radius2);
  shape->setBoundingRotation(rot);
  return shape;
315
316
}

Samuel Jones's avatar
Samuel Jones committed
317
Shape2D *
318
319
320
321
322
InstrumentWidgetDecoder::decodeRectangle(const QMap<QString, QVariant> &map) {
  const auto x0 = map[QString("x0")].toDouble();
  const auto y0 = map[QString("y0")].toDouble();
  const auto x1 = map[QString("x1")].toDouble();
  const auto y1 = map[QString("y1")].toDouble();
323
  const auto rot = map[QString("rotation")].toDouble();
324
325
326

  const QPointF point1(x0, y0);
  const QPointF point2(x1, y1);
327
328
329
  auto shape = new Shape2DRectangle(point1, point2);
  shape->setBoundingRotation(rot);
  return shape;
330
331
}

Samuel Jones's avatar
Samuel Jones committed
332
Shape2D *
333
334
335
336
InstrumentWidgetDecoder::decodeRing(const QMap<QString, QVariant> &map) {
  const auto xWidth = map[QString("xWidth")].toDouble();
  const auto yWidth = map[QString("yWidth")].toDouble();

Samuel Jones's avatar
Samuel Jones committed
337
  const auto baseShape = this->decodeShape(map[QString("shape")].toMap());
338
339
  return new Shape2DRing(baseShape, xWidth, yWidth);
}
340
341
342
343
344
345
Shape2D *
InstrumentWidgetDecoder::decodeSector(const QMap<QString, QVariant> &map) {
  const double outerRadius = map[QString("outerRadius")].toDouble();
  const double innerRadius = map[QString("innerRadius")].toDouble();
  const double startAngle = map[QString("startAngle")].toDouble();
  const double endAngle = map[QString("endAngle")].toDouble();
Mathieu Tillet's avatar
Mathieu Tillet committed
346
347
  const double centerX = map[QString("centerX")].toDouble();
  const double centerY = map[QString("centerY")].toDouble();
348
349

  return new Shape2DSector(innerRadius, outerRadius, startAngle, endAngle,
Mathieu Tillet's avatar
Mathieu Tillet committed
350
                           QPointF(centerX, centerY));
351
}
352

Samuel Jones's avatar
Samuel Jones committed
353
Shape2D *
354
355
356
InstrumentWidgetDecoder::decodeFree(const QMap<QString, QVariant> &map) {
  QPolygonF polygon;

357
  const auto parameters = map[QString("paramaters")].toList();
Gagik Vardanyan's avatar
Gagik Vardanyan committed
358
  for (const auto &param : parameters) {
Samuel Jones's avatar
Samuel Jones committed
359
360
361
    const auto paramList = param.toList();
    const double x = paramList[0].toDouble();
    const double y = paramList[1].toDouble();
362
363
364
365
366
367
368

    polygon << QPointF(x, y);
  }

  return new Shape2DFree(polygon);
}

Samuel Jones's avatar
Samuel Jones committed
369
void InstrumentWidgetDecoder::decodeAlignmentInfo(
370
    const QList<QVariant> &list, std::shared_ptr<ProjectionSurface> &obj) {
371
372
373

  std::vector<std::pair<Mantid::Kernel::V3D, QPointF>> alignmentPlane;
  for (const auto &item : list) {
Samuel Jones's avatar
Samuel Jones committed
374
375
376
    const auto itemList = item.toList();
    const auto qLabMap = itemList[0].toMap();
    const auto marker = itemList[1].toPointF();
377
378
379
380
    Mantid::Kernel::V3D qValue(qLabMap[QString("x")].toDouble(),
                               qLabMap[QString("y")].toDouble(),
                               qLabMap[QString("z")].toDouble());

381
    alignmentPlane.emplace_back(qValue, marker);
382
383
  }
  obj->m_selectedAlignmentPlane = alignmentPlane;
Samuel Jones's avatar
Samuel Jones committed
384
385
}
} // namespace MantidWidgets
386
} // namespace MantidQt