modis_dataset.cpp
Go to the documentation of this file.
1 // MODIS
2 #include "block_utils.h"
3 #include "fifo_cache.h"
4 #include "modis_dataset.h"
5 
6 // TerraLib
7 #include <terralib/geometry.h>
8 #include <terralib/raster.h>
9 #include <terralib/srs.h>
10 
11 // STL
12 #include <cassert>
13 #include <set>
14 
15 // Boost
16 #include <boost/date_time/gregorian/gregorian.hpp>
17 #include <boost/timer/timer.hpp>
18 
20 {
21  public:
22 
23  impl(const std::map <std::string, std::map <std::string, std::string > >& tile_idx,
24  const std::string subdataset_prefix,
25  const std::string subdataset_suffix,
26  std::size_t max_pixel_cache_size,
27  std::size_t max_block_cache_size,
28  std::size_t max_raster_cache_size);
29 
30  ~impl();
31 
32  void query(const double& longitude, const double& latitude,
33  const unsigned char** values,
34  const std::vector<boost::gregorian::date>** times) const;
35 
36  int data_type() const;
37 
38  const te::rst::Grid* grid() const;
39 
40  private:
41 
42  unsigned char* check_in_block_cache(unsigned int col, unsigned int row) const;
43 
44  unsigned char* check_in_raster_cache(unsigned int col, unsigned int row) const;
45 
46  unsigned char* check_in_disk(unsigned int col, unsigned int row) const;
47 
48  unsigned char* sync_cache_from_blocks(const std::vector<unsigned char*>& blocks,
49  unsigned int col,
50  unsigned int row) const;
51 
52  unsigned char* sync_cache_from_rasters(const std::vector<te::rst::Raster*>& rasters,
53  unsigned int col,
54  unsigned int row) const;
55 
56  //unsigned char* alloc_pixel();
57 
58  std::vector<unsigned char*>* alloc_blocks() const;
59 
60  void extract_block_data(std::vector<unsigned char*>& blocks,
61  const std::vector<te::rst::Raster*>& rasters,
62  unsigned int block_x,
63  unsigned int block_y) const;
64 
66 
68 
69  void load_time_info();
70 
71  private:
72 
73  std::vector<boost::gregorian::date> m_times;
74  std::string m_subdataset_prefix;
75  std::string m_subdataset_suffix;
77  const std::map <std::string, std::map <std::string, std::string > >* m_tile_idx;
83  unsigned int m_blk_w;
84  unsigned int m_blk_h;
85  unsigned int m_blk_size;
86  unsigned int m_nblks_x;
87  unsigned int m_nblks_y;
88  unsigned int m_nblks_per_tile;
89  unsigned int m_modis_tile_w;
90  unsigned int m_modis_tile_h;
91  unsigned int m_ntiles_x;
92  unsigned int m_ntiles_y;
93  unsigned int m_modis_tile_h_offset;
94  unsigned int m_modis_tile_v_offset;
95  unsigned int m_tot_blocks_in_x;
98 };
99 
100 modis_dataset::impl::impl(const std::map <std::string, std::map <std::string, std::string > >& tile_idx,
101  const std::string subdataset_prefix,
102  const std::string subdataset_suffix,
103  std::size_t max_pixel_cache_size,
104  std::size_t max_block_cache_size,
105  std::size_t max_raster_cache_size)
106  : m_subdataset_prefix(subdataset_prefix),
107  m_subdataset_suffix(subdataset_suffix),
109  m_tile_idx(&tile_idx),
110  m_grid(0),
111  m_converter(0),
112  m_pixel_cache(0),
113  m_block_cache(0),
114  m_raster_cache(0),
115  m_blk_w(0),
116  m_blk_h(0),
117  m_blk_size(0),
118  m_nblks_x(0),
119  m_nblks_y(0),
120  m_nblks_per_tile(0),
121  m_modis_tile_w(0),
122  m_modis_tile_h(0),
123  m_ntiles_x(0),
124  m_ntiles_y(0),
130 {
131  load_time_info();
132 
134 
136 
138 
140 
141  //converter->setSourceSRID(4326);
142  //converter->setTargetSRID(150000);
143 
144  m_pixel_cache = new fifo_cache<unsigned char>(max_pixel_cache_size);
145 
146  m_block_cache = new fifo_cache<std::vector<unsigned char*> >(max_block_cache_size);
147 
148  m_raster_cache = new fifo_cache<std::vector<te::rst::Raster*> >(max_raster_cache_size);
149 
151 }
152 
154 {
155  delete m_grid;
156  delete m_converter;
157  delete m_pixel_cache;
158  delete m_block_cache;
159  delete m_raster_cache;
160 }
161 
162 inline void modis_dataset::impl::query(const double& longitude, const double& latitude,
163  const unsigned char** values,
164  const std::vector<boost::gregorian::date>** times) const
165 {
166  *values = 0;
167  *times = 0;
168 
169  //if(longitude < -180.0 || longitude > 180.0 ||
170  // latitude < -90.0 || latitude > 90.0)
171  // throw std::runtime_error("point query is out of range!");
172 
173 // tranform long/lat to sinu
174  double x = longitude; //double x = 0.0;
175  double y = latitude; //double y = 0.0;
176 
177  //m_converter->convert(longitude, latitude, x, y);
178 
179 // check if tranformation is in range
180  //if(x < m_grid->getExtent( || x > m_xmax ||
181  // y < m_ymin || y > m_ymax)
182  // throw std::runtime_error("point query after srs tranformation is out of range!");
183 
184 // transform world in column and row indices
185  double dcol = 0.0;
186  double drow = 0.0;
187 
188  m_grid->geoToGrid(x, y, dcol, drow);
189 
190  unsigned int col = static_cast<unsigned int>(dcol);
191  unsigned int row = static_cast<unsigned int>(drow);
192 
193 // is data in the pixel cache?
194  boost::uint64_t id = static_cast<boost::uint64_t>(row) *
195  static_cast<boost::uint64_t>(m_grid->getNumberOfColumns()) +
196  static_cast<boost::uint64_t>(col);
197 
198  const unsigned char* data = m_pixel_cache->data(id);
199 
200  if(data == 0)
201  {
202  data = check_in_block_cache(col, row);
203 
204  if(data == 0)
205  {
206  data = check_in_raster_cache(col, row);
207 
208  if(data == 0)
209  data = check_in_disk(col, row);
210 
211  if(data == 0)
212  throw std::logic_error("a coisa ta feia!");
213  }
214  }
215 
216  *values = data;
217  *times = &m_times;
218 
219  return;
220 }
221 
223 {
224  return m_value_data_type;
225 }
226 
228 {
229  return m_grid;
230 }
231 
232 inline unsigned char* modis_dataset::impl::check_in_block_cache(unsigned int col, unsigned int row) const
233 {
234  boost::uint64_t v = row / m_modis_tile_h;
235  boost::uint64_t h = col / m_modis_tile_w;
236 
237  boost::uint64_t tile_col = col % m_modis_tile_w;
238  boost::uint64_t tile_row = row % m_modis_tile_h;
239 
240  boost::uint64_t tile_block_x = tile_col / m_blk_w;
241  boost::uint64_t tile_block_y = tile_row / m_blk_h;
242 
243  boost::uint64_t id = (v * m_tot_blocks_in_x) +
244  (h * m_nblks_per_tile) +
245  (tile_block_y * m_nblks_x + tile_block_x);
246 
247  const std::vector<unsigned char*>* blocks = m_block_cache->data(id);
248 
249  return (blocks != 0) ? sync_cache_from_blocks(*blocks, col, row) : 0;
250 }
251 
252 inline unsigned char* modis_dataset::impl::check_in_raster_cache(unsigned int col, unsigned int row) const
253 {
254  unsigned int h = col / m_modis_tile_w;
255 
256  unsigned int v = row / m_modis_tile_h;
257 
258  boost::uint64_t id = static_cast<boost::uint64_t>(v) * m_ntiles_x + static_cast<boost::uint64_t>(h);
259 
260  const std::vector<te::rst::Raster*>* rasters = m_raster_cache->data(id);
261 
262  return (rasters != 0) ? sync_cache_from_rasters(*rasters, col, row) : 0;
263 }
264 
265 inline unsigned char* modis_dataset::impl::check_in_disk(unsigned int col, unsigned int row) const
266 {
267  const std::size_t nrasters = m_times.size();
268 
269  std::vector<te::rst::Raster*>* rasters = 0;
270 
271  if(m_raster_cache->is_full())
272  {
273  for(std::size_t i = 0; i != nrasters; ++i)
274  {
275  delete (*rasters)[i];
276  (*rasters)[i] = 0;
277  }
278  }
279  else
280  {
281  rasters = new std::vector<te::rst::Raster*>(nrasters);
282  }
283 
284 // loop through each raster
285  unsigned int h = col / m_modis_tile_w + m_modis_tile_h_offset;
286 
287  unsigned int v = row / m_modis_tile_h + m_modis_tile_v_offset;
288 
289  std::string sh = boost::lexical_cast<std::string>(h);
290 
291  if(h < 10)
292  sh = "0" + sh;
293 
294  std::string sv = boost::lexical_cast<std::string>(v);
295 
296  if(v < 10)
297  sv = "0" + sv;
298 
299  std::string hv = "h" + sh + "v" + sv;
300 
301  const std::map<std::string, std::string>& raster_files = m_tile_idx->at(hv);
302 
303  std::map<std::string, std::string>::const_iterator it = raster_files.begin();
304 
305  std::size_t i = 0;
306 
307  boost::timer::cpu_timer timer;
308 
309  while(it != raster_files.end())
310  {
311  const std::string& raster_file = it->second;
312 
314 
315  (*rasters)[i] = raster;
316 
317  ++it;
318  ++i;
319  }
320 
321  std::string ret_val = timer.format();
322  std::cout << "tile dataset opened in: " << ret_val << std::endl;
323 
324  return (i != 0) ? sync_cache_from_rasters(*rasters, col, row) : 0;
325 }
326 
327 inline unsigned char* modis_dataset::impl::sync_cache_from_blocks(const std::vector<unsigned char*>& blocks,
328  unsigned int col,
329  unsigned int row) const
330 {
331  unsigned int tile_col = col % m_modis_tile_w;
332  unsigned int tile_row = row % m_modis_tile_h;
333 
334  unsigned int offset = (tile_col % m_blk_w + ((tile_row % m_blk_h) * m_blk_w)) * m_pixel_data_type_size;
335 
336  unsigned char* data = 0;
337 
338  if(m_pixel_cache->is_full())
339  data = m_pixel_cache->pop();
340  else
341  data = new unsigned char[m_times.size() * m_pixel_data_type_size];
342 
343  m_extract_pixel_data(blocks, offset, data);
344 
345  boost::uint64_t id = static_cast<boost::uint64_t>(row) *
346  static_cast<boost::uint64_t>(m_grid->getNumberOfColumns()) +
347  static_cast<boost::uint64_t>(col);
348 
349  m_pixel_cache->push(id, data);
350 
351  return data;
352 }
353 
354 inline unsigned char* modis_dataset::impl::sync_cache_from_rasters(const std::vector<te::rst::Raster*>& rasters,
355  unsigned int col,
356  unsigned int row) const
357 {
358  assert(rasters.size() == m_times.size());
359 
360  boost::uint64_t tile_col = col % m_modis_tile_w;
361  boost::uint64_t tile_row = row % m_modis_tile_h;
362 
363  boost::uint64_t tile_block_x = tile_col / m_blk_w;
364  boost::uint64_t tile_block_y = tile_row / m_blk_h;
365 
366  boost::uint64_t v = row / m_modis_tile_h;
367  boost::uint64_t h = col / m_modis_tile_w;
368 
369  std::vector<unsigned char*>* blocks = 0;
370 
371  if(m_block_cache->is_full())
372  blocks = m_block_cache->pop();
373  else
374  blocks = alloc_blocks();
375 
376  extract_block_data(*blocks, rasters, tile_block_x, tile_block_y);
377 
378  boost::uint64_t id = (v * m_tot_blocks_in_x) +
379  (h * m_nblks_per_tile) +
380  (tile_block_y * m_nblks_x + tile_block_x);
381 
382  m_block_cache->push(id, blocks);
383 
384  return sync_cache_from_blocks(*blocks, col, row);
385 }
386 
387 inline std::vector<unsigned char*>* modis_dataset::impl::alloc_blocks() const
388 {
389  const std::size_t nblocks = m_times.size();
390 
391  std::vector<unsigned char*>* blocks = new std::vector<unsigned char*>(nblocks);
392 
393  for(std::size_t i = 0; i != nblocks; ++i)
394  {
395  unsigned char* block_data = new unsigned char[m_blk_size];
396 
397  (*blocks)[i] = block_data;
398  }
399 
400  return blocks;
401 }
402 
403 inline void modis_dataset::impl::extract_block_data(std::vector<unsigned char*>& blocks,
404  const std::vector<te::rst::Raster*>& rasters,
405  unsigned int block_x,
406  unsigned int block_y) const
407 {
408  assert(blocks.size() == rasters.size());
409  assert(blocks.size() == m_times.size());
410 
411  const std::size_t nrasters = rasters.size();
412 
413  for(std::size_t i = 0; i != nrasters; ++i)
414  {
415  te::rst::Raster* raster = rasters[i];
416 
417  unsigned char* block_data = blocks[i];
418 
419  assert(raster->getNumberOfBands() == 1);
420 
421  raster->getBand(0)->read(block_x, block_y, block_data);
422  }
423 }
424 
426 {
427  if(m_tile_idx->empty() || m_tile_idx->begin()->second.empty())
428  return;
429 
430  const std::string& sample_file = m_tile_idx->begin()->second.begin()->second;
431 
433 
434  m_blk_w = raster->getBand(0)->getProperty()->m_blkw;
435  m_blk_h = raster->getBand(0)->getProperty()->m_blkh;
436 
437  m_nblks_x = raster->getBand(0)->getProperty()->m_nblocksx;
438  m_nblks_y = raster->getBand(0)->getProperty()->m_nblocksy;
439 
441 
442  m_value_data_type = raster->getBand(0)->getProperty()->getType();
443 
445 
447 
448  m_modis_tile_w = raster->getNumberOfColumns();
449  m_modis_tile_h = raster->getNumberOfRows();
450 }
451 
453 {
454  if(m_tile_idx->empty() || m_tile_idx->begin()->second.empty())
455  return;
456 
457  unsigned int min_h = std::numeric_limits<unsigned int>::max();
458  unsigned int min_v = std::numeric_limits<unsigned int>::max();
459  unsigned int max_h = std::numeric_limits<unsigned int>::min();
460  unsigned int max_v = std::numeric_limits<unsigned int>::min();
461 
462  te::gm::Envelope modis_extent;
463 
464 // iterate over the first raster of each tile
465  std::map <std::string, std::map <std::string, std::string > >::const_iterator it = m_tile_idx->begin();
466 
467  while(it != m_tile_idx->end())
468  {
469  const std::string& hv = it->first;
470 
471  const std::map <std::string, std::string >& rasters_of_a_tile = it->second;
472 
473  if(rasters_of_a_tile.empty())
474  {
475  ++it;
476  continue;
477  }
478  else
479  {
480  unsigned int h = boost::lexical_cast<unsigned int>(hv.substr(1, 2));
481  unsigned int v = boost::lexical_cast<unsigned int>(hv.substr(4, 2));
482 
483  if(h < min_h)
484  min_h = h;
485 
486  if(v < min_v)
487  min_v = v;
488 
489  if(h > max_h)
490  max_h = h;
491 
492  if(v > max_v)
493  max_v = v;
494 
495  const std::string& raster_file = rasters_of_a_tile.begin()->second;
496 
498 
499  modis_extent.Union(*(raster->getGrid()->getExtent()));
500 
501  ++it;
502  }
503  }
504 
505  m_ntiles_x = max_h - min_h + 1;
506  m_ntiles_y = max_v - min_v + 1;
507 
508  unsigned int ncols = (max_h - min_h + 1) * m_modis_tile_w;
509  unsigned int nrows = (max_v - min_v + 1) * m_modis_tile_h;
510 
511  m_grid = new te::rst::Grid(ncols, nrows, new te::gm::Envelope(modis_extent));
512 
513  m_modis_tile_h_offset = min_h;
514  m_modis_tile_v_offset = min_v;
515 }
516 
518 {
519  std::set<std::string> all_times;
520 
521  std::map <std::string, std::map <std::string, std::string > >::const_iterator hv_it = m_tile_idx->begin();
522 
523  while(hv_it != m_tile_idx->end())
524  {
525  std::map <std::string, std::string>::const_iterator it = hv_it->second.begin();
526 
527  while(it != hv_it->second.end())
528  {
529  //if(!all_times.find(it->first))
530  all_times.insert(it->first);
531 
532  ++it;
533  }
534 
535  ++hv_it;
536  }
537 
538  std::set<std::string>::const_iterator time_it = all_times.begin();
539 
540  while(time_it != all_times.end())
541  {
542  m_times.push_back(boost::gregorian::from_string(*time_it));
543 
544  ++time_it;
545  }
546 }
547 
548 modis_dataset::modis_dataset(const std::map <std::string, std::map <std::string, std::string > >& tile_idx,
549  const std::string subdataset_prefix,
550  const std::string subdataset_suffix,
551  std::size_t max_pixel_cache_size,
552  std::size_t max_block_cache_size,
553  std::size_t max_raster_cache_size)
554  : m_pimpl(0)
555 {
556  m_pimpl = new impl(tile_idx, subdataset_prefix, subdataset_suffix,
557  max_pixel_cache_size, max_block_cache_size, max_raster_cache_size);
558 }
559 
561 {
562  delete m_pimpl;
563 }
564 
565 void modis_dataset::query(const double& longitude, const double& latitude,
566  const unsigned char** values,
567  const std::vector<boost::gregorian::date>** times) const
568 {
569  m_pimpl->query(longitude, latitude, values, times);
570 }
571 
573 {
574  return m_pimpl->data_type();
575 }
576 
578 {
579  return m_pimpl->grid();
580 }
581 
582 
583 
const te::rst::Grid * grid() const
unsigned int m_modis_tile_w
fifo_cache< unsigned char > * m_pixel_cache
std::string m_subdataset_suffix
int data_type() const
te::rst::Grid * m_grid
const std::map< std::string, std::map< std::string, std::string > > * m_tile_idx
This file contains include headers for TerraLib Spatial Reference System module.
impl(const std::map< std::string, std::map< std::string, std::string > > &tile_idx, const std::string subdataset_prefix, const std::string subdataset_suffix, std::size_t max_pixel_cache_size, std::size_t max_block_cache_size, std::size_t max_raster_cache_size)
T * pop()
Definition: fifo_cache.h:63
unsigned int m_nblks_x
unsigned int m_nblks_y
bool is_full() const
Definition: fifo_cache.h:58
unsigned int m_blk_size
const te::rst::Grid * grid() const
unsigned int m_blk_w
int data_type() const
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
void query(const double &longitude, const double &latitude, const unsigned char **values, const std::vector< boost::gregorian::date > **times) const
void geoToGrid(const double &x, const double &y, double &col, double &row) const
Get the grid point associated to a spatial location.
unsigned int m_nblks_per_tile
unsigned char * sync_cache_from_rasters(const std::vector< te::rst::Raster * > &rasters, unsigned int col, unsigned int row) const
unsigned char * check_in_disk(unsigned int col, unsigned int row) const
void(* extract_pixel_data_fnct_t)(const std::vector< unsigned char * > &, unsigned int, unsigned char *)
Definition: block_utils.h:7
unsigned int m_blk_h
fifo_cache< std::vector< te::rst::Raster * > > * m_raster_cache
boost::shared_ptr< Raster > RasterPtr
std::vector< unsigned char * > * alloc_blocks() const
An Envelope defines a 2D rectangular region.
An abstract class for raster data strucutures.
unsigned char * check_in_raster_cache(unsigned int col, unsigned int row) const
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
void set_extract_pixel_data_strategy(extract_pixel_data_fnct_t *f, int data_type)
Definition: block_utils.cpp:13
unsigned int m_tot_blocks_in_x
unsigned int getNumberOfColumns() const
Returns the grid number of columns.
std::complex< double > times(std::complex< double > lhs, std::complex< double > rhs)
void extract_block_data(std::vector< unsigned char * > &blocks, const std::vector< te::rst::Raster * > &rasters, unsigned int block_x, unsigned int block_y) const
const T * data(boost::uint64_t id) const
Definition: fifo_cache.h:51
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
te::srs::Converter * m_converter
unsigned int m_ntiles_x
std::string m_subdataset_prefix
TERASTEREXPORT int GetPixelSize(int datatype)
Returns the byte size of a given datatype.
unsigned char * check_in_block_cache(unsigned int col, unsigned int row) const
std::vector< boost::gregorian::date > m_times
A Converter is responsible for the conversion of coordinates between different Coordinate Systems (CS...
Definition: Converter.h:53
virtual void read(int x, int y, void *buffer) const =0
It reads a data block to the specified buffer.
modis_dataset(const std::map< std::string, std::map< std::string, std::string > > &tile_idx, const std::string subdataset_prefix, const std::string subdataset_suffix, std::size_t max_pixel_cache_size=2, std::size_t max_block_cache_size=1, std::size_t max_raster_cache_size=1)
unsigned int m_ntiles_y
unsigned char * sync_cache_from_blocks(const std::vector< unsigned char * > &blocks, unsigned int col, unsigned int row) const
unsigned int m_modis_tile_h
fifo_cache< std::vector< unsigned char * > > * m_block_cache
This file contains include headers for the Vector Geometry model of TerraLib.
list rasters
Definition: compose.py:3
A rectified grid is the spatial support for raster data.
Definition: raster/Grid.h:68
void query(const double &longitude, const double &latitude, const unsigned char **values, const std::vector< boost::gregorian::date > **times) const
unsigned int col
unsigned int m_modis_tile_h_offset
void push(boost::uint64_t id, T *data)
Definition: fifo_cache.h:77
static Raster * open(const std::map< std::string, std::string > &rinfo, te::common::AccessPolicy p=te::common::RAccess)
It opens a raster with the given parameters and default raster driver.
extract_pixel_data_fnct_t m_extract_pixel_data
unsigned int m_modis_tile_v_offset