brainrat-private  5.1.2
slices_d.h
Go to the documentation of this file.
1 /* Copyright (C) 2000-2013 CEA
2  *
3  * This software and supporting documentation were developed by
4  * bioPICSEL
5  * CEA/DSV/I²BM/MIRCen/LMN, Batiment 61,
6  * 18, route du Panorama
7  * 92265 Fontenay-aux-Roses
8  * France
9  */
10 
11 #include <cartobase/object/object.h>
12 #include <cartobase/stream/directory.h>
13 #include <cartobase/stream/fileutil.h>
14 #include <aims/io/channelR.h>
15 #include <brainrat/data/slices.h>
17 
18 
19 //------------------------------------------------------------------------------
20 // Utility functions
21 //------------------------------------------------------------------------------
22 template<class T> bool
23 detectSlices(aims::Process & p, const std::string &, aims::Finder &)
24 {
25  SlicesDetector & proc = (SlicesDetector &)p;
26 
27  // Instanciate detector object
29  1. / proc.fraction,
30  NB_MODES,
31  MAX_HISTO,
32  !proc.disable_checks);
33 
34 // std::vector<Component> components;
35  carto::Object bounds;
36 
37 // float default_value = (proc.res? INCH / proc.res > 0 : 1.);
38 // std::vector<float> vs(default_value, 4);
39 
40  carto::VolumeRef<int16_t> vol;
41  //
42  // Read data to use for processing components
43  //
44  aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileIn);
45  reader.read(vol, proc.c);
46  std::cout << "Original image loaded" << std::endl;
47 
48  // Step 1: Detect components
49  std::vector<Component> components = detector.analyze(vol, proc.n, proc.res,
50  proc.lt, proc.ht);
51 
52  // Step 2: Convert components to generic object that describes bounding
53  // boxes
54  bounds = detector.boundingBoxes(vol, components);
55 
56 // // Step 2: sort components
57 // // It is necessary to first sort using 2 dimensions because images are 2d
58 // if (proc.dimensionsizes.size() == 0) {
59 // proc.dimensionsizes.push_back(1);
60 // }
61 //
62 // if (proc.dimensionorders.size() == 0) {
63 // proc.dimensionorders.push_back(0);
64 // }
65 //
66 // std::vector<int32_t> columnsizes;
67 // columnsizes.push_back(proc.dimensionsizes[0]);
68 // columnsizes.push_back(proc.dimensionsizes[1] * proc.dimensionsizes[2]);
69 // columnsizes.push_back(1);
70 // // std::cout << "First sorting process." << std::endl;
71 // components = sortComponent(components, columnsizes);
72 // // std::cout << "Second sorting process." << std::endl;
73 // components = changeComponentsIndex(components,
74 // proc.dimensionsizes,
75 // proc.dimensionorders,
76 // 1, 1);
77 //
78 // std::cout << "Last sorting process (according to slice taking)."
79 // << std::endl;
80 // std::cout << std::endl;
81 // writeComponents(components);
82 // std::cout << std::endl;
83 
84  // Write components in JSON format
85 // carto::Object bounds = carto::Object::value(carto::PropertySet());
86 // std::vector<carto::Object> b;
87 //
88 // std::vector<Component>::const_iterator end = components.end(), it;
89 // for (it = components.begin(); it != end; ++it) {
90 // carto::Object bound = carto::Object::value(carto::PropertySet());
91 //
92 // std::vector<std::vector<float> > v;
93 // std::vector<float> lower_bound(3, 0.);
94 // std::vector<float> upper_bound(3, 0.);
95 // const Component & c = *it;
96 //
97 // // Get bounding box coordinates
98 // lower_bound[0] = (vs[0] * c.abscissa_x);
99 // lower_bound[1] = (vs[1] * c.ordinate_y);
100 // lower_bound[2] = (vs[2] * c.coordinate_z);
101 // upper_bound[0] = (vs[0] * c.abscissa_X);
102 // upper_bound[1] = (vs[1] * c.ordinate_Y);
103 // upper_bound[2] = (vs[2] * c.coordinate_Z);
104 // v.push_back(lower_bound);
105 // v.push_back(upper_bound);
106 //
107 // bound->setProperty("bounds", v);
108 // b.push_back(bound);
109 // }
110 // bounds->setProperty("bounding_boxes", b);
111 
112  aims::Writer<carto::Object> w(proc.fileOut);
113  const std::string format("JSON");
114  return w.write(bounds, false, &format);
115 }
116 
117 template<class T> bool
118 individStackSlices(aims::Process & p, const std::string &, aims::Finder &)
119 {
120  SlicesStacker & proc = (SlicesStacker &)p;
121 
122 // #ifdef INDIVID_STACK_SLICES
123  carto::VolumeRef<T> vol;
124 
125  std::vector<Component> components;
126 
127  if (proc.dimensionsizes.size() == 0) {
128  proc.dimensionsizes.push_back(1);
129  }
130 
131  if (proc.dimensionorders.size() == 0) {
132  proc.dimensionorders.push_back(0);
133  }
134 
135 
136  {
137  // Only allocate data_analysis during analysis step
138  carto::VolumeRef<int16_t> volgrey;
139  //
140  // Read data to use for processing components
141  //
142  if (!proc.fileInP.empty())
143  {
144  aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileInP);
145  reader.read(volgrey, proc.c);
146  std::cout << "Pre-processed image loaded" << std::endl;
147  }
148  else
149  {
150  aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileIn);
151  reader.read(volgrey, proc.c);
152  std::cout << "Original image loaded" << std::endl;
153  }
154  // Instanciate detector object
156  1. / proc.fraction,
157  NB_MODES,
158  MAX_HISTO,
159  true);
160 
161  // Step 1: Detect components
162  components = detector.analyze(volgrey, proc.n, proc.res,
163  proc.lt, proc.ht);
164  }
165 
166  // Step 2: sort components
167  // It is necessary to first sort using 2 dimensions because images are 2d
168  std::vector<int32_t> columnsizes;
169  columnsizes.push_back(proc.dimensionsizes[0]);
170  columnsizes.push_back(proc.dimensionsizes[1] * proc.dimensionsizes[2]);
171  columnsizes.push_back(1);
172  // std::cout << "First sorting process." << std::endl;
173  components = sortComponent(components, columnsizes);
174  // std::cout << "Second sorting process." << std::endl;
175  components = changeComponentsIndex(components,
176  proc.dimensionsizes,
177  proc.dimensionorders,
178  1, 1);
179 
180  std::cout << "Last sort processed (according to slice taking) ..."
181  << std::endl;
182 
183  std::cout << std::endl;
184  writeComponents(components);
185  std::cout << std::endl;
186 
187  // Step 3: reconstruct volume
188  aims::Reader<carto::VolumeRef<T> > fileIn(proc.fileIn);
189  fileIn.read(vol);
190 
191  T bg = background<T>(components, vol);
192  std::cout << "Background : " << toString(bg) << std::endl;
193 
194  bool result = false;
195  if (proc.nostack)
196  {
197  // Use input file name by default
198  std::string outname = (proc.outName.empty() ? FileUtil::removeExtension(
199  FileUtil::basename(
200  proc.fileIn))
201  : proc.outName);
202 
203  result = writeNumberedSlices(proc.dx, proc.dy,
204  proc.res, proc.z,
205  bg,
206  components,
207  vol,
208  proc.fileOut,
209  outname,
210  proc.format,
211  proc.sn);
212  std::cout << "Volume written to output directory. Terminated."
213  << std::endl;
214  }
215  else
216  {
217  result = writeStackedSlices(proc.dx, proc.dy,
218  proc.res, proc.z,
219  bg,
220  components,
221  vol,
222  proc.fileOut,
223  proc.format);
224  std::cout << "Volume written to output file. Terminated." << std::endl;
225  }
226 
227  return result;
228 // #else
229 // std::cout << "!!!WARNING!!! indiviualize and stack processing has been "
230 // "disabled at compile time." << std::endl;
231 // #endif
232 }
233 
234 
235 template<class T>
236 void rescale(carto::VolumeRef<T> &in, RescalerInfo & info)
237 {
238  if (std::isnan(info.vmin)) {
239  if (! info.usevtypelimits) {
240  info.vmin = (double) in.min();
241  }
242  }
243 
244  if (std::isnan(info.vmax)) {
245  if (! info.usevtypelimits) {
246  info.vmax = (double) in.max();
247  }
248  }
249 
250  DefaultedRescalerInfo<T, T> defaultedinfo(info);
251 
252  int x, y, z, t,
253  dx = in.getSizeX(),
254  dy = in.getSizeY(),
255  dz = in.getSizeZ(),
256  dt = in.getSizeT();
257 
258  for (t = 0; t < dt; ++t)
259  {
260  for (z = 0; z < dz; ++z)
261  {
262  for (y = 0; y < dy; ++y)
263  {
264  for (x = 0; x < dx; ++x)
265  in(x, y, z, t) = defaultedinfo.getScaledValue(
266  in(x, y, z, t));
267  }
268  }
269  }
270 }
271 
272 template<class T>
273 bool writeStackedSlices(int32_t dx, int32_t dy, int32_t res,
274  float z,
275  T background,
276  std::vector<Component> &cpnt,
277  carto::VolumeRef<T> &data,
278  std::string outputfile,
279  std::string format)
280 {
281  int32_t x, y, l;
282 
283  const std::string *wf = 0;
284  if (!format.empty())
285  wf = &format;
286 
287  Object options = Object::value(Dictionary());
288  //options->setProperty("exact_format", true);
289 
290  if (dx == 0)
291  dx = extractMaxima(
294  else if (dx < extractMaxima(
296  * BORDER_LOCAL)
297  {
298  throw dimension_x_error();
299  }
300 
301  if (dy == 0)
302  dy = extractMaxima(
305  else if (dy < extractMaxima(
307  * BORDER_LOCAL)
308  {
309  throw dimension_y_error();
310  }
311 
312  carto::VolumeRef<T> recons_volume(dx, dy, cpnt.size());
313  std::vector<float> vs(4, 1.);
314  vs[0] = INCH / res;
315  vs[1] = INCH / res;
316  vs[2] = z;
317 
318  recons_volume.header().setProperty("voxel_size", vs);
319 
320  // Background optimized from histogram analysis
321  recons_volume = background;
322 
323  std::cout << "Reconstructing volume ..." << std::endl << std::endl;
324  for (l = 0; l < int32_t(cpnt.size()); ++l)
325  {
326  Point2d shift, size_component;
327 
328  size_component[0] = cpnt[l].bounding_hz + 2 * BORDER_LOCAL;
329  size_component[1] = cpnt[l].bounding_vt + 2 * BORDER_LOCAL;
330 
331  shift[0] = (dx - size_component[0]) / 2;
332  shift[1] = (dy - size_component[1]) / 2;
333 
334  for (y = 0; y < size_component[1] ; ++y)
335  for (x = 0; x < size_component[0] ; ++x)
336  {
337  if (((x + cpnt[l].abscissa_x - BORDER_LOCAL) >= 0)
338  && ((x + cpnt[l].abscissa_x - BORDER_LOCAL) < data.getSizeX())
339  && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) >= 0)
340  && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) < data.getSizeY()))
341  {
342  recons_volume(x + shift[0],
343  y + shift[1],
344  cpnt[l].label_f - 1) = data(
345  x + cpnt[l].abscissa_x - BORDER_LOCAL,
346  y + cpnt[l].ordinate_y - BORDER_LOCAL);
347  }
348  }
349  }
350 
351  std::cout << "Stacking process achieved." << std::endl;
352 
353  //
354  // Ecriture du fichier
355  //
356  aims::Writer<carto::VolumeRef<T> > volumeWriter(outputfile, options);
357  return volumeWriter.write(recons_volume, false, wf);
358 }
359 
360 template<class T>
361 bool writeNumberedSlices(int32_t dx, int32_t dy, int32_t res,
362  float z,
363  T background,
364  std::vector<Component> &cpnt,
365  carto::VolumeRef<T> &data,
366  std::string outputdir,
367  std::string outputname,
368  std::string format,
369  uint8_t slicemin)
370 {
371  int32_t x, y, l;
372 
373  Directory dir = Directory(outputdir);
374  dir.makedirs();
375 
376  std::string dirname = dir.dirname();
377  std::string extension = FileUtil::extension(outputname);
378  std::string wf = (format.empty() && extension.empty() ? "GIS" : format);
379 
380  Object options = Object::value(Dictionary());
381  options->setProperty("exact_format", true);
382 
383  if (dx == 0)
384  dx = extractMaxima(
387  else if (dx < extractMaxima(
389  * BORDER_LOCAL)
390  {
391  throw dimension_x_error();
392  }
393 
394  if (dy == 0)
395  dy = extractMaxima(
398  else if (dy < extractMaxima(
400  * BORDER_LOCAL)
401  {
402  throw dimension_y_error();
403  }
404 
405  carto::VolumeRef<T> slice(dx, dy);
406  std::vector<float> vs(4, 1.);
407  vs[0] = INCH / res;
408  vs[1] = INCH / res;
409  vs[2] = z;
410 
411  slice.header().setProperty("voxel_size", vs);
412 
413  std::cout << "Writing volume slices ..." << std::endl << std::endl;
414 
415  for (l=0; l<int32_t(cpnt.size()); ++l)
416  {
417  // Background optimized from histogram analysis
418  slice = background;
419 
420  Point2d shift, size_component;
421 
422  size_component[0] = cpnt[l].bounding_hz + 2 * BORDER_LOCAL;
423  size_component[1] = cpnt[l].bounding_vt + 2 * BORDER_LOCAL;
424 
425  shift[0] = (dx - size_component[0]) / 2;
426  shift[1] = (dy - size_component[1]) / 2;
427 
428  for (y = 0; y < size_component[1] ; ++y)
429  for (x = 0; x < size_component[0] ; ++x)
430  {
431  if (((x + cpnt[l].abscissa_x - BORDER_LOCAL) >= 0)
432  && ((x + cpnt[l].abscissa_x - BORDER_LOCAL) < data.getSizeX())
433  && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) >= 0)
434  && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) < data.getSizeY()))
435  {
436  slice(x + shift[0],
437  y + shift[1]) = data(x + cpnt[l].abscissa_x
438  - BORDER_LOCAL,
439  y + cpnt[l].ordinate_y
440  - BORDER_LOCAL);
441  }
442  }
443 
444  std::stringstream ss;
445  ss << outputdir << FileUtil::separator()
446  << FileUtil::removeExtension(FileUtil::basename(outputname));
447  ss << "_" << setfill('0') << setw(4) << slicemin + cpnt[l].label_f - 1;
448 
449  if (! extension.empty())
450  ss << "." << extension;
451 
452  // std::cout << "Writing file : " << ss.str()
453  // << std::endl << std::flush;
454 
455  aims::Writer<carto::VolumeRef<T> > sliceWriter(ss.str(), options);
456  if (! sliceWriter.write(slice, false, &wf))
457  return false;
458  }
459 
460  return true;
461 }
carto::Object boundingBoxes(const carto::VolumeRef< int16_t > &vol, const std::vector< Component > &components)
std::vector< Component > analyze(carto::VolumeRef< int16_t > &vol, const int32_t slices_number=6, const int32_t scan_resolution=0, const int32_t threshold_lowerbound=0, const int32_t threshold_upperbound=0)
float min_size
Definition: slices.h:46
bool disable_checks
Definition: slices.h:50
int32_t lt
Definition: slices.h:48
int32_t res
Definition: slices.h:47
std::string fileOut
Definition: slices.h:44
float fraction
Definition: slices.h:46
int32_t ht
Definition: slices.h:48
uint8_t c
Definition: slices.h:49
int32_t n
Definition: slices.h:47
std::string fileIn
Definition: slices.h:43
int32_t lt
Definition: slices.h:71
int32_t res
Definition: slices.h:70
std::string format
Definition: slices.h:65
float fraction
Definition: slices.h:68
std::string fileIn
Definition: slices.h:60
float z
Definition: slices.h:73
bool nostack
Definition: slices.h:67
uint8_t c
Definition: slices.h:72
float min_size
Definition: slices.h:68
int32_t ht
Definition: slices.h:71
std::vector< int32_t > dimensionsizes
Definition: slices.h:64
std::string fileOut
Definition: slices.h:62
int32_t dy
Definition: slices.h:71
std::vector< int32_t > dimensionorders
Definition: slices.h:64
uint8_t sn
Definition: slices.h:69
int32_t dx
Definition: slices.h:71
int32_t n
Definition: slices.h:70
std::string fileInP
Definition: slices.h:61
std::string outName
Definition: slices.h:63
std::vector< Component > sortComponent(std::vector< Component > &cpnt, std::vector< int32_t > dimensionsizes)
#define NB_MODES
Definition: slices.h:24
@ ComponentSize_vt
Definition: slices.h:97
@ ComponentSize_hz
Definition: slices.h:96
#define BORDER_GLOBAL
Definition: slices.h:34
std::vector< Component > changeComponentsIndex(std::vector< Component > &components, std::vector< int32_t > dimensionsizes, std::vector< int32_t > dimensionorders, int32_t offset=1, int32_t step=1)
#define MAX_HISTO
Definition: slices.h:26
#define BORDER_LOCAL
Definition: slices.h:33
void writeComponents(std::vector< Component > &comp)
int32_t extractMaxima(std::vector< int32_t > vctr)
T background(std::vector< Component > &cpnt, carto::VolumeRef< T > &vol)
Definition: slices.h:489
#define INCH
Definition: slices.h:23
std::vector< int32_t > extractVectorFromComponent(std::vector< Component > cpnt, ContinuityParameterTested param)
void rescale(carto::VolumeRef< T > &in, RescalerInfo &info)
Definition: slices_d.h:236
bool detectSlices(aims::Process &p, const std::string &, aims::Finder &)
Definition: slices_d.h:23
bool writeNumberedSlices(int32_t dx, int32_t dy, int32_t res, float z, T background, std::vector< Component > &cpnt, carto::VolumeRef< T > &data, std::string outputdir, std::string outputname, std::string format, uint8_t slicemin)
Definition: slices_d.h:361
bool writeStackedSlices(int32_t dx, int32_t dy, int32_t res, float z, T background, std::vector< Component > &cpnt, carto::VolumeRef< T > &data, std::string outputfile, std::string format)
Definition: slices_d.h:273
bool individStackSlices(aims::Process &p, const std::string &, aims::Finder &)
Definition: slices_d.h:118