Seg3D  2.4
Seg3D is a free volume segmentation and processing tool developed by the NIH Center for Integrative Biomedical Computing at the University of Utah Scientific Computing and Imaging (SCI) Institute.
stos.hxx
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2016 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27  */
28 
29 // File : stos.hxx
30 // Author : Pavel A. Koshevoy
31 // Created : 2006/06/23 13:40
32 // Copyright : (C) 2004-2008 University of Utah
33 // Description : Slice to slice registration container class.
34 
35 #ifndef STOS_HXX_
36 #define STOS_HXX_
37 
38 // system includes:
39 #include <iostream>
40 #include <iomanip>
41 #include <fstream>
42 #include <string>
43 
44 // boost:
45 #include <boost/filesystem.hpp>
46 
47 // local includes:
48 #include <Core/ITKCommon/common.hxx>
49 #include <Core/ITKCommon/the_utils.hxx>
50 
51 #include <Core/Utils/Exception.h>
52 #include <Core/Utils/Log.h>
53 
54 namespace bfs=boost::filesystem;
55 
56 //----------------------------------------------------------------
57 // stos_t
58 //
59 template <typename TImage = image_t>
60 class stos_t
61 {
62 public:
63  stos_t() {}
64 
65  stos_t(const bfs::path & fn_s0,
66  const bfs::path & fn_s1,
67  const bfs::path & fn_mask_s0,
68  const bfs::path & fn_mask_s1,
69  const bool & flipped_0,
70  const bool & flipped_1,
71  const TImage * s0,
72  const TImage * s1,
73  const unsigned int & shrink_factor,
74  const base_transform_t * t01) : t01_(t01)
75  {
76  fn_[0] = fn_s0;
77  fn_[1] = fn_s1;
78 
79  fn_mask_[0] = fn_mask_s0;
80  fn_mask_[1] = fn_mask_s1;
81 
82  flipped_[0] = flipped_0;
83  flipped_[1] = flipped_1;
84 
85  sp_[0] = s0->GetSpacing();
86  sp_[1] = s1->GetSpacing();
87 
88  sz_[0] = s0->GetLargestPossibleRegion().GetSize();
89  sz_[1] = s1->GetLargestPossibleRegion().GetSize();
90 
91  sp_[0][0] /= shrink_factor;
92  sp_[0][1] /= shrink_factor;
93  sp_[1][0] /= shrink_factor;
94  sp_[1][1] /= shrink_factor;
95 
96  sz_[0][0] *= shrink_factor;
97  sz_[0][1] *= shrink_factor;
98  sz_[1][0] *= shrink_factor;
99  sz_[1][1] *= shrink_factor;
100  }
101 
102  stos_t(const bfs::path & fn_s0,
103  const bfs::path & fn_s1,
104  const bfs::path & fn_mask_s0,
105  const bfs::path & fn_mask_s1,
106  const bool & flipped_0,
107  const bool & flipped_1,
108  const double spacing_x0,
109  const double spacing_y0,
110  const double spacing_x1,
111  const double spacing_y1,
112  const unsigned int size_x0,
113  const unsigned int size_y0,
114  const unsigned int size_x1,
115  const unsigned int size_y1,
116  const base_transform_t * t01) : t01_(t01)
117  {
118  fn_[0] = fn_s0;
119  fn_[1] = fn_s1;
120 
121  fn_mask_[0] = fn_mask_s0;
122  fn_mask_[1] = fn_mask_s1;
123 
124  flipped_[0] = flipped_0;
125  flipped_[1] = flipped_1;
126 
127  sp_[0][0] = spacing_x0;
128  sp_[0][1] = spacing_y0;
129  sp_[1][0] = spacing_x1;
130  sp_[1][1] = spacing_y1;
131 
132  sz_[0][0] = size_x0;
133  sz_[0][1] = size_y0;
134  sz_[1][0] = size_x1;
135  sz_[1][1] = size_y1;
136  }
137 
138  stos_t(const bfs::path & fn_load,
139  const bfs::path & override_slice0_path = "",
140  const bfs::path & override_slice1_path = "")
141  {
142  if (! load(fn_load, override_slice0_path, override_slice1_path) )
143  {
144  std::ostringstream oss;
145  oss << "Loading stos file " << fn_load << " (with slice path overrides "
146  << override_slice0_path << " and " << override_slice1_path << ") failed.";
147  CORE_THROW_EXCEPTION(oss.str());
148  }
149  }
150 
151  // load the filenames of the slices and the corresponding transform:
152  bool load(const bfs::path & fn_load,
153  const bfs::path & slice0_path = "",
154  const bfs::path & slice1_path = "",
155  const bool blab = false)
156  {
157  std::fstream si;
158  the::open_utf8(si, fn_load.string().c_str(), std::ios::in);
159  if (!si.is_open())
160  {
161  std::ostringstream oss;
162  oss << "Could not open " << fn_load << " for reading, skipping....";
163  CORE_LOG_WARNING(oss.str());
164  return false;
165  }
166 
167  fn_load_ = fn_load;
168  if (blab) std::cout << "stos_t loading " << fn_load_.string() << std::endl;
169 
170  bool ok = load(si, slice0_path, slice1_path);
171  si.close();
172 
173  return ok;
174  }
175 
176  bool load(std::istream & si,
177  const bfs::path & override_slice0_path = "",
178  const bfs::path & override_slice1_path = "")
179  {
180  std::string f[2];
181  std::getline(si, f[0]);
182  std::getline(si, f[1]);
183 
184  // Setup slice paths...
185  bfs::path corrected_path[2];
186  corrected_path[0] = override_slice0_path;
187  corrected_path[1] = override_slice1_path;
188 
189  // Override if needed.
190  for (int i = 0; i < 2; i++)
191  {
192  if (! corrected_path[i].empty() )
193  {
194  bfs::path mosaicPath(f[i]);
195  bfs::path p = corrected_path[i] / mosaicPath.filename();
196  if ( bfs::exists(p) )
197  {
198  fn_[i] = p;
199  }
200  else
201  {
202  std::ostringstream oss;
203  oss << "Overridden file path " << p << " does not exist. Ignoring path override.";
204  CORE_LOG_WARNING(oss.str());
205 
206  fn_[i] = f[i];
207  }
208  }
209  else
210  {
211  if ( bfs::exists(f[i]) )
212  {
213  fn_[i] = f[i];
214  }
215  else
216  {
217  std::ostringstream oss;
218  oss << "File path " << f[i] << " does not exist.";
219  CORE_LOG_ERROR(oss.str());
220  return false;
221  }
222  }
223  }
224 
225  std::string line;
226  {
227  std::getline(si, line);
228  std::istringstream iss(line);
229  iss >> flipped_[0];
230  line.clear();
231  }
232 
233  {
234  std::getline(si, line);
235  std::istringstream iss(line);
236  iss >> flipped_[1];
237  line.clear();
238  }
239 
240  {
241  std::getline(si, line);
242  std::istringstream iss(line);
243  iss >> sp_[0][0] >> sp_[0][1] >> sz_[0][0] >> sz_[0][1];
244  line.clear();
245  }
246 
247  {
248  std::getline(si, line);
249  std::istringstream iss(line);
250  iss >> sp_[1][0] >> sp_[1][1] >> sz_[1][0] >> sz_[1][1];
251  line.clear();
252  }
253 
254  itk::TransformBase::Pointer tmp = load_transform(si);
255 
256  t01_ = dynamic_cast<base_transform_t *>(tmp.GetPointer());
257  bool ok = t01_.GetPointer() != NULL;
258 
259  fn_mask_[0].clear();
260  fn_mask_[1].clear();
261 
262  // skip to the next line (by skipping white space):
263  si >> std::ws;
264 
265  std::string optional;
266  std::getline(si, optional);
267  if (optional == "two_user_supplied_masks:")
268  {
269  std::string tmp;
270  std::getline(si, tmp);
271  if ( bfs::exists(bfs::path(tmp)) )
272  {
273  fn_mask_[0] = tmp;
274  }
275  tmp.clear();
276  std::getline(si, tmp);
277  if ( bfs::exists(bfs::path(tmp)) )
278  {
279  fn_mask_[1] = tmp;
280  }
281  }
282 
283  return ok;
284  }
285 
286  // save this slice-to-slice registration:
287  bool save(const bfs::path & fn_save, const bool blab = false) const
288  {
289  std::fstream so;
290  the::open_utf8(so, fn_save.string().c_str(), std::ios::out);
291  if (!so.is_open())
292  {
293  std::ostringstream oss;
294  oss << "Could not open " << fn_save << " for writing, skipping....";
295  CORE_LOG_WARNING(oss.str());
296  return false;
297  }
298  if (blab) std::cout << "saving " << fn_save << std::endl;
299 
300  save(so);
301  so.close();
302 
303  // FIXME: not sure if this is useful/necessary:
304  fn_load_ = fn_save;
305 
306  return true;
307  }
308 
309  void save(std::ostream & so) const
310  {
311  std::ios::fmtflags old_flags = so.setf(std::ios::scientific);
312  int old_precision = so.precision();
313  so.precision(12);
314 
315  so << fn_[0].string() << std::endl
316  << fn_[1].string() << std::endl
317  << flipped_[0] << std::endl
318  << flipped_[1] << std::endl
319  << sp_[0][0] << '\t'
320  << sp_[0][1] << '\t'
321  << static_cast<int>(sz_[0][0]) << '\t'
322  << static_cast<int>(sz_[0][1]) << std::endl
323  << sp_[1][0] << '\t'
324  << sp_[1][1] << '\t'
325  << static_cast<int>(sz_[1][0]) << '\t'
326  << static_cast<int>(sz_[1][1]) << std::endl;
327 
328  save_transform(so, t01_);
329  so << std::endl;
330 
331  if (!fn_mask_[0].empty() && !fn_mask_[1].empty())
332  {
333  so << "two_user_supplied_masks:" << std::endl
334  << fn_mask_[0].string() << std::endl
335  << fn_mask_[1].string() << std::endl;
336  }
337 
338  so.setf(old_flags);
339  so.precision(old_precision);
340  }
341 
342  // convenience functions:
343  inline pnt2d_t tile_min(unsigned int /* i */) const
344  { return pnt2d(0, 0); }
345 
346  inline pnt2d_t tile_max(unsigned int i) const
347  {
348  return pnt2d(sp_[i][0] * static_cast<double>(sz_[i][0]),
349  sp_[i][1] * static_cast<double>(sz_[i][1]));
350  }
351 
352  inline pnt2d_t tile_center(unsigned int i) const
353  {
354  pnt2d_t min = tile_min(i);
355  pnt2d_t max = tile_max(i);
356  return min + (max - min) * 0.5;
357  }
358 
359  // datamembers:
360  mutable bfs::path fn_load_;
361  bfs::path fn_[2]; // filenames of the fixed/moving slices
362  bfs::path image_dirs_[2];
363  bfs::path fn_mask_[2]; // filenames of slice masks, optional
364  bool flipped_[2];
365  typename TImage::SpacingType sp_[2];
366  typename TImage::RegionType::SizeType sz_[2];
367  base_transform_t::ConstPointer t01_;
368 };
369 
370 //----------------------------------------------------------------
371 // operator <<
372 //
373 template <typename TImage>
374 inline static std::ostream &
375 operator << (std::ostream & so, const stos_t<TImage> & stos)
376 {
377  stos.save(so);
378  return so;
379 }
380 
381 //----------------------------------------------------------------
382 // save_stos
383 //
384 template <typename TImage>
385 inline static bool
386 save_stos(const bfs::path & fn_save,
387  const bfs::path & fn_s0,
388  const bfs::path & fn_s1,
389  const bfs::path & fn_mask_s0,
390  const bfs::path & fn_mask_s1,
391  const bool & flipped_0,
392  const bool & flipped_1,
393  const TImage * s0,
394  const TImage * s1,
395  const unsigned int & shrink_factor,
396  const base_transform_t * transform,
397  const bool blab = false)
398 {
399  stos_t<TImage> stos(fn_s0,
400  fn_s1,
401  fn_mask_s0,
402  fn_mask_s1,
403  flipped_0,
404  flipped_1,
405  s0,
406  s1,
407  shrink_factor,
408  transform);
409  return stos.save(fn_save, blab);
410 }
411 
412 
413 #endif // STOS_HXX_
Definition: stos.hxx:60