libvisiontransfer  10.0.0
parameter.cpp
1 /*******************************************************************************
2  * Copyright (c) 2022 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #include <string>
16 #include <vector>
17 #include <cstring>
18 #include <sstream>
19 #include <set>
20 
21 #include <iostream>
22 
23 #include <visiontransfer/parameter.h>
24 
25 namespace visiontransfer {
26 namespace param {
27 
28 using namespace internal;
29 
30 Parameter::Parameter(const std::string& uid)
31 : uid(uid), name(uid), governorType(GOVERNOR_NONE), invokeGovernorOnInit(false), accessForConfig(ACCESS_NONE), accessForApi(ACCESS_NONE), interactionHint(INTERACTION_ACTIVE), isModified(false) {
32 }
33 
35  std::string result = governorString;
36  std::set<char> subst{'P', 'O', 'N', 'E', 'D'};
37  std::ostringstream ss;
38  char what;
39  size_t where = -1;
40  while (true) {
41  int foundAt = -1;
42  int foundRightmost = -1;
43  what = 0;
44  for (auto ch: subst) {
45  std::string lookfor = "%";
46  lookfor += ch;
47  foundAt = result.rfind(lookfor, where);
48  if (foundAt > foundRightmost) {
49  foundRightmost = foundAt;
50  what = ch;
51  }
52  }
53  if (foundRightmost >= 0) {
54  ss.str("");
55  switch(what) {
56  case 'P':
57  ss << "\"" << getUid() << "\"";
58  break;
59  case 'O':
60  if (isScalar()) {
61  ss << "\"" << getCurrent<std::string>() << "\"";
62  } else {
63  bool first = true;
64  for (auto e: getTensorData()) {
65  if (first) first = false;
66  else ss << " ";
67  ss << e;
68  }
69  }
70  break;
71  case 'E':
72  ss << getTensorDimension();
73  if (isTensor()) {
74  auto sh = getTensorShape();
75  for (auto d: sh) {
76  ss << " " << d;
77  }
78  }
79  break;
80  case 'D':
81  ss << newVal.getTensorDimension();
82  if (isTensor()) {
83  auto sh = newVal.getTensorShape();
84  for (auto d: sh) {
85  ss << " " << d;
86  }
87  }
88  break;
89  case 'N':
90  default:
91  if (newVal.isScalar()) {
92  ss << "\"" << newVal.getValue<std::string>() << "\"";
93  } else {
94  bool first = true;
95  for (auto e: newVal.getTensorData()) {
96  if (first) first = false;
97  else ss << " ";
98  ss << e;
99  }
100  }
101  break;
102  }
103  result.replace(foundRightmost, 2, ss.str());
104  }
105  if (where == 0) break; // cannot go further left
106  where = (foundRightmost > 0) ? foundRightmost-1 : 0;
107  }
108  return result;
109 }
110 
112  if (isTensor()) {
114  } else {
115  if (isValidNewValue(from.getCurrent<std::string>())) {
116  currentValue.setType(this->type);
117  // always cache string
118  switch (this->type) {
119  case ParameterValue::ParameterType::TYPE_INT:
120  currentValue.setValue(from.getCurrent<int>()); break;
121  case ParameterValue::ParameterType::TYPE_DOUBLE:
122  currentValue.setValue(from.getCurrent<double>()); break;
123  case ParameterValue::ParameterType::TYPE_STRING:
124  case ParameterValue::ParameterType::TYPE_SAFESTRING:
125  case ParameterValue::ParameterType::TYPE_COMMAND:
126  currentValue.setValue(from.getCurrent<std::string>()); break;
127  break;
128  case ParameterValue::ParameterType::TYPE_BOOL:
129  currentValue.setValue(from.getCurrent<bool>()); break;
130  break;
131  case ParameterValue::ParameterType::TYPE_TENSOR:
132  if(currentValue.getTensorShape() != from.getTensorShape()) {
133  throw std::runtime_error("Cannot assign tensors with unequal shape");
134  }
135  currentValue.setTensorData(from.getTensorData());
136  case ParameterValue::ParameterType::TYPE_UNDEFINED:
137  throw std::runtime_error("Cannot assign a value to an undefined parameter");
138  }
139  } else {
140  throw std::runtime_error(std::string("Unchecked invalid value ") + from.getCurrent<std::string>() + " for parameter " + getUid());
141  }
142  }
143  return *this;
144 }
145 
147  if (!hasDefault()) {
148  throw std::runtime_error(std::string("Cannot set current value from default - no default value set for ") + getUid());
149  }
150  switch (this->type) {
151  case ParameterValue::ParameterType::TYPE_INT:
152  currentValue.setValue(getDefault<int>()); break;
153  case ParameterValue::ParameterType::TYPE_DOUBLE:
154  currentValue.setValue(getDefault<double>()); break;
155  case ParameterValue::ParameterType::TYPE_STRING:
156  case ParameterValue::ParameterType::TYPE_SAFESTRING:
157  currentValue.setValue(getDefault<std::string>()); break;
158  break;
159  case ParameterValue::ParameterType::TYPE_BOOL:
160  currentValue.setValue(getDefault<bool>()); break;
161  break;
162  case ParameterValue::ParameterType::TYPE_TENSOR:
163  if (hasCurrent() && (currentValue.getTensorNumElements() != defaultValue.getTensorNumElements())) {
164  throw std::runtime_error(std::string("Mismatching current and default tensor sizes for ") + getUid());
165  }
166  currentValue.setTensorData(defaultValue.getTensorData());
167  break;
168  case ParameterValue::ParameterType::TYPE_COMMAND:
169  // Ignore commands for resetting to default value
170  break;
171  case ParameterValue::ParameterType::TYPE_UNDEFINED:
172  throw std::runtime_error("Cannot assign a value to an undefined parameter");
173  }
174  return *this;
175 }
176 
177 template<> VT_EXPORT bool Parameter::enforceIncrement(bool t) {
178  return t;
179 }
180 
181 template<> VT_EXPORT int Parameter::enforceIncrement(int t) {
182  if (hasIncrement() && ((this->type==ParameterValue::TYPE_INT) || (this->type==ParameterValue::TYPE_DOUBLE))) {
183  double val = t;
184  double inc = getIncrement<double>();
185  if (hasRange()) {
186  double min = getMin<double>();
187  return (int) (min + inc * ((int) (val-min)/inc));
188  } else {
189  return (int) (inc * ((int) val/inc));
190  }
191  } else {
192  return t;
193  }
194 }
195 
196 template<> VT_EXPORT double Parameter::enforceIncrement(double t) {
197  if (hasIncrement() && ((this->type==ParameterValue::TYPE_INT) || (this->type==ParameterValue::TYPE_DOUBLE))) {
198  double val = t;
199  double inc = getIncrement<double>();
200  if (hasRange()) {
201  double min = getMin<double>();
202  return min + inc * ((int) (val-min)/inc);
203  } else {
204  return inc * ((int) val/inc);
205  }
206  } else {
207  return t;
208  }
209 }
210 
211 template<> VT_EXPORT std::string Parameter::enforceIncrement(std::string t) {
212  if (hasIncrement() && ((this->type==ParameterValue::TYPE_INT) || (this->type==ParameterValue::TYPE_DOUBLE))) {
213  double val = ConversionHelpers::anyToDouble(t);
214  double inc = getIncrement<double>();
215  if (hasRange()) {
216  double min = getMin<double>();
217  return ConversionHelpers::anyToString(min + inc * ((int) (val-min)/inc));
218  } else {
219  return ConversionHelpers::anyToString(inc * ((int) val/inc));
220  }
221  } else {
222  return t;
223  }
224 }
225 
226 std::vector<double>& Parameter::getTensorDataReference() {
227  if (hasCurrent()) {
228  return currentValue.getTensorDataReference();
229  } else {
230  if (hasDefault()) {
231  return defaultValue.getTensorDataReference();
232  } else {
233  throw std::runtime_error("Tried getTensorDataReference(), but no value set and no default defined");
234  }
235  }
236 }
237 
238 std::vector<double> Parameter::getTensorData() const {
239  if (hasCurrent()) {
240  return currentValue.getTensorData();
241  } else {
242  if (hasDefault()) {
243  return defaultValue.getTensorData();
244  } else {
245  throw std::runtime_error("Tried getTensorData(), but no value set and no default defined");
246  }
247  }
248 }
249 
251  if (hasDefault()) {
252  return defaultValue.getTensorDataReference();
253  } else {
254  throw std::runtime_error("Tried getTensorDefaultDataReference(), but no value set and no default defined");
255  }
256 }
257 
258 std::vector<double> Parameter::getTensorDefaultData() const {
259  if (hasDefault()) {
260  return defaultValue.getTensorData();
261  } else {
262  throw std::runtime_error("Tried getTensorDefaultData(), but no default defined");
263  }
264 }
265 
266 } // namespace param
267 } // namespace visiontransfer
268 
269 
std::string interpolateCommandLine(const ParameterValue &newVal)
Definition: parameter.cpp:34
bool isValidNewValue(T t) const
Definition: parameter.h:245
unsigned int getTensorDimension() const
Definition: parameter.h:122
static double anyToDouble(T val)
Converts any type to a double.
std::vector< double > & getTensorDefaultDataReference()
Definition: parameter.cpp:250
Parameter & setCurrentFrom(const Parameter &from)
Definition: parameter.cpp:111
std::string getUid() const
Definition: parameter.h:72
std::vector< double > & getTensorDataReference()
Definition: parameter.cpp:226
std::vector< double > getTensorDefaultData() const
Definition: parameter.cpp:258
std::vector< double > getTensorData() const
Return a copy of the internal tensor data.
std::vector< unsigned int > getTensorShape() const
Definition: parameter.h:125
static std::string anyToString(T val)
Converts any type to a string.
Parameter & setTensorData(const std::vector< double > &data)
Definition: parameter.h:139
std::vector< double > & getTensorDataReference()
Return a reference to the internal tensor data (caution)
std::vector< double > getTensorData() const
Definition: parameter.cpp:238
Nerian Vision Technologies