DynExp
Highly flexible laboratory automation for dynamically changing experiments.
WidefieldLocalization.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
5 
6 namespace DynExpInstr
7 {
8  std::strong_ordering operator<=>(const WidefieldLocalizationCellIDType& lhs, const WidefieldLocalizationCellIDType& rhs)
9  {
10  if (lhs.X_id == rhs.X_id && lhs.Y_id == rhs.Y_id)
11  return std::strong_ordering::equal;
12  else if (lhs.Y_id > rhs.Y_id || (lhs.Y_id == rhs.Y_id && lhs.X_id > rhs.X_id))
13  return std::strong_ordering::greater;
14  else
15  return std::strong_ordering::less;
16  }
17 
18  std::ostream& operator<<(std::ostream& stream, const WidefieldLocalizationCellIDType& CellID)
19  {
20  stream << "CellIDString = " << CellID.IDString << "\n";
21  stream << "CellIDX = " << CellID.X_id << "\n";
22  stream << "CellIDY = " << CellID.Y_id << "\n";
23  stream << "CellIDValid = " << (CellID.Valid ? "yes" : "no") << "\n";
24 
25  return stream;
26  }
27 
29  {
30  InitFuncImpl(dispatch_tag<InitTask>(), Instance);
31  }
32 
34  {
35  ExitFuncImpl(dispatch_tag<ExitTask>(), Instance);
36  }
37 
39  {
40  UpdateFuncImpl(dispatch_tag<UpdateTask>(), Instance);
41  }
42 
44  : ImageWidth(Util::NumToT<google::protobuf::uint32>(Image.width())), ImageHeight(Util::NumToT<google::protobuf::uint32>(Image.height())),
45  ImageFormat(Image.format())
46  {
47  ImageData.resize(Image.sizeInBytes());
48 
49  // No deep copy in QImage::bits(), since Image is const (see https://doc.qt.io/qt-5/qimage.html#bits-1).
50  std::memcpy(ImageData.data(), Image.bits(), ImageData.size());
51  }
52 
53  DynExpProto::WidefieldLocalization::ImageMessage WidefieldLocalizationTasks::ImageProcessingTaskBase::MakeImageMessage()
54  {
55  DynExpProto::WidefieldLocalization::ImageMessage ImageMsg;
56 
57  ImageMsg.set_width(ImageWidth);
58  ImageMsg.set_height(ImageHeight);
59 
60  switch (ImageFormat)
61  {
62  case QImage::Format::Format_Grayscale8: ImageMsg.set_imageformat(DynExpProto::WidefieldLocalization::ImageFormatType::Mono8); break;
63  case QImage::Format::Format_Grayscale16: ImageMsg.set_imageformat(DynExpProto::WidefieldLocalization::ImageFormatType::Mono16); break;
64  default: throw Util::NotImplementedException("The format of the given image is not supported.");
65  }
66 
67  ImageMsg.set_image(std::move(ImageData));
68 
69  return ImageMsg;
70  }
71 
73  : TaskBase(CallbackFunc), ImageProcessingTaskBase(Image)
74  {
75  }
76 
78  {
79  grpc::ClientContext Context;
80  DynExpProto::WidefieldLocalization::ImageMessage ImageMsg = MakeImageMessage();
81  DynExpProto::WidefieldLocalization::CellIDMessage CellIDMsg;
82 
84  {
85  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
86  StubPtr = InstrData->GetStub<0>();
87  } // InstrData unlocked here.
88 
89  auto Result = StubPtr->ReadCellID(&Context, ImageMsg, &CellIDMsg);
90  if (!Result.ok())
91  throw DynExpHardware::gRPCException(Result);
92  if (CellIDMsg.resultmsg().result() != DynExpProto::WidefieldLocalization::ResultType::OK &&
93  CellIDMsg.resultmsg().result() != DynExpProto::WidefieldLocalization::ResultType::LocalizationFailed)
94  throw Util::ServiceFailedException("Reading the cell id failed on the remote service site.");
95 
96  {
97  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
98 
99  if (CellIDMsg.resultmsg().result() == DynExpProto::WidefieldLocalization::ResultType::OK)
100  {
101  // Reading the cell id worked.
102  InstrData->CellID.IDString = CellIDMsg.idstring();
103  InstrData->CellID.X_id = CellIDMsg.id().x();
104  InstrData->CellID.Y_id = CellIDMsg.id().y();
105  InstrData->CellID.Valid = true;
106  InstrData->CellID.CellShift_px_x = CellIDMsg.has_cellshift_px() ? CellIDMsg.cellshift_px().x() : 0;
107  InstrData->CellID.CellShift_px_y = CellIDMsg.has_cellshift_px() ? CellIDMsg.cellshift_px().y() : 0;
108  }
109  else
110  {
111  // Extracting the cell id did not work since it was not readable from the image.
112  // However, the extraction routines themselves worked. Do not throw in case of that 'soft' error.
113  InstrData->CellID = {};
114  }
115  } // InstrData unlocked here.
116 
117  return {};
118  }
119 
121  : TaskBase(CallbackFunc), ImageProcessingTaskBase(Image)
122  {
123  }
124 
126  {
127  grpc::ClientContext Context;
128  DynExpProto::WidefieldLocalization::ImageMessage ImageMsg = MakeImageMessage();
129  DynExpProto::WidefieldLocalization::PositionsMessage PositionsMsg;
130 
132  {
133  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
134  StubPtr = InstrData->GetStub<0>();
135  } // InstrData unlocked here.
136 
137  auto Result = StubPtr->AnalyzeWidefield(&Context, ImageMsg, &PositionsMsg);
138  if (!Result.ok())
139  throw DynExpHardware::gRPCException(Result);
140 
141  {
142  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
143  InstrData->SetLocalizedPositions(PositionsMsg);
144  } // InstrData unlocked here.
145 
146  return {};
147  }
148 
150  : TaskBase(CallbackFunc), ImageProcessingTaskBase(Image)
151  {
152  }
153 
155  {
156  grpc::ClientContext Context;
157  DynExpProto::WidefieldLocalization::ImageMessage ImageMsg = MakeImageMessage();
158  DynExpProto::WidefieldLocalization::VoidMessage VoidMsg;
159 
161  {
162  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
163  StubPtr = InstrData->GetStub<0>();
164  } // InstrData unlocked here.
165 
166  auto Result = StubPtr->AnalyzeTipTilt(&Context, ImageMsg, &VoidMsg);
167  if (!Result.ok())
168  throw DynExpHardware::gRPCException(Result);
169 
170  return {};
171  }
172 
174  std::string_view MeasureSavePath, CallbackType CallbackFunc) noexcept
175  : TaskBase(CallbackFunc), ImageProcessingTaskBase(Image), CellID(CellID), MeasureSavePath(MeasureSavePath)
176  {
177  }
178 
180  {
181  grpc::ClientContext Context;
182  DynExpProto::WidefieldLocalization::RecallPositionsMessage RecallPositionsMsg;
183  DynExpProto::WidefieldLocalization::PositionsMessage PositionsMsg;
184 
185  auto ImageMsg = std::make_unique<DynExpProto::WidefieldLocalization::ImageMessage>(MakeImageMessage());
186  RecallPositionsMsg.set_allocated_image(ImageMsg.release());
187 
188  auto CellIDResultsMsg = std::make_unique<DynExpProto::WidefieldLocalization::ResultMessage>();
189  CellIDResultsMsg->set_result(CellID.Valid ? DynExpProto::WidefieldLocalization::ResultType::OK : DynExpProto::WidefieldLocalization::ResultType::GeneralError);
190  auto IDPointMsg = std::make_unique<DynExpProto::WidefieldLocalization::PointMessage>();
191  IDPointMsg->set_x(CellID.X_id);
192  IDPointMsg->set_y(CellID.Y_id);
193  auto CellIDMsg = std::make_unique<DynExpProto::WidefieldLocalization::CellIDMessage>();
194  CellIDMsg->set_allocated_resultmsg(CellIDResultsMsg.release());
195  CellIDMsg->set_idstring(CellID.IDString);
196  CellIDMsg->set_allocated_id(IDPointMsg.release());
197  RecallPositionsMsg.set_allocated_cellid(CellIDMsg.release());
198 
199  RecallPositionsMsg.set_measuresavepath(MeasureSavePath);
200 
202  {
203  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
204  StubPtr = InstrData->GetStub<0>();
205  } // InstrData unlocked here.
206 
207  auto Result = StubPtr->RecallPositions(&Context, RecallPositionsMsg, &PositionsMsg);
208  if (!Result.ok())
209  throw DynExpHardware::gRPCException(Result);
210 
211  {
212  auto InstrData = DynExp::dynamic_InstrumentData_cast<WidefieldLocalization>(Instance.InstrumentDataGetter());
213  InstrData->SetLocalizedPositions(PositionsMsg);
214  } // InstrData unlocked here.
215 
216  return {};
217  }
218 
219  void WidefieldLocalizationData::ResetImpl(dispatch_tag<gRPCInstrumentData>)
220  {
221  CellID = {};
222  LocalizedPositions.clear();
223 
224  ResetImpl(dispatch_tag<WidefieldLocalizationData>());
225  }
226 
227  void WidefieldLocalizationData::SetLocalizedPositions(const DynExpProto::WidefieldLocalization::PositionsMessage& PositionsMsg)
228  {
229  if (PositionsMsg.resultmsg().result() != DynExpProto::WidefieldLocalization::ResultType::OK)
230  throw Util::ServiceFailedException("Widefield localization failed on the remote service site.");
231 
232  const auto NumPositions = PositionsMsg.entries_size();
233  LocalizedPositions.clear();
234  for (std::remove_const_t<decltype(NumPositions)> i = 0; i < NumPositions; ++i)
235  {
236  QPoint Position{ Util::NumToT<int>(PositionsMsg.entries(i).pos_px().x()), Util::NumToT<int>(PositionsMsg.entries(i).pos_px().y()) };
237  LocalizedPositions.emplace(PositionsMsg.entries(i).id(), Position);
238  }
239  }
240 
241  WidefieldLocalization::WidefieldLocalization(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
242  : gRPCInstrument(OwnerThreadID, std::move(Params))
243  {
244  }
245 
247  {
249  }
250 }
Implementation of a gRPC client instrument to access a remote service for image processing (localizat...
Defines an exception caused by an operation involving the gRPC library and communication over a TCP s...
void SetLocalizedPositions(const DynExpProto::WidefieldLocalization::PositionsMessage &PositionsMsg)
void ResetImpl(dispatch_tag< gRPCInstrumentData >) override final
AnalyzeDistortionTask(const QImage &Image, CallbackType CallbackFunc) noexcept
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
AnalyzeWidefieldTask(const QImage &Image, CallbackType CallbackFunc) noexcept
void ExitFuncImpl(dispatch_tag< gRPCInstrumentTasks::ExitTask< DynExp::InstrumentBase, 0, DynExpProto::WidefieldLocalization::WidefieldLocalization >>, DynExp::InstrumentInstance &Instance) override final
DynExpProto::WidefieldLocalization::ImageMessage MakeImageMessage()
void InitFuncImpl(dispatch_tag< gRPCInstrumentTasks::InitTask< DynExp::InstrumentBase, 0, DynExpProto::WidefieldLocalization::WidefieldLocalization >>, DynExp::InstrumentInstance &Instance) override final
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
ReadCellIDTask(const QImage &Image, CallbackType CallbackFunc) noexcept
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
RecallPositionsTask(const QImage &Image, const WidefieldLocalizationCellIDType &CellID, std::string_view MeasureSavePath, CallbackType CallbackFunc) noexcept
void UpdateFuncImpl(dispatch_tag< gRPCInstrumentTasks::UpdateTask< DynExp::InstrumentBase, 0, DynExpProto::WidefieldLocalization::WidefieldLocalization >>, DynExp::InstrumentInstance &Instance) override final
void ResetImpl(dispatch_tag< gRPCInstrument >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
WidefieldLocalization(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Meta instrument template for transforming meta instruments into network instruments,...
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
Definition: Instrument.h:772
const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter
Getter for instrument's data. Refer to InstrumentBase::InstrumentDataGetterType.
Definition: Instrument.h:791
Refer to ParamsBase::dispatch_tag.
Definition: Object.h:2018
std::function< void(const TaskBase &, ExceptionContainer &)> CallbackType
Type of a callback function which is invoked when a task has finished, failed or has been aborted....
Definition: Instrument.h:939
Defines the return type of task functions.
Definition: Instrument.h:824
Thrown when a requested feature is either under development and thus not implemented yet or when a sp...
Definition: Exception.h:299
Denotes that e.g. a remote gRPC service failed.
Definition: Exception.h:357
DynExp's instrument namespace contains the implementation of DynExp instruments which extend DynExp's...
Definition: Instrument.h:1254
std::strong_ordering operator<=>(const WidefieldLocalizationCellIDType &lhs, const WidefieldLocalizationCellIDType &rhs)
std::shared_ptr< typename gRPCStub::Stub > StubPtrType
Alias for a pointer to a gRPC stub.
std::ostream & operator<<(std::ostream &stream, const WidefieldLocalizationCellIDType &CellID)
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition: Object.h:1807
Accumulates include statements to provide a precompiled header.