1 #ifndef bstm_ingest_boxm2_scene_function_hxx_
2 #define bstm_ingest_boxm2_scene_function_hxx_
3 
4 #include "bstm_ingest_boxm2_scene_function.h"
5 
6 //#define ALPHA_SCALING
7 #define DEBUG
8 
9 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
10 bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::
bstm_ingest_boxm2_scene_function(bstm_block * blk,bstm_time_block * blk_t,std::map<std::string,bstm_data_base * > & datas,boxm2_block * boxm2_blk,std::map<std::string,boxm2_data_base * > & boxm2_datas,double local_time,double p_threshold,double app_threshold)11     bstm_ingest_boxm2_scene_function(
12         bstm_block *blk,
13         bstm_time_block *blk_t,
14         std::map<std::string, bstm_data_base *> &datas,
15         boxm2_block *boxm2_blk,
16         std::map<std::string, boxm2_data_base *> &boxm2_datas,
17         double local_time,
18         double p_threshold,
19         double app_threshold) {
20   p_threshold_ = p_threshold;
21   app_threshold_ = app_threshold;
22 
23   init_data(blk, blk_t, datas, boxm2_blk, boxm2_datas, local_time);
24   conform();
25   ingest();
26 }
27 
28 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
init_data(bstm_block * blk,bstm_time_block * blk_t,std::map<std::string,bstm_data_base * > & datas,boxm2_block * boxm2_blk,std::map<std::string,boxm2_data_base * > & boxm2_datas,double local_time)29 bool bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::init_data(
30     bstm_block *blk,
31     bstm_time_block *blk_t,
32     std::map<std::string, bstm_data_base *> &datas,
33     boxm2_block *boxm2_blk,
34     std::map<std::string, boxm2_data_base *> &boxm2_datas,
35     double local_time) {
36   local_time_ = local_time;
37 
38   // store block and pointer to uchar16 3d block
39   blk_ = blk;
40   blk_t_ = blk_t;
41   boxm2_blk_ = boxm2_blk;
42 
43   // store data buffers
44   for (std::map<std::string, bstm_data_base *>::const_iterator iter =
45            datas.begin();
46        iter != datas.end();
47        iter++) {
48     if (iter->first == bstm_data_traits<BSTM_ALPHA>::prefix("")) { // if alpha,
49       alpha_ =
50           (bstm_data_traits<BSTM_ALPHA>::datatype *)iter->second->data_buffer();
51     } else { // if app model
52       apm_model_ = (typename bstm_data_traits<APM_TYPE>::datatype *)
53                        iter->second->data_buffer();
54     }
55   }
56 
57   // get boxm2 data buffers
58   for (std::map<std::string, boxm2_data_base *>::const_iterator iter =
59            boxm2_datas.begin();
60        iter != boxm2_datas.end();
61        iter++) {
62     if (iter->first == boxm2_data_traits<BOXM2_ALPHA>::prefix("")) // if alpha,
63       boxm2_alpha_ = (boxm2_data_traits<BOXM2_ALPHA>::datatype *)
64                          iter->second->data_buffer();
65     else // if app model
66       boxm2_apm_model_ =
67           (typename boxm2_data_traits<BOXM2_APM_TYPE>::datatype *)
68               iter->second->data_buffer();
69   }
70 
71   // block max level
72   max_level_ = blk_->max_level();
73   max_level_t_ = blk_t_->max_level();
74 
75   // length of one side of a sub block
76   block_len_ = blk->sub_block_dim().x();
77 
78   // number of time trees
79   sub_block_num_t_ = blk_t_->sub_block_num();
80 
81   // USE rootlevel to determine MAX_INNER and MAX_CELLS
82   if (max_level_t_ == 1) {
83     std::cout << "Trying to refine scene with max level 1" << std::endl;
84     return true;
85   } else if (max_level_t_ == 2) {
86     MAX_INNER_CELLS_T_ = 1, MAX_CELLS_T_ = 3;
87   } else if (max_level_t_ == 3) {
88     MAX_INNER_CELLS_T_ = 3, MAX_CELLS_T_ = 7;
89   } else if (max_level_t_ == 4) {
90     MAX_INNER_CELLS_T_ = 7, MAX_CELLS_T_ = 15;
91   } else if (max_level_t_ == 5) {
92     MAX_INNER_CELLS_T_ = 15, MAX_CELLS_T_ = 31;
93   } else if (max_level_t_ == 6) {
94     MAX_INNER_CELLS_T_ = 31, MAX_CELLS_T_ = 63;
95   } else
96     std::cerr << "ERROR! No max_level_t_\n";
97 
98   // USE rootlevel to determine MAX_INNER and MAX_CELLS
99   if (max_level_ == 1) {
100     std::cout << "Trying to refine scene with max level 1" << std::endl;
101     return true;
102   } else if (max_level_ == 2) {
103     MAX_INNER_CELLS_ = 1, MAX_CELLS_ = 9;
104   } else if (max_level_ == 3) {
105     MAX_INNER_CELLS_ = 9, MAX_CELLS_ = 73;
106   } else if (max_level_ == 4) {
107     MAX_INNER_CELLS_ = 73, MAX_CELLS_ = 585;
108   } else
109     std::cerr << "ERROR! No max_level_\n";
110 
111   // for debugging
112   num_split_ = 0;
113 
114   return true;
115 }
116 
117 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
conform()118 bool bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::conform() {
119   boxm2_array_3d<uchar16> &trees = blk_->trees();
120   boxm2_array_3d<uchar16> boxm2_trees = boxm2_blk_->trees_copy();
121   uchar16 *trees_copy = new uchar16[trees.size()]; // copy of those trees
122   int *dataIndex = new int[trees.size()]; // data index for each new tree
123   int currIndex = 0;                      // curr tree being looked at
124   int dataSize = 0;                       // running sum of data size
125 
126   // 1. loop over each tree, refine it in place
127   boxm2_array_3d<uchar16>::iterator blk_iter;
128   boxm2_array_3d<uchar16>::const_iterator boxm2_blk_iter;
129   for (blk_iter = trees.begin(), boxm2_blk_iter = boxm2_trees.begin();
130        blk_iter != trees.end();
131        ++blk_iter, ++boxm2_blk_iter, ++currIndex) {
132     // 0. store data index for eahc tree.
133     dataIndex[currIndex] = dataSize;
134 
135     // 1. get current tree information
136     uchar16 tree = (*blk_iter);
137     boct_bit_tree curr_tree((unsigned char *)tree.data_block(), max_level_);
138 
139     uchar16 boxm2_tree = (*boxm2_blk_iter);
140     boct_bit_tree boxm2_curr_tree((unsigned char *)boxm2_tree.data_block(),
141                                   max_level_);
142 
143     // 2. make sure the bstm tree is as refined as boxm2 tree
144     boct_bit_tree refined_tree = this->conform_tree(curr_tree, boxm2_curr_tree);
145     int newSize = refined_tree.num_cells();
146 
147     // cache refined tree
148     std::memcpy(
149         trees_copy[currIndex].data_block(), refined_tree.get_bits(), 16);
150     dataSize += newSize;
151   }
152 
153   // 2. allocate new time blk of the appropriate size
154   bstm_block_id id = blk_->block_id();
155   bstm_block_metadata m_data;
156   m_data.init_level_t_ = blk_t_->init_level();
157   m_data.max_level_t_ = blk_t_->max_level();
158   m_data.sub_block_num_t_ = blk_t_->sub_block_num();
159   bstm_time_block *newTimeBlk =
160       new bstm_time_block(id, m_data, dataSize); // create empty time block
161 
162   boxm2_array_1d<uchar8> &new_time_trees =
163       newTimeBlk->time_trees(); // refined trees
164   // std::cout<<"Number of new time trees: "<<  new_time_trees.size() -
165   // blk_t_->time_trees().size() <<std::endl;
166 
167   // allocate buffer to hold depth differences, one difference per time tree
168   // will be used to scale alpha later on
169   char *depth_diff = new char[new_time_trees.size()];
170   std::memset(
171       depth_diff, 0, sizeof(char) * new_time_trees.size()); // zero out buffer
172 
173   // 3. loop through trees again, putting the time trees in the right place
174   int newInitCount = 0;
175   currIndex = 0;
176   for (blk_iter = trees.begin(); blk_iter != trees.end();
177        ++blk_iter, ++currIndex) {
178     // 1. get current tree information
179     uchar16 tree = (*blk_iter);
180     boct_bit_tree old_tree((unsigned char *)tree.data_block(), max_level_);
181 
182     // 2. refine tree locally (only updates refined_tree and returns new tree
183     // size)
184     boct_bit_tree refined_tree(
185         (unsigned char *)trees_copy[currIndex].data_block(), max_level_);
186 
187     // 2.5 pack data bits into refined tree
188     // store data index in bits [10, 11, 12, 13] ;
189     int root_index = dataIndex[currIndex];
190     refined_tree.set_data_ptr(root_index, false); // is not random
191 
192     // 3. swap data from old location to new location
193     newInitCount +=
194         this->move_time_trees(old_tree, refined_tree, newTimeBlk, depth_diff);
195 
196     // 4. store old tree in new tree, swap data out
197     std::memcpy(blk_iter, refined_tree.get_bits(), 16);
198   }
199 
200   delete[] dataIndex;
201   delete[] trees_copy;
202 
203   // 4.  loop over time trees to calculate the size of new data blocks
204   //    keep index of data sizes, but don't save into them just yet
205   dataIndex = new int[new_time_trees.size()]; // data index for each new tree
206   currIndex = 0;                              // curr tree being looked at
207   dataSize = 0;                               // running sum of data size
208   boxm2_array_1d<uchar8>::iterator time_trees_iter;
209   for (time_trees_iter = new_time_trees.begin();
210        time_trees_iter != new_time_trees.end();
211        ++time_trees_iter, ++currIndex) {
212     // 0. store data index for each tree.
213     dataIndex[currIndex] = dataSize;
214 
215     // 1. get refined tree
216     bstm_time_tree new_time_tree(
217         (unsigned char *)(*time_trees_iter).data_block(), max_level_t_);
218 
219     // 2. save its new size
220     int newSize = new_time_tree.num_leaves(); // number of leaves, not all
221                                               // cells.
222     dataSize += newSize;
223   }
224 
225   // 5. alloc new data buffers with appropriate size
226   bstm_data_base *newA = new bstm_data_base(
227       new char[dataSize * bstm_data_traits<BSTM_ALPHA>::datasize()],
228       dataSize *bstm_data_traits<BSTM_ALPHA>::datasize(),
229       id);
230 
231   bstm_data_base *newM = new bstm_data_base(
232       new char[dataSize * bstm_data_traits<APM_TYPE>::datasize()],
233       dataSize *bstm_data_traits<APM_TYPE>::datasize(),
234       id);
235 
236   bstm_data_traits<BSTM_ALPHA>::datatype *alpha_cpy =
237       (bstm_data_traits<BSTM_ALPHA>::datatype *)newA->data_buffer();
238   typename bstm_data_traits<APM_TYPE>::datatype *mog_cpy =
239       (typename bstm_data_traits<APM_TYPE>::datatype *)newM->data_buffer();
240 
241   // 6. copy data from old data to new buffers
242   currIndex = 0;
243   for (time_trees_iter = new_time_trees.begin();
244        time_trees_iter != new_time_trees.end();
245        ++time_trees_iter, ++currIndex) {
246     // 1. get refined tree
247     bstm_time_tree new_time_tree(
248         (unsigned char *)(*time_trees_iter).data_block(), max_level_t_);
249 
250     // 2. get data pointer
251     int old_data_ptr = new_time_tree.get_data_ptr();
252     int new_data_ptr = dataIndex[currIndex];
253 
254     // 3. copy data using old ptr to new data buffers
255     std::memcpy(
256         &(alpha_cpy[new_data_ptr]),
257         &(alpha_[old_data_ptr]),
258         bstm_data_traits<BSTM_ALPHA>::datasize() *
259             new_time_tree.num_leaves()); // number of leaves, not all cells.
260     std::memcpy(
261         &(mog_cpy[new_data_ptr]),
262         &(apm_model_[old_data_ptr]),
263         bstm_data_traits<APM_TYPE>::datasize() *
264             new_time_tree.num_leaves()); // number of leaves, not all cells.
265 
266 // scale alpha data using the depth they were copied from
267 // to be consistent.
268 #ifdef ALPHA_SCALING
269     if (depth_diff[currIndex] > 0)
270       for (int i = 0; i < new_time_tree.num_cells(); i++)
271         alpha_cpy[new_data_ptr + i] *= float(1 << (int)depth_diff[currIndex]);
272 #endif
273 
274     // 4. correct data ptr
275     new_time_tree.set_data_ptr(dataIndex[currIndex]);
276 
277     // 5. save it back
278     std::memcpy(time_trees_iter, new_time_tree.get_bits(), TT_NUM_BYTES);
279   }
280 
281   delete[] dataIndex;
282   delete[] depth_diff;
283 
284   // 7. update cache, replace time trees
285   bstm_cache_sptr cache = bstm_cache::instance();
286   cache->replace_time_block(id, newTimeBlk);
287   cache->replace_data_base(id, bstm_data_traits<BSTM_ALPHA>::prefix(), newA);
288   cache->replace_data_base(id, bstm_data_traits<APM_TYPE>::prefix(), newM);
289 
290   blk_t_ = newTimeBlk;
291   alpha_ = alpha_cpy;
292   apm_model_ = mog_cpy;
293 
294   return true;
295 }
296 
297 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
move_time_trees(boct_bit_tree & unrefined_tree,boct_bit_tree & refined_tree,bstm_time_block * newTimeBlk,char * depth_diff)298 int bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::move_time_trees(
299     boct_bit_tree &unrefined_tree,
300     boct_bit_tree &refined_tree,
301     bstm_time_block *newTimeBlk,
302     char *depth_diff) {
303   int newSize = refined_tree.num_cells();
304 
305   // zip through each leaf cell and
306   int oldDataPtr = unrefined_tree.get_data_ptr(false);
307   int newDataPtr = refined_tree.get_data_ptr(false);
308   int newInitCount = 0;
309   int cellsMoved = 0;
310 
311   for (int j = 0; j < MAX_CELLS_ && cellsMoved < newSize; ++j) {
312     // if parent bit is 1, then you're a valid cell
313     int pj = unrefined_tree.parent_index(j); // Bit_index of parent bit
314     bool validCellOld = (j == 0) || unrefined_tree.bit_at(pj);
315     bool validCellNew = (j == 0) || refined_tree.bit_at(pj);
316     if (validCellOld && validCellNew) {
317       // move data to new location
318 
319       boxm2_array_1d<vnl_vector_fixed<unsigned char, 8> > old_time_trees =
320           blk_t_->get_cell_all_tt(oldDataPtr); // get all tt from prev. loc
321       // newTimeBlk->set_cell_all_tt(newDataPtr,old_time_trees); //set all tt to
322       // new loc
323 
324       if (!refined_tree.is_leaf(j)) // if the time trees being copied belong to
325                                     // an inner cell, erase their time trees
326       {
327         vnl_vector_fixed<unsigned char, 8> *erased_old_time_trees =
328             new vnl_vector_fixed<unsigned char, 8>[sub_block_num_t_];
329         for (unsigned int t_idx = 0; t_idx < sub_block_num_t_; ++t_idx) {
330           bstm_time_tree tmp_tree(
331               old_time_trees[t_idx]
332                   .data_block()); // create tree by copying the tree data
333           tmp_tree.erase_cells(); // erase all cells except for root.
334           erased_old_time_trees[t_idx].set(
335               tmp_tree.get_bits()); // copy to erased_old_time_trees
336         }
337         newTimeBlk->set_cell_all_tt(
338             newDataPtr,
339             boxm2_array_1d<vnl_vector_fixed<unsigned char, 8> >(
340                 sub_block_num_t_,
341                 erased_old_time_trees)); // set all tt to new loc
342         delete[] erased_old_time_trees;
343       } else // if the time trees being copied belong to a leaf, copy them as
344              // they are.
345         newTimeBlk->set_cell_all_tt(newDataPtr,
346                                     old_time_trees); // set all tt to new loc
347 
348       // increment
349       ++oldDataPtr;
350       ++newDataPtr;
351       ++cellsMoved;
352     }
353     // case where it's a new leaf...
354     else if (validCellNew) {
355       // find parent in old tree
356       int valid_parent_bit = pj;
357       while (
358           valid_parent_bit != 0 &&
359           !unrefined_tree.bit_at(unrefined_tree.parent_index(valid_parent_bit)))
360         valid_parent_bit = unrefined_tree.parent_index(valid_parent_bit);
361 
362       int parent_dataPtr =
363           unrefined_tree.get_data_index(valid_parent_bit, false);
364 
365       // move root data to new location
366       boxm2_array_1d<vnl_vector_fixed<unsigned char, 8> > old_time_trees =
367           blk_t_->get_cell_all_tt(parent_dataPtr); // get all tt from root loc
368       newTimeBlk->set_cell_all_tt(
369           newDataPtr, old_time_trees); // set all tt to new loc(child)
370 
371       // save depth differences
372       for (unsigned int i = 0; i < sub_block_num_t_; ++i)
373         depth_diff[newDataPtr + i] =
374             char(refined_tree.depth_at(j) -
375                  unrefined_tree.depth_at(valid_parent_bit));
376 
377       // update new data pointer
378       ++newDataPtr;
379       ++newInitCount;
380       ++cellsMoved;
381     }
382   }
383 
384   return newInitCount;
385 }
386 
387 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
388 boct_bit_tree
conform_tree(boct_bit_tree curr_tree,boct_bit_tree boxm2_curr_tree)389 bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::conform_tree(
390     boct_bit_tree curr_tree, boct_bit_tree boxm2_curr_tree) {
391   boct_bit_tree refined_tree(curr_tree.get_bits(),
392                              max_level_); // initialize tree to return
393 
394   for (int i = 0; i < MAX_INNER_CELLS_;
395        ++i) //(iterate through the max number of inner cells)
396     if (boxm2_curr_tree.bit_at(i) == 1 &&
397         refined_tree.bit_at(i) ==
398             0) // if boxm2 cell is divided, also divide bstm cell
399       refined_tree.set_bit_at(i, true);
400 
401   return refined_tree;
402 }
403 
404 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
ingest()405 bool bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::ingest() {
406   // loop over each tree in blk and boxm2_blk.
407   //--loop over each cell in the bstm tree
408   //----loop over cell's time trees.
409   //------if time tree does contain local_time,
410   //--------refine time tree(boxm2 dataptr, time tree)
411   //----keep record of the datasize for alpha, mog, numobs etc.
412 
413   const boxm2_array_3d<uchar16> &trees = blk_->trees();
414   const boxm2_array_3d<uchar16> &boxm2_trees = boxm2_blk_->trees();
415   boxm2_array_1d<uchar8> &time_trees =
416       blk_t_->time_trees(); // time trees to refine
417 
418   // make a copy of the time trees in blk_t_
419   uchar8 *time_tree_copy_buffer = new uchar8[time_trees.size()];
420   boxm2_array_1d<uchar8> time_trees_blk_copy(time_trees.size(),
421                                              time_tree_copy_buffer);
422   for (unsigned int i = 0; i < time_trees.size(); ++i)
423     std::memcpy(time_trees_blk_copy[i].data_block(),
424                 time_trees[i].data_block(),
425                 TT_NUM_BYTES);
426 
427   int *dataIndex = new int[time_trees.size()]; // data index for each new tree
428   int dataSize = 0;                            // running sum of data size
429   int currIndex = 0;
430 
431   // alloc new data buffers with appropriate size
432   bstm_block_id id = blk_->block_id();
433   bstm_cache_sptr cache = bstm_cache::instance();
434   bstm_data_base *change_buffer = cache->get_data_base_new(
435       id,
436       bstm_data_traits<BSTM_CHANGE>::prefix(),
437       blk_t_->tree_buff_length() * bstm_data_traits<BSTM_CHANGE>::datasize());
438 
439   change_array_ =
440       (bstm_data_traits<BSTM_CHANGE>::datatype *)change_buffer->data_buffer();
441 
442   int tree_index = 0;
443   boxm2_array_3d<uchar16>::const_iterator blk_iter, boxm2_blk_iter;
444   for (blk_iter = trees.begin(), boxm2_blk_iter = boxm2_trees.begin();
445        blk_iter != trees.end();
446        ++blk_iter, ++boxm2_blk_iter) {
447     // load boct trees from both blk and boxm2_blk
448     uchar16 tree = (*blk_iter);
449     boct_bit_tree curr_tree((unsigned char *)tree.data_block(), max_level_);
450 
451     uchar16 boxm2_tree = (*boxm2_blk_iter);
452     boct_bit_tree boxm2_curr_tree((unsigned char *)boxm2_tree.data_block(),
453                                   max_level_);
454 
455     int num_cells = curr_tree.num_cells();
456     int num_processed_cells = 0;
457     for (int i = 0; i < MAX_CELLS_ && num_processed_cells < num_cells; ++i) {
458       int pi = (i - 1) >> 3; // Bit_index of parent bit
459       if ((i == 0) || curr_tree.bit_at(pi)) {
460         bool is_leaf = !curr_tree.bit_at(i);
461 
462         // it might be that the bstm cell is further divided than the boxm2
463         // cell.
464         int i_boxm2 = i;
465         while (i_boxm2 != 0 &&
466                !boxm2_curr_tree.bit_at(boxm2_curr_tree.parent_index(i_boxm2)))
467           i_boxm2 = boxm2_curr_tree.parent_index(i_boxm2);
468 
469         // get data ptr for both trees
470         int bstm_data_offset = curr_tree.get_data_index(i, false);
471         int boxm2_data_offset = boxm2_curr_tree.get_data_index(i_boxm2, false);
472 
473         // refine all the time trees associated with curr cell.
474         this->refine_all_time_trees(bstm_data_offset,
475                                     boxm2_data_offset,
476                                     dataIndex,
477                                     currIndex,
478                                     dataSize,
479                                     curr_tree.depth_at(i),
480                                     boxm2_curr_tree.depth_at(i_boxm2),
481                                     is_leaf);
482         num_processed_cells++;
483       }
484     }
485     tree_index++;
486   }
487 
488   // std::cout << "New data size is " << dataSize << std::endl;
489 
490   bstm_data_base *newA = new bstm_data_base(
491       new char[dataSize * bstm_data_traits<BSTM_ALPHA>::datasize()],
492       dataSize *bstm_data_traits<BSTM_ALPHA>::datasize(),
493       id);
494   bstm_data_base *newM = new bstm_data_base(
495       new char[dataSize * bstm_data_traits<APM_TYPE>::datasize()],
496       dataSize *bstm_data_traits<APM_TYPE>::datasize(),
497       id);
498   bstm_data_traits<BSTM_ALPHA>::datatype *alpha_cpy =
499       (bstm_data_traits<BSTM_ALPHA>::datatype *)newA->data_buffer();
500   typename bstm_data_traits<APM_TYPE>::datatype *apm_cpy =
501       (typename bstm_data_traits<APM_TYPE>::datatype *)newM->data_buffer();
502 
503   // loop over each tree in blk and boxm2_blk.
504   //--loop over each time tree
505   //----copy everything from old tree's data
506   //----except for the current cell, copy that from boxm2 data.
507   currIndex = 0;
508   int newInitCount = 0;
509 
510   for (blk_iter = trees.begin(), boxm2_blk_iter = boxm2_trees.begin();
511        blk_iter != trees.end();
512        ++blk_iter, ++boxm2_blk_iter) {
513     // load boct trees from both blk and boxm2_blk
514     uchar16 tree = (*blk_iter);
515     boct_bit_tree curr_tree((unsigned char *)tree.data_block(), max_level_);
516 
517     uchar16 boxm2_tree = (*boxm2_blk_iter);
518     boct_bit_tree boxm2_curr_tree((unsigned char *)boxm2_tree.data_block(),
519                                   max_level_);
520 
521     int num_cells = curr_tree.num_cells();
522     int num_processed_cells = 0;
523     for (int i = 0; i < MAX_CELLS_ && num_processed_cells < num_cells; ++i) {
524       int pi = (i - 1) >> 3; // Bit_index of parent bit
525       if ((i == 0) || curr_tree.bit_at(pi)) {
526         // it might be that the bstm cell is further divided than the boxm2
527         // cell.
528         int i_boxm2 = i;
529         while (i_boxm2 != 0 &&
530                !boxm2_curr_tree.bit_at(boxm2_curr_tree.parent_index(i_boxm2)))
531           i_boxm2 = boxm2_curr_tree.parent_index(i_boxm2);
532 
533         // get data ptr for both trees
534         int bstm_data_offset = curr_tree.get_data_index(i, false);
535         int boxm2_data_offset = boxm2_curr_tree.get_data_index(i_boxm2, false);
536 
537         int depth_diff =
538             curr_tree.depth_at(i) - boxm2_curr_tree.depth_at(i_boxm2);
539         newInitCount += move_all_time_trees_data(time_trees_blk_copy,
540                                                  bstm_data_offset,
541                                                  boxm2_data_offset,
542                                                  dataIndex,
543                                                  currIndex,
544                                                  alpha_cpy,
545                                                  apm_cpy,
546                                                  depth_diff);
547         num_processed_cells++;
548       }
549     }
550   }
551 
552   // std::cout<<"Number of new cells: "<<newInitCount<<std::endl;
553 
554   // replace databases
555   cache->replace_data_base(id, bstm_data_traits<BSTM_ALPHA>::prefix(), newA);
556   cache->replace_data_base(id, bstm_data_traits<APM_TYPE>::prefix(), newM);
557 
558   delete[] time_tree_copy_buffer;
559   delete[] dataIndex;
560 
561   return true;
562 }
563 
564 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
565 int bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::
move_all_time_trees_data(boxm2_array_1d<uchar8> & time_trees_blk_copy,int bstm_data_offset,int boxm2_data_offset,int * dataIndex,int & currIndex,bstm_data_traits<BSTM_ALPHA>::datatype * alpha_cpy,typename bstm_data_traits<APM_TYPE>::datatype * apm_cpy,int depth_diff)566     move_all_time_trees_data(
567         boxm2_array_1d<uchar8> &time_trees_blk_copy,
568         int bstm_data_offset,
569         int boxm2_data_offset,
570         int *dataIndex,
571         int &currIndex,
572         bstm_data_traits<BSTM_ALPHA>::datatype *alpha_cpy,
573         typename bstm_data_traits<APM_TYPE>::datatype *apm_cpy,
574         int depth_diff) {
575   // load original time trees
576   boxm2_array_1d<uchar8> time_trees_copy(
577       sub_block_num_t_,
578       &(time_trees_blk_copy[bstm_data_offset * sub_block_num_t_]));
579 
580   boxm2_array_1d<uchar8> time_trees_refined =
581       blk_t_->get_cell_all_tt(bstm_data_offset);
582 
583   // zip thru time trees
584   int newInitCount = 0;
585   for (unsigned int t = 0; t < time_trees_refined.size(); ++t) {
586     bstm_time_tree refined_tree(time_trees_refined[t].data_block(),
587                                 max_level_t_);
588     bstm_time_tree original_tree(time_trees_copy[t].data_block(), max_level_t_);
589 
590     // set the root data pointer of the refined tree
591     int root_index = dataIndex[currIndex];
592     refined_tree.set_data_ptr(root_index);
593 
594     newInitCount +=
595         this->move_data(original_tree, refined_tree, alpha_cpy, apm_cpy);
596 
597     if (t ==
598         blk_t_->tree_index(
599             local_time_)) // if this time tree contains the queried time
600     {
601       float cell_min, cell_max;
602       refined_tree.cell_range(
603           refined_tree.traverse(local_time_ - blk_t_->tree_index(local_time_)),
604           cell_min,
605           cell_max);
606       if (cell_min ==
607           local_time_ -
608               blk_t_->tree_index(local_time_)) { // if the current time is the
609                                                  // start of a cell in which new
610                                                  // data will be placed
611         this->place_curr_data(
612             refined_tree, boxm2_data_offset, alpha_cpy, apm_cpy, depth_diff);
613       }
614     }
615 
616     // make sure to write the refined bits to blk_t_
617     uchar8 refined_bits(refined_tree.get_bits());
618     blk_t_->set_cell_tt(bstm_data_offset, refined_bits, t);
619 
620     currIndex++;
621   }
622   return newInitCount;
623 }
624 
625 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
626 bool bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::
refine_all_time_trees(int bstm_data_offset,int boxm2_data_offset,int * dataIndex,int & currIndex,int & dataSize,int currDepth,int currDepth_boxm2,bool is_leaf)627     refine_all_time_trees(int bstm_data_offset,
628                           int boxm2_data_offset,
629                           int *dataIndex,
630                           int &currIndex,
631                           int &dataSize,
632                           int currDepth,
633                           int currDepth_boxm2,
634                           bool is_leaf) {
635   bool refined_any_time_tree = false;
636   // zip thru time trees
637   int newSize = 0;
638   boxm2_array_1d<uchar8> all_time_trees =
639       blk_t_->get_cell_all_tt(bstm_data_offset);
640   for (unsigned int t = 0; t < all_time_trees.size(); ++t) {
641     dataIndex[currIndex] = dataSize;
642 
643     bstm_time_tree tmp_tree(all_time_trees[t].data_block(), max_level_t_);
644     // if this time tree contains the queried time and it is a leaf.
645     // if not a leaf, don't bother refining its time tree to save space.
646     if (t == blk_t_->tree_index(local_time_) && is_leaf) {
647       bstm_time_tree refined_t_tree = this->refine_time_tree(tmp_tree,
648                                                              bstm_data_offset,
649                                                              boxm2_data_offset,
650                                                              currDepth,
651                                                              currDepth_boxm2);
652       uchar8 refined_bits(refined_t_tree.get_bits());
653       blk_t_->set_cell_tt(
654           bstm_data_offset, refined_bits, t); // save it in time block
655       newSize =
656           refined_t_tree.num_leaves(); // count up the number of cells needed
657     } else
658       newSize = tmp_tree.num_leaves(); // count up the number of cells needed
659 
660     if (tmp_tree.num_cells() != newSize)
661       refined_any_time_tree = true;
662 
663     dataSize += newSize;
664     currIndex++;
665   }
666   return refined_any_time_tree;
667 }
668 
669 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
670 void bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::
place_curr_data(bstm_time_tree & refined_tree,int boxm2_data_offset,bstm_data_traits<BSTM_ALPHA>::datatype * alpha_cpy,typename bstm_data_traits<APM_TYPE>::datatype * apm_cpy,int depth_diff)671     place_curr_data(bstm_time_tree &refined_tree,
672                     int boxm2_data_offset,
673                     bstm_data_traits<BSTM_ALPHA>::datatype *alpha_cpy,
674                     typename bstm_data_traits<APM_TYPE>::datatype *apm_cpy,
675                     int
676 #ifdef ALPHA_SCALING
677                         depth_diff
678 #endif
679                     ) {
680   float trees_local_time = local_time_ - blk_t_->tree_index(local_time_);
681   int new_ptr =
682       refined_tree.get_data_index(refined_tree.traverse(trees_local_time));
683 
684 #ifdef DEBUG
685   if (new_ptr == -1)
686     std::cerr << "ERROR, data index is -1\n";
687 #endif
688 
689   alpha_cpy[new_ptr] = boxm2_alpha_[boxm2_data_offset];
690   apm_cpy[new_ptr] = boxm2_apm_model_[boxm2_data_offset];
691 
692 #ifdef ALPHA_SCALING
693   alpha_cpy[new_ptr] *= float(
694       1 << (int)depth_diff); // scale alpha to be consistent with its depth.
695 #endif
696 }
697 
698 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
699 bstm_time_tree
refine_time_tree(const bstm_time_tree & input_tree,int bstm_data_offset,int boxm2_data_offset,int currDepth,int currDepth_boxm2)700 bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::refine_time_tree(
701     const bstm_time_tree &input_tree,
702     int bstm_data_offset,
703     int boxm2_data_offset,
704     int currDepth,
705     int currDepth_boxm2) {
706   // initialize tree to return
707   bstm_time_tree refined_tree(input_tree.get_bits(), max_level_t_);
708 
709   float trees_local_time = local_time_ - blk_t_->tree_index(local_time_);
710 
711   if (currDepth < currDepth_boxm2)
712     std::cout << "ERROR: boxm2 and bstm depths don't match!" << std::endl;
713 
714   // first, query for boxm2 data
715   double side_len_boxm2 = block_len_ / double(1 << currDepth_boxm2);
716   boxm2_data_traits<BOXM2_ALPHA>::datatype boxm2_curr_alpha =
717       boxm2_alpha_[boxm2_data_offset];
718   float boxm2_p = 1 - std::exp(-boxm2_curr_alpha * side_len_boxm2);
719   typename boxm2_data_traits<BOXM2_APM_TYPE>::datatype boxm2_mog =
720       boxm2_apm_model_[boxm2_data_offset];
721 
722   // and then bstm data
723   double side_len = block_len_ / double(1 << currDepth);
724   int data_offset =
725       refined_tree.get_data_index(refined_tree.traverse(trees_local_time));
726 
727 #ifdef DEBUG
728   if (data_offset == -1)
729     std::cerr << "ERROR, data index is -1!\n";
730 #endif
731 
732   bstm_data_traits<BSTM_ALPHA>::datatype alpha = alpha_[data_offset];
733   float p = 1 - std::exp(-alpha * side_len);
734   typename bstm_data_traits<APM_TYPE>::datatype mog = apm_model_[data_offset];
735 
736   // save change of probabilities
737   change_array_[bstm_data_offset] = std::fabs(boxm2_p - p);
738 
739   if (is_similar(p, mog, boxm2_p, boxm2_mog))
740     return refined_tree;
741   else // need to refine time tree
742   {
743     bool split_complete = false;
744     while (!split_complete) {
745       int curr_cell = refined_tree.traverse(trees_local_time);
746       int currDepth = refined_tree.depth_at(curr_cell);
747 
748       float cell_min, cell_max;
749       refined_tree.cell_range(curr_cell, cell_min, cell_max);
750       if (cell_min == trees_local_time) // found cell starting at queried time.
751         split_complete = true;          // we're done here.
752       else if (currDepth < TT_NUM_LVLS - 1) {
753         refined_tree.set_bit_at(curr_cell, true); // split curr_cell
754         ++num_split_t_;
755       } else // reached end of tree...
756         split_complete = true;
757     }
758 
759     return refined_tree;
760   }
761 }
762 
763 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
is_similar(float p,typename bstm_data_traits<APM_TYPE>::datatype mog,float boxm2_p,typename boxm2_data_traits<BOXM2_APM_TYPE>::datatype boxm2_mog)764 bool bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::is_similar(
765     float p,
766     typename bstm_data_traits<APM_TYPE>::datatype mog,
767     float boxm2_p,
768     typename boxm2_data_traits<BOXM2_APM_TYPE>::datatype boxm2_mog) {
769   return bstm_similarity_traits<APM_TYPE, BOXM2_APM_TYPE>::is_similar(
770       mog, boxm2_mog, p, boxm2_p, p_threshold_, app_threshold_);
771 }
772 
773 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
move_data(bstm_time_tree & unrefined_tree,bstm_time_tree & refined_tree,bstm_data_traits<BSTM_ALPHA>::datatype * alpha_cpy,typename bstm_data_traits<APM_TYPE>::datatype * apm_cpy)774 int bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::move_data(
775     bstm_time_tree &unrefined_tree,
776     bstm_time_tree &refined_tree,
777     bstm_data_traits<BSTM_ALPHA>::datatype *alpha_cpy,
778     typename bstm_data_traits<APM_TYPE>::datatype *apm_cpy) {
779   int newInitCount = 0;
780 
781   std::vector<int> new_leaves = refined_tree.get_leaf_bits();
782   std::vector<int> old_leaves = unrefined_tree.get_leaf_bits();
783 
784   for (int & new_leave : new_leaves) {
785     // get new data ptr
786     int newDataPtr = refined_tree.get_data_index(new_leave);
787 
788     // find out if this leaf exists in the unrefined tree as well
789     int pj = unrefined_tree.parent_index(new_leave); // Bit_index of parent bit
790     bool validCellOld = (new_leave == 0) || unrefined_tree.bit_at(pj);
791 
792     int oldDataPtr;
793     if (validCellOld) // if they both exist
794       oldDataPtr = unrefined_tree.get_data_index(new_leave);
795     else {
796       // find parent in old tree
797       int valid_parent_bit = pj;
798       while (
799           valid_parent_bit != 0 &&
800           !unrefined_tree.bit_at(unrefined_tree.parent_index(valid_parent_bit)))
801         valid_parent_bit = unrefined_tree.parent_index(valid_parent_bit);
802 
803       oldDataPtr = unrefined_tree.get_data_index(valid_parent_bit);
804 
805       // increment new cell count
806       newInitCount++;
807     }
808     // copy data
809     alpha_cpy[newDataPtr] = alpha_[oldDataPtr];
810     apm_cpy[newDataPtr] = apm_model_[oldDataPtr];
811   }
812   return newInitCount;
813 }
814 
815 // OLD DEPRECATED CODE
816 #if 0
817 
818 template <bstm_data_type APM_TYPE, boxm2_data_type BOXM2_APM_TYPE>
819 int bstm_ingest_boxm2_scene_function<APM_TYPE, BOXM2_APM_TYPE>::move_data(bstm_time_tree& unrefined_tree, bstm_time_tree& refined_tree,
820                                                                           bstm_data_traits<BSTM_ALPHA>::datatype*  alpha_cpy,
821                                                                           typename bstm_data_traits<APM_TYPE>::datatype * apm_cpy )
822 {
823   int newSize = refined_tree.num_cells();
824 
825   //zip through each leaf cell and
826   int oldDataPtr = unrefined_tree.get_data_ptr();
827   int newDataPtr = refined_tree.get_data_ptr();
828   int newInitCount = 0;
829   int cellsMoved = 0;
830   for (int j=0; j<MAX_CELLS_T_ && cellsMoved<newSize; ++j)
831   {
832     //--------------------------------------------------------------------
833     //4 Cases:
834     // - Old cell and new cell exist - transfer data over
835     // - new cell exists, old cell doesn't - create new occupancy based on depth
836     // - old cell exists, new cell doesn't - uh oh this is bad news
837     // - neither cell exists - do nothing and carry on
838     //--------------------------------------------------------------------
839     //if parent bit is 1, then you're a valid cell
840     int pj = unrefined_tree.parent_index(j);           //Bit_index of parent bit
841     bool validCellOld = (j==0) || unrefined_tree.bit_at(pj);
842     bool validCellNew = (j==0) || refined_tree.bit_at(pj);
843     if (validCellOld && validCellNew) {
844       //move root data to new location
845       alpha_cpy[newDataPtr]  = alpha_[oldDataPtr];
846       apm_cpy[newDataPtr]  = apm_model_[oldDataPtr];
847 
848       //increment
849       ++oldDataPtr;
850       ++newDataPtr;
851       ++cellsMoved;
852     }
853     //case where it's a new leaf...
854     else if (validCellNew) {
855       //find parent in old tree
856       int valid_parent_bit = pj;
857       while ( valid_parent_bit !=0 && !unrefined_tree.bit_at( unrefined_tree.parent_index(valid_parent_bit) ) )
858         valid_parent_bit = unrefined_tree.parent_index(valid_parent_bit);
859 
860       int parent_data_ptr = unrefined_tree.get_data_index(valid_parent_bit);
861 
862 #ifdef DEBUG
863   if (parent_data_ptr == -1)
864     std::cerr << "ERROR, data index is -1\n";
865 #endif
866 
867       alpha_cpy[newDataPtr]    = alpha_[ parent_data_ptr ];
868       apm_cpy[newDataPtr]      = apm_model_[parent_data_ptr];
869 
870       //update new data pointer
871       ++newDataPtr;
872       ++newInitCount;
873       ++cellsMoved;
874     }
875   }
876   return newInitCount;
877 }
878 #endif
879 
880 #endif // bstm_ingest_boxm2_scene_function_hxx_
881