File: elxConversion.h

package info (click to toggle)
elastix 5.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 42,480 kB
  • sloc: cpp: 68,403; lisp: 4,118; python: 1,013; xml: 182; sh: 177; makefile: 33
file content (242 lines) | stat: -rw-r--r-- 8,174 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef elxConversion_h
#define elxConversion_h

#include "itkMatrix.h"

#include <iterator>
#include <map>
#include <string>
#include <type_traits> // For is_integral and is_same.
#include <vector>

namespace itk
{
// Forward declaration from ITK header <itkOptimizerParameters.h>.
template <typename>
class ITK_TEMPLATE_EXPORT OptimizerParameters;
} // namespace itk

namespace elastix
{
/**
 * \class Conversion
 *
 * \brief A class that contains utility functions for the conversion of
 * number of seconds and parameter values to text.
 */
class Conversion
{
public:
  /** Corresponds with typedefs from the elastix class itk::ParameterFileParser. */
  using ParameterValuesType = std::vector<std::string>;
  using ParameterMapType = std::map<std::string, ParameterValuesType>;
  using Self = Conversion;

  /** Convenience function to convert seconds to day, hour, minute, second format. */
  static std::string
  SecondsToDHMS(const double totalSeconds, const unsigned int precision);

  /** Convenience function to convert a boolean to a text string. */
  static constexpr const char *
  BoolToString(const bool arg)
  {
    return arg ? "true" : "false";
  }

  /** Converts a raw itk::Object pointer to a text string. */
  static std::string
  ObjectPtrToString(itk::Object *);

  /** Converts the specified `std::vector` to an OptimizerParameters object. */
  static itk::OptimizerParameters<double>
  ToOptimizerParameters(const std::vector<double> &);

  /** Converts the specified parameter map to a text string, according to the elastix parameter text file format. */
  static std::string
  ParameterMapToString(const ParameterMapType &);

  /** Convenience function overload to convert a Boolean to a text string. */
  static std::string
  ToString(const bool arg)
  {
    return BoolToString(arg);
  }

  /** Convenience function overload to convert a double precision floating point to a text string. */
  static std::string
  ToString(double);

  /** Convenience function overload to convert a single precision floating point to a text string. */
  static std::string
  ToString(float);

  /** Convenience function overload to convert an integer to a text string. */
  template <typename TInteger>
  static std::string
  ToString(const TInteger integerValue)
  {
    static_assert(std::is_integral_v<TInteger>, "An integer type expected!");
    static_assert(!std::is_same_v<TInteger, bool>, "No bool expected!");
    return std::to_string(integerValue);
  }


  /** Convenience function overload to convert a container to a vector of
   * text strings. The container may be an itk::Size, itk::Index,
   * itk::Point<double,N>, or itk::Vector<double,N>, or
   * itk::OptimizationParameters<double>.
   *
   * The C++ SFINAE idiom is being used to ensure that the argument type
   * supports standard C++ iteration.
   */
  template <typename TContainer, typename SFINAE = typename TContainer::iterator>
  static std::vector<std::string>
  ToVectorOfStrings(const TContainer & container)
  {
    std::vector<std::string> result;

    result.reserve(container.size());

    for (const auto element : container)
    {
      result.push_back(Conversion::ToString(element));
    }
    return result;
  }

  /** Convenience function overload to convert a 2-D matrix to a vector of
   * text strings. Typically used for an itk::ImageBase::DirectionType.
   */
  template <typename T, unsigned int NRows, unsigned int NColumns>
  static std::vector<std::string>
  ToVectorOfStrings(const itk::Matrix<T, NRows, NColumns> & matrix)
  {
    std::vector<std::string> result;
    result.reserve(NColumns * NRows);

    for (unsigned column{}; column < NColumns; ++column)
    {
      for (unsigned row{}; row < NRows; ++row)
      {
        result.push_back(Conversion::ToString(matrix(row, column)));
      }
    }
    return result;
  }


  /** Convenience function to concatenate two vectors. */
  template <typename TValue>
  static std::vector<TValue>
  ConcatenateVectors(std::vector<TValue> vector1, std::vector<TValue> vector2)
  {
    vector1.insert(end(vector1), std::make_move_iterator(begin(vector2)), std::make_move_iterator(end(vector2)));
    return vector1;
  }


  /** Convenience function which tells whether the argument may represent a number (either fixed point, floating point,
   * or integer/whole number).
   * \note IsNumber("NaN") and IsNumber("nan") return false.
   */
  static bool
  IsNumber(const std::string &);


  /** Similar to Qt5 `QDir::toNativeSeparators(const QString &pathName)`.
   */
  static std::string
  ToNativePathNameSeparators(const std::string &);

  /** A templated function to cast strings to a type T.
   * Returns true when casting was successful and false otherwise.
   * We make use of the casting functionality of string streams.
   */
  template <class T>
  static bool
  StringToValue(const std::string & str, T & value)
  {
    // Conversion to bool is supported by another StringToValue overload.
    static_assert(!std::is_same_v<T, bool>, "This StringToValue<T> overload does not support bool!");

    // 8-bits (signed/unsigned) char types are supported by other StringToValue
    // overloads.
    static_assert(sizeof(T) > 1, "This StringToValue<T> overload does not support (signed/unsigned) char!");

    if (std::is_unsigned_v<T> && (!str.empty()) && (str.front() == '-'))
    {
      // An unsigned value should not start with a minus sign!
      return false;
    }

    auto inputStream = [&str] {
      const auto decimalPointPos = str.find_first_of('.');
      const bool hasDecimalPointAndTrailingZeros =
        (decimalPointPos != std::string::npos) &&
        (static_cast<std::uintmax_t>(std::count(str.cbegin() + decimalPointPos + 1, str.cend(), '0')) ==
         (str.size() - decimalPointPos - 1));
      return std::istringstream(
        hasDecimalPointAndTrailingZeros ? std::string(str.cbegin(), str.cbegin() + decimalPointPos) : str);
    }();

    // Note: `inputStream >> value` evaluates to false when the `badbit` or the `failbit` is set.
    return (inputStream >> value) && inputStream.eof();

  } // end StringToValue()


  /** Provide a specialization for std::string, since the general StringToValue
   * (especially outputStringStream >> value) will not work for strings containing spaces.
   */
  static bool
  StringToValue(const std::string & str, std::string & value);

  /**@{ Overloads for floating point types, to support NaN and infinity. */
  static bool
  StringToValue(const std::string & str, double & value);

  static bool
  StringToValue(const std::string & str, float & value);
  /**@}*/

  /**@{ Overloads for (signed/unsigned) char types, processing them as 8-bits integer types. */
  static bool
  StringToValue(const std::string & str, char & value);

  static bool
  StringToValue(const std::string & str, signed char & value);

  static bool
  StringToValue(const std::string & str, unsigned char & value);
  /**@}*/

  /** Overload to cast a string to a bool. Returns true when casting was successful and false otherwise. */
  static bool
  StringToValue(const std::string & str, bool & value);

  /** Overload to cast a string to an itk::Object pointer. Returns true when casting was successful and false otherwise.
   */
  static bool
  StringToValue(const std::string & str, itk::Object *& value);
};

} // end namespace elastix

#endif // end #ifndef elxConversion_h