From b83b05e2600f7f4f8a01525b4719958abb1cad2a Mon Sep 17 00:00:00 2001 From: iannellog Date: Sat, 3 Mar 2018 18:25:22 +0100 Subject: [PATCH] New features - path and name of metadata file of unstitched datasets (mdata.bin) can be changed using command line option --mdata_bin - loading of special cases of unstitched subvolumes has been optimized --- cmake/Version.cmake | 2 +- src/imagemanager/UnstitchedVolume.cpp | 565 +++++++++++++------------- src/imagemanager/VirtualVolume.h | 2 +- src/iomanager/ioplugins.h | 10 +- src/ui/CLI.cpp | 4 + src/ui/CLI.h | 2 + src/ui/main.cpp | 3 +- src/volumemanager/vmBlockVolume.cpp | 21 +- src/volumemanager/vmBlockVolume.h | 7 +- src/volumemanager/vmMCVolume.cpp | 7 + src/volumemanager/vmMCVolume.h | 5 +- src/volumemanager/vmStackedVolume.cpp | 30 +- src/volumemanager/vmStackedVolume.h | 7 +- src/volumemanager/vmVirtualStack.h | 2 + src/volumemanager/vmVirtualVolume.h | 7 +- 15 files changed, 367 insertions(+), 307 deletions(-) diff --git a/cmake/Version.cmake b/cmake/Version.cmake index dc3b89f6..4d0e67f8 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -1,6 +1,6 @@ set(TeraStitcher_VERSION_MAJOR 1) set(TeraStitcher_VERSION_MINOR 10) -set(TeraStitcher_VERSION_PATCH 11) +set(TeraStitcher_VERSION_PATCH 12) set(TeraStitcher_VERSION "${TeraStitcher_VERSION_MAJOR}.${TeraStitcher_VERSION_MINOR}.${TeraStitcher_VERSION_PATCH}") add_definitions( -DTERASTITCHER_MAJOR=${TeraStitcher_VERSION_MAJOR} ) diff --git a/src/imagemanager/UnstitchedVolume.cpp b/src/imagemanager/UnstitchedVolume.cpp index d87c911e..5b40daac 100644 --- a/src/imagemanager/UnstitchedVolume.cpp +++ b/src/imagemanager/UnstitchedVolume.cpp @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-03. Giulio. @ADDED special cases of buffer loading that can be optimized * 2018-01-23. Giulio. @ADDED check to set always the input format of a MultiVolume dataset as a non-interleaved input format * 2018-01-20. Giulio. @ADDED a check to avoid performing stitching if there is no intersection between the requested region and the selected matrix of tiles * 2018-01-18. Giulio. @CHANGED the initialization of the input plugin in the constructors @@ -549,121 +550,13 @@ real32* UnstitchedVolume::internal_loadSubvolume_to_real32(int &VV0,int &VV1, in sint64 height = V1 - V0; sint64 depth = D1 - D0; - // 2018-01-20. Giulio. Unused variables - //int slice_height = -1; - //int slice_width = -1; - //slice_height = (int)(slice_height == -1 ? height : slice_height); - //slice_width = (int)(slice_width == -1 ? width : slice_width); - - buffer = new iom::real_t[height*width*depth]; - if ( !buffer ) - throw iim::IOException(iom::strprintf("cannot allocate the buffer of float (%llu x %llu x %u x %llu = %llu bytes)", - height, width, depth, sizeof(iom::real_t), height*width*depth), __iom__current__function__); - - //for (int i=0; i V0 && HH0 < H1 && HH1 > H0 ) { // there is intesection: load data - //computing VH coordinates of all stripes - for(int row_index=stitcher->ROW_START; row_index<=stitcher->ROW_END; row_index++) - { - stripesCoords[row_index].up_left.V = stitcher->getStripeABS_V(row_index,true); - stripesCoords[row_index].up_left.H = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_H(); - stripesCoords[row_index].bottom_right.V = stitcher->getStripeABS_V(row_index,false); - stripesCoords[row_index].bottom_right.H = volume->getSTACKS()[row_index][stitcher->COL_END]->getABS_H()+volume->getStacksWidth(); - } - - // clear stripesCorners - for ( int i=0; igetN_ROWS(); i++ ) { - stripesCorners[i].ups.clear(); - stripesCorners[i].bottoms.clear(); - stripesCorners[i].merged.clear(); - } - - //computing stripes corners, i.e. corners that result from the overlap between each pair of adjacent stripes - for(int row_index=stitcher->ROW_START; row_index<=stitcher->ROW_END; row_index++) - { - stripe_corner tmp; - - //for first VirtualStack of every stripe - tmp.H = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_H(); - tmp.h = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_V()-stripesCoords[row_index].up_left.V; - tmp.up = true; - stripesCorners[row_index].ups.push_back(tmp); - - tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_V() - volume->getStacksHeight(); - tmp.up = false; - stripesCorners[row_index].bottoms.push_back(tmp); - - for(int col_index=stitcher->COL_START; col_indexCOL_END; col_index++) - { - if(volume->getSTACKS()[row_index][col_index]->getABS_V() < volume->getSTACKS()[row_index][col_index+1]->getABS_V()) - { - tmp.H = volume->getSTACKS()[row_index][col_index]->getABS_H() + volume->getStacksWidth(); - tmp.h = volume->getSTACKS()[row_index][col_index+1]->getABS_V() - stripesCoords[row_index].up_left.V; - tmp.up = true; - stripesCorners[row_index].ups.push_back(tmp); - - tmp.H = volume->getSTACKS()[row_index][col_index+1]->getABS_H(); - tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][col_index+1]->getABS_V() - volume->getStacksHeight(); - tmp.up = false; - stripesCorners[row_index].bottoms.push_back(tmp); - } - else - { - tmp.H = volume->getSTACKS()[row_index][col_index+1]->getABS_H(); - tmp.h = volume->getSTACKS()[row_index][col_index+1]->getABS_V() - stripesCoords[row_index].up_left.V; - tmp.up = true; - stripesCorners[row_index].ups.push_back(tmp); - - tmp.H = volume->getSTACKS()[row_index][col_index]->getABS_H()+volume->getStacksWidth(); - tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][col_index+1]->getABS_V() - volume->getStacksHeight(); - tmp.up = false; - stripesCorners[row_index].bottoms.push_back(tmp); - } - } - - //for last VirtualStack of every stripe (h is not set because it doesn't matter) - tmp.H = volume->getSTACKS()[row_index][stitcher->COL_END]->getABS_H() + volume->getStacksWidth(); - tmp.up = true; - stripesCorners[row_index].ups.push_back(tmp); - - tmp.up = false; - stripesCorners[row_index].bottoms.push_back(tmp); - } - - //ordered merging between ups and bottoms corners for every stripe - for(int row_index = 1; row_index<=(volume->getN_ROWS()-1); row_index++) - { - stripesCorners[row_index-1].merged.merge(stripesCorners[row_index-1].bottoms, compareCorners); - stripesCorners[row_index-1].merged.merge(stripesCorners[row_index ].ups, compareCorners); - } - - sint64 u_strp_bottom_displ; // bottom displacement of up stripe - sint64 d_strp_top_displ; // top displacement of down stripe - sint64 u_strp_top_displ; // top displacement of up stripe - sint64 d_strp_left_displ; - sint64 u_strp_left_displ; - sint64 d_strp_width; - sint64 u_strp_width; - sint64 dd_strp_top_displ; - sint64 u_strp_d_strp_overlap = 0; // overlap between up and down stripes; WARNING: check how initialize - sint64 h_up; - sint64 h_down; - sint64 h_overlap; - iom::real_t *buffer_ptr, *ustripe_ptr, *dstripe_ptr; - - iom::real_t* stripe_up=NULL, *stripe_down; //will contain up-stripe and down-stripe computed by calling 'getStripe' method - double angle; //angle between 0 and PI used to sample overlapping zone in [0,PI] - double delta_angle; //angle step - + //retrieving blending function iom::real_t (*blending)(double& angle, iom::real_t& pixel1, iom::real_t& pixel2); - //retrieving blending function if(blending_algo == S_SINUSOIDAL_BLENDING) blending = StackStitcher::sinusoidal_blending; else if(blending_algo == S_NO_BLENDING) @@ -673,197 +566,315 @@ real32* UnstitchedVolume::internal_loadSubvolume_to_real32(int &VV0,int &VV1, in else if(blending_algo == S_ENHANCED_NO_BLENDING) blending = StackStitcher::enhanced_no_blending; else - throw iim::IOException(iom::strprintf("unrecognized blending function"), __iom__current__function__); + throw iim::IOException(iom::strprintf("unrecognized blending function"), __iom__current__function__); - sint64 z = D0; // starting slice (offset is index 'k') - - // 2017-08-19. Giulio. @ADDED offsets on whole buffer to reduce the amount of data to be copied - // if 'delta' variables are zero the whole buffer is filled with data returned by getStripe method - sint64 subvol_V_top_delta = cb->getENABLED() ? 0 : VV0 - V0; //top V(ertical) offset of actual subvolume - sint64 subvol_V_bottom_delta = cb->getENABLED() ? 0 : V1 - VV1; //bottom V(ertical) offset of actual subvolume - - if ( subvol_V_top_delta < 0 ) { - iom::warning(iom::strprintf("V top offset negative: set to 0").c_str(), __iom__current__function__); - subvol_V_top_delta = 0; - } - if ( subvol_V_bottom_delta < 0 ) { - iom::warning(iom::strprintf("V bottom offset negative: set to 0").c_str(), __iom__current__function__); - subvol_V_bottom_delta = 0; - } - - for(sint64 k = 0; k < depth; k++) - { - //looping on all stripes + // 2018-03-03. Giulio. @ADDED special cases that can be optimized + if ( (stitcher->ROW_START == stitcher->ROW_END) && (stitcher->COL_START == stitcher->COL_END) ) { // special case: just one tile + buffer = volume->getSTACKS()[stitcher->ROW_START][stitcher->COL_START]->loadImageStack2(D0,D1-1,VV0, VV1, HH0, HH1); + volume->getSTACKS()[stitcher->ROW_START][stitcher->COL_START]->releaseImageStackOwnership(); // acquire buffer ownership + } + else if ( stitcher->ROW_START == stitcher->ROW_END ) { // special case: just one stripe + for(sint64 k = D0+0; k < D0+depth; k++) + { + if ( cb->getENABLED() ) + // since 'delta' variables are zero all returned data will be copied in the final buffer + buffer = stitcher->getStripe(stitcher->ROW_START,(int)k, restore_direction, stk_rst, blending_algo); + else + // only requested data are actually read into the returned buffer and will be copied into the final buffer + buffer = stitcher->getStripe2(stitcher->ROW_START,(int)k, VV0, VV1, HH0, HH1, restore_direction, stk_rst, blending_algo); + } + } + else { + buffer = new iom::real_t[height*width*depth]; + if ( !buffer ) + throw iim::IOException(iom::strprintf("cannot allocate the buffer of float (%llu x %llu x %u x %llu = %llu bytes)", + height, width, depth, sizeof(iom::real_t), height*width*depth), __iom__current__function__); + + memset(buffer,0,sizeof(iom::real_t)*height*width*depth); + + //computing VH coordinates of all stripes + for(int row_index=stitcher->ROW_START; row_index<=stitcher->ROW_END; row_index++) + { + stripesCoords[row_index].up_left.V = stitcher->getStripeABS_V(row_index,true); + stripesCoords[row_index].up_left.H = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_H(); + stripesCoords[row_index].bottom_right.V = stitcher->getStripeABS_V(row_index,false); + stripesCoords[row_index].bottom_right.H = volume->getSTACKS()[row_index][stitcher->COL_END]->getABS_H()+volume->getStacksWidth(); + } + + // clear stripesCorners + for ( int i=0; igetN_ROWS(); i++ ) { + stripesCorners[i].ups.clear(); + stripesCorners[i].bottoms.clear(); + stripesCorners[i].merged.clear(); + } + + //computing stripes corners, i.e. corners that result from the overlap between each pair of adjacent stripes for(int row_index=stitcher->ROW_START; row_index<=stitcher->ROW_END; row_index++) { - //loading down stripe - if(row_index==stitcher->ROW_START) stripe_up = NULL; - - // 2017-04-12. Giulio. @ADDED release of allocated buffers if an exception is raised in 'getStripe' (prevent further exceptions in the GUI version) - try { - // 2017-08-19. Giulio. @CHANGED the method reading only the actually requested data is invoked only if buffering is not enabled - if ( cb->getENABLED() ) - // since 'delta' variables are zero all returned data will be copied in the final buffer - stripe_down = stitcher->getStripe(row_index,(int)(z+k), restore_direction, stk_rst, blending_algo); + stripe_corner tmp; + + //for first VirtualStack of every stripe + tmp.H = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_H(); + tmp.h = volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_V()-stripesCoords[row_index].up_left.V; + tmp.up = true; + stripesCorners[row_index].ups.push_back(tmp); + + tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][stitcher->COL_START]->getABS_V() - volume->getStacksHeight(); + tmp.up = false; + stripesCorners[row_index].bottoms.push_back(tmp); + + for(int col_index=stitcher->COL_START; col_indexCOL_END; col_index++) + { + if(volume->getSTACKS()[row_index][col_index]->getABS_V() < volume->getSTACKS()[row_index][col_index+1]->getABS_V()) + { + tmp.H = volume->getSTACKS()[row_index][col_index]->getABS_H() + volume->getStacksWidth(); + tmp.h = volume->getSTACKS()[row_index][col_index+1]->getABS_V() - stripesCoords[row_index].up_left.V; + tmp.up = true; + stripesCorners[row_index].ups.push_back(tmp); + + tmp.H = volume->getSTACKS()[row_index][col_index+1]->getABS_H(); + tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][col_index+1]->getABS_V() - volume->getStacksHeight(); + tmp.up = false; + stripesCorners[row_index].bottoms.push_back(tmp); + } else - // only requested data are actually read into the returned buffer and will be copied into the final buffer - stripe_down = stitcher->getStripe2(row_index,(int)(z+k), VV0, VV1, HH0, HH1, restore_direction, stk_rst, blending_algo); + { + tmp.H = volume->getSTACKS()[row_index][col_index+1]->getABS_H(); + tmp.h = volume->getSTACKS()[row_index][col_index+1]->getABS_V() - stripesCoords[row_index].up_left.V; + tmp.up = true; + stripesCorners[row_index].ups.push_back(tmp); + + tmp.H = volume->getSTACKS()[row_index][col_index]->getABS_H()+volume->getStacksWidth(); + tmp.h = stripesCoords[row_index].bottom_right.V - volume->getSTACKS()[row_index][col_index+1]->getABS_V() - volume->getStacksHeight(); + tmp.up = false; + stripesCorners[row_index].bottoms.push_back(tmp); + } } - catch( iom::exception& exception) { - stitcher->volume->releaseBuffers(); - throw iom::exception(iom::exception(exception.what())); - } - - if(stripe_up) u_strp_bottom_displ = stripesCoords[row_index-1].bottom_right.V - V0; - d_strp_top_displ = stripesCoords[row_index ].up_left.V - V0; - if(stripe_up) u_strp_top_displ = stripesCoords[row_index-1].up_left.V - V0; - d_strp_left_displ = stripesCoords[row_index ].up_left.H - H0; - if(stripe_up) u_strp_left_displ = stripesCoords[row_index-1].up_left.H - H0; - d_strp_width = stripesCoords[row_index ].bottom_right.H - stripesCoords[row_index ].up_left.H; - if(stripe_up) u_strp_width = stripesCoords[row_index-1].bottom_right.H - stripesCoords[row_index-1].up_left.H; - if(stripe_up) u_strp_d_strp_overlap = u_strp_bottom_displ - d_strp_top_displ; - if(row_index!=stitcher->ROW_END) - dd_strp_top_displ = stripesCoords[row_index+1].up_left.V - V0; - h_up = h_down = u_strp_d_strp_overlap; - -/********************************************************************************************************************************************************************************************************** - -This comment assumes h_overlap >= 0 -The actual code manages also the case h_overlap < 0 (meaning that there are regions uncovered between the up stripe and the down stripe -The loop copies the down stripe onto the buffer merged with the overlapping zone of the up stripe - - - | index on whole buffer | index on up stripe |index on down stripe | - | | | | - ------- ----------------------------------------------- | u_strp_top_displ | | | - | | | | | - | | | | | - | | | | | - | already copied in previous cycle | | | | - | | | | | - / | | | | -up stripe - | | | | - \ -- ............................................... | d_strp_top_displ | (d_strp_top_displ - u_strp_top_displ) | | - | | first cycle (only up stripe) | | | | - | | ............................ | d_strp_top_displ+h_up | (d_strp_top_displ + h_up - u_strp_top_displ) | h_up | - | | OVERLAPPING ZONE second cycle (both stripes) | | | | - | | ---------------------------- | d_strp_top_displ+h_up+h_overlap | | h_up + h_overlap | - | | third cycle (only down stripe) | | | | - ---- / ----------------------------------------------- | d_strp_top_displ+h_up+h_overlap+h_down = u_strp_bottom_displ | (u_strp_bottom_displ - d_strp_top_displ) | | -down stripe - | | | | - \ | | | | - | NON OVERLAPPING ZONE | i | (i - d_strp_top_displ) | | - | | | | | - ---- | ___.___.___.___.___.___.___.___.___.___.___.___ | dd_strp_top_displ | | | - | | | | | | - | | - | -- ............................................... - | - | - / -dd stripe - - \ next stripe - | - | - | - | - | - ------- ___.___.___.___.___.___.___.___.___.___.___.___ - -**********************************************************************************************************************************************************************************************************/ - - // 2017-08-19. Giulio. @ADDED top offset on down stripe to reduce the amount of data to be copied - // subvol_V_top_delta = 0 -> d_strp_V_top_delta = 0 - sint64 d_strp_V_top_delta = (subvol_V_top_delta > d_strp_top_displ) ? (subvol_V_top_delta - d_strp_top_displ) : 0; + + //for last VirtualStack of every stripe (h is not set because it doesn't matter) + tmp.H = volume->getSTACKS()[row_index][stitcher->COL_END]->getABS_H() + volume->getStacksWidth(); + tmp.up = true; + stripesCorners[row_index].ups.push_back(tmp); + + tmp.up = false; + stripesCorners[row_index].bottoms.push_back(tmp); + } + + //ordered merging between ups and bottoms corners for every stripe + for(int row_index = 1; row_index<=(volume->getN_ROWS()-1); row_index++) + { + stripesCorners[row_index-1].merged.merge(stripesCorners[row_index-1].bottoms, compareCorners); + stripesCorners[row_index-1].merged.merge(stripesCorners[row_index ].ups, compareCorners); + } + + sint64 u_strp_bottom_displ; // bottom displacement of up stripe + sint64 d_strp_top_displ; // top displacement of down stripe + sint64 u_strp_top_displ; // top displacement of up stripe + sint64 d_strp_left_displ; + sint64 u_strp_left_displ; + sint64 d_strp_width; + sint64 u_strp_width; + sint64 dd_strp_top_displ; + sint64 u_strp_d_strp_overlap = 0; // overlap between up and down stripes; WARNING: check how initialize + sint64 h_up; + sint64 h_down; + sint64 h_overlap; + iom::real_t *buffer_ptr, *ustripe_ptr, *dstripe_ptr; + + iom::real_t* stripe_up=NULL, *stripe_down; //will contain up-stripe and down-stripe computed by calling 'getStripe' method + double angle; //angle between 0 and PI used to sample overlapping zone in [0,PI] + double delta_angle; //angle step + + sint64 z = D0; // starting slice (offset is index 'k') + + // 2017-08-19. Giulio. @ADDED offsets on whole buffer to reduce the amount of data to be copied + // if 'delta' variables are zero the whole buffer is filled with data returned by getStripe method + sint64 subvol_V_top_delta = cb->getENABLED() ? 0 : VV0 - V0; //top V(ertical) offset of actual subvolume + sint64 subvol_V_bottom_delta = cb->getENABLED() ? 0 : V1 - VV1; //bottom V(ertical) offset of actual subvolume + + if ( subvol_V_top_delta < 0 ) { + iom::warning(iom::strprintf("V top offset negative: set to 0").c_str(), __iom__current__function__); + subvol_V_top_delta = 0; + } + if ( subvol_V_bottom_delta < 0 ) { + iom::warning(iom::strprintf("V bottom offset negative: set to 0").c_str(), __iom__current__function__); + subvol_V_bottom_delta = 0; + } + + for(sint64 k = 0; k < depth; k++) + { + //looping on all stripes + for(int row_index=stitcher->ROW_START; row_index<=stitcher->ROW_END; row_index++) + { + //loading down stripe + if(row_index==stitcher->ROW_START) stripe_up = NULL; + + // 2017-04-12. Giulio. @ADDED release of allocated buffers if an exception is raised in 'getStripe' (prevent further exceptions in the GUI version) + try { + // 2017-08-19. Giulio. @CHANGED the method reading only the actually requested data is invoked only if buffering is not enabled + if ( cb->getENABLED() ) + // since 'delta' variables are zero all returned data will be copied in the final buffer + stripe_down = stitcher->getStripe(row_index,(int)(z+k), restore_direction, stk_rst, blending_algo); + else + // only requested data are actually read into the returned buffer and will be copied into the final buffer + stripe_down = stitcher->getStripe2(row_index,(int)(z+k), VV0, VV1, HH0, HH1, restore_direction, stk_rst, blending_algo); + } + catch( iom::exception& exception) { + stitcher->volume->releaseBuffers(); + throw iom::exception(iom::exception(exception.what())); + } + + if(stripe_up) u_strp_bottom_displ = stripesCoords[row_index-1].bottom_right.V - V0; + d_strp_top_displ = stripesCoords[row_index ].up_left.V - V0; + if(stripe_up) u_strp_top_displ = stripesCoords[row_index-1].up_left.V - V0; + d_strp_left_displ = stripesCoords[row_index ].up_left.H - H0; + if(stripe_up) u_strp_left_displ = stripesCoords[row_index-1].up_left.H - H0; + d_strp_width = stripesCoords[row_index ].bottom_right.H - stripesCoords[row_index ].up_left.H; + if(stripe_up) u_strp_width = stripesCoords[row_index-1].bottom_right.H - stripesCoords[row_index-1].up_left.H; + if(stripe_up) u_strp_d_strp_overlap = u_strp_bottom_displ - d_strp_top_displ; + if(row_index!=stitcher->ROW_END) + dd_strp_top_displ = stripesCoords[row_index+1].up_left.V - V0; + h_up = h_down = u_strp_d_strp_overlap; + + /********************************************************************************************************************************************************************************************************** + + This comment assumes h_overlap >= 0 + The actual code manages also the case h_overlap < 0 (meaning that there are regions uncovered between the up stripe and the down stripe + The loop copies the down stripe onto the buffer merged with the overlapping zone of the up stripe + + + | index on whole buffer | index on up stripe |index on down stripe | + | | | | + ------- ----------------------------------------------- | u_strp_top_displ | | | + | | | | | + | | | | | + | | | | | + | already copied in previous cycle | | | | + | | | | | + / | | | | + up stripe - | | | | + \ -- ............................................... | d_strp_top_displ | (d_strp_top_displ - u_strp_top_displ) | | + | | first cycle (only up stripe) | | | | + | | ............................ | d_strp_top_displ+h_up | (d_strp_top_displ + h_up - u_strp_top_displ) | h_up | + | | OVERLAPPING ZONE second cycle (both stripes) | | | | + | | ---------------------------- | d_strp_top_displ+h_up+h_overlap | | h_up + h_overlap | + | | third cycle (only down stripe) | | | | + ---- / ----------------------------------------------- | d_strp_top_displ+h_up+h_overlap+h_down = u_strp_bottom_displ | (u_strp_bottom_displ - d_strp_top_displ) | | + down stripe - | | | | + \ | | | | + | NON OVERLAPPING ZONE | i | (i - d_strp_top_displ) | | + | | | | | + ---- | ___.___.___.___.___.___.___.___.___.___.___.___ | dd_strp_top_displ | | | + | | | | | | + | | + | -- ............................................... + | + | + / + dd stripe - + \ next stripe + | + | + | + | + | + ------- ___.___.___.___.___.___.___.___.___.___.___.___ + + **********************************************************************************************************************************************************************************************************/ + + // 2017-08-19. Giulio. @ADDED top offset on down stripe to reduce the amount of data to be copied + // subvol_V_top_delta = 0 -> d_strp_V_top_delta = 0 + sint64 d_strp_V_top_delta = (subvol_V_top_delta > d_strp_top_displ) ? (subvol_V_top_delta - d_strp_top_displ) : 0; - //overlapping zone - if(row_index!=stitcher->ROW_START) - { - // 2017-08-19. Giulio. @ADDED top offset on up stripe to reduce the amount of data to be copied - // subvol_V_top_delta = 0 -> u_strp_V_top_delta = 0 - sint64 u_strp_V_top_delta = (subvol_V_top_delta > u_strp_top_displ) ? (subvol_V_top_delta - u_strp_top_displ) : 0; - - std::list::iterator cnr_i_next, cnr_i = stripesCorners[row_index-1].merged.begin(); - stripe_corner *cnr_left=&(*cnr_i), *cnr_right; - cnr_i++; - cnr_i_next = cnr_i; - cnr_i_next++; - - while( cnr_i != stripesCorners[row_index-1].merged.end()) - { - //computing h_up, h_overlap, h_down - cnr_right = &(*cnr_i); - if(cnr_i_next == stripesCorners[row_index-1].merged.end()) + //overlapping zone + if(row_index!=stitcher->ROW_START) + { + // 2017-08-19. Giulio. @ADDED top offset on up stripe to reduce the amount of data to be copied + // subvol_V_top_delta = 0 -> u_strp_V_top_delta = 0 + sint64 u_strp_V_top_delta = (subvol_V_top_delta > u_strp_top_displ) ? (subvol_V_top_delta - u_strp_top_displ) : 0; + + std::list::iterator cnr_i_next, cnr_i = stripesCorners[row_index-1].merged.begin(); + stripe_corner *cnr_left=&(*cnr_i), *cnr_right; + cnr_i++; + cnr_i_next = cnr_i; + cnr_i_next++; + + while( cnr_i != stripesCorners[row_index-1].merged.end()) { - h_up = cnr_left->up ? u_strp_d_strp_overlap : 0; - h_down = cnr_left->up ? 0 : u_strp_d_strp_overlap; - } - else - if(cnr_left->up) - h_up = cnr_left->h; + //computing h_up, h_overlap, h_down + cnr_right = &(*cnr_i); + if(cnr_i_next == stripesCorners[row_index-1].merged.end()) + { + h_up = cnr_left->up ? u_strp_d_strp_overlap : 0; + h_down = cnr_left->up ? 0 : u_strp_d_strp_overlap; + } else - h_down = cnr_left->h; + if(cnr_left->up) + h_up = cnr_left->h; + else + h_down = cnr_left->h; - h_overlap = u_strp_d_strp_overlap - h_up - h_down; + h_overlap = u_strp_d_strp_overlap - h_up - h_down; - //splitting overlapping zone in sub-regions along H axis - for(sint64 j= cnr_left->H - H0; j < cnr_right->H - H0; j++) - { - delta_angle = PI/(h_overlap-1); - angle = 0; + //splitting overlapping zone in sub-regions along H axis + for(sint64 j= cnr_left->H - H0; j < cnr_right->H - H0; j++) + { + delta_angle = PI/(h_overlap-1); + angle = 0; - //UP stripe zone - buffer_ptr = &buffer[k*height*width+std::max(d_strp_top_displ,subvol_V_top_delta)*width+j]; - ustripe_ptr = &stripe_up[std::max((d_strp_top_displ-u_strp_top_displ),u_strp_V_top_delta)*u_strp_width +j - u_strp_left_displ]; - for(sint64 i=std::max(d_strp_top_displ,subvol_V_top_delta); i(d_strp_top_displ+h_up+(h_overlap >= 0 ? 0 : h_overlap),height-subvol_V_bottom_delta); i++, buffer_ptr+=width, ustripe_ptr+= u_strp_width) - *buffer_ptr = *ustripe_ptr; - - //OVERLAPPING zone - buffer_ptr = &buffer[k*height*width+std::max((d_strp_top_displ+h_up),subvol_V_top_delta)*width+j]; - ustripe_ptr = &stripe_up[std::max((d_strp_top_displ+h_up-u_strp_top_displ),u_strp_V_top_delta)*u_strp_width +j - u_strp_left_displ]; - dstripe_ptr = &stripe_down[std::max((d_strp_top_displ+h_up-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width +j - d_strp_left_displ]; - for(sint64 i=std::max(d_strp_top_displ+h_up,subvol_V_top_delta); i(d_strp_top_displ+h_up+h_overlap,height-subvol_V_bottom_delta); i++, buffer_ptr+=width, ustripe_ptr+= u_strp_width, dstripe_ptr+=d_strp_width, angle+=delta_angle) - *buffer_ptr = blending(angle,*ustripe_ptr,*dstripe_ptr); - - //DOWN stripe zone - buffer_ptr = &buffer[k*height*width+std::max((d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0)),subvol_V_top_delta)*width+j]; - dstripe_ptr = &stripe_down[std::max(((d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0))-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width +j - d_strp_left_displ]; - for(sint64 i=std::max(d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0),subvol_V_top_delta); i(d_strp_top_displ+h_up+h_overlap+h_down,height-subvol_V_bottom_delta); i++, buffer_ptr+=width, dstripe_ptr+=d_strp_width) - *buffer_ptr = *dstripe_ptr; + //UP stripe zone + buffer_ptr = &buffer[k*height*width+std::max(d_strp_top_displ,subvol_V_top_delta)*width+j]; + ustripe_ptr = &stripe_up[std::max((d_strp_top_displ-u_strp_top_displ),u_strp_V_top_delta)*u_strp_width +j - u_strp_left_displ]; + for(sint64 i=std::max(d_strp_top_displ,subvol_V_top_delta); i(d_strp_top_displ+h_up+(h_overlap >= 0 ? 0 : h_overlap),height-subvol_V_bottom_delta); i++, buffer_ptr+=width, ustripe_ptr+= u_strp_width) + *buffer_ptr = *ustripe_ptr; + + //OVERLAPPING zone + buffer_ptr = &buffer[k*height*width+std::max((d_strp_top_displ+h_up),subvol_V_top_delta)*width+j]; + ustripe_ptr = &stripe_up[std::max((d_strp_top_displ+h_up-u_strp_top_displ),u_strp_V_top_delta)*u_strp_width +j - u_strp_left_displ]; + dstripe_ptr = &stripe_down[std::max((d_strp_top_displ+h_up-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width +j - d_strp_left_displ]; + for(sint64 i=std::max(d_strp_top_displ+h_up,subvol_V_top_delta); i(d_strp_top_displ+h_up+h_overlap,height-subvol_V_bottom_delta); i++, buffer_ptr+=width, ustripe_ptr+= u_strp_width, dstripe_ptr+=d_strp_width, angle+=delta_angle) + *buffer_ptr = blending(angle,*ustripe_ptr,*dstripe_ptr); + + //DOWN stripe zone + buffer_ptr = &buffer[k*height*width+std::max((d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0)),subvol_V_top_delta)*width+j]; + dstripe_ptr = &stripe_down[std::max(((d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0))-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width +j - d_strp_left_displ]; + for(sint64 i=std::max(d_strp_top_displ+h_up+(h_overlap >= 0 ? h_overlap : 0),subvol_V_top_delta); i(d_strp_top_displ+h_up+h_overlap+h_down,height-subvol_V_bottom_delta); i++, buffer_ptr+=width, dstripe_ptr+=d_strp_width) + *buffer_ptr = *dstripe_ptr; + } + + cnr_left = cnr_right; + cnr_i++; + if(cnr_i_next != stripesCorners[row_index-1].merged.end()) + cnr_i_next++; } + } - cnr_left = cnr_right; - cnr_i++; - if(cnr_i_next != stripesCorners[row_index-1].merged.end()) - cnr_i_next++; + //non-overlapping zone + // 2017-08-19. Giulio. @CHANGED only requested data is copied of first stripe if subvol_V_top_delta > 0 and of last stripe if subvol_V_bottom_delta > 0 + buffer_ptr = &buffer[k*height*width+((row_index==stitcher->ROW_START ? subvol_V_top_delta : u_strp_bottom_displ))*width]; + for(sint64 i=(row_index==stitcher->ROW_START ? subvol_V_top_delta : u_strp_bottom_displ); i<(row_index==stitcher->ROW_END? height-subvol_V_bottom_delta : dd_strp_top_displ); i++) + { + dstripe_ptr = &stripe_down[std::max((i-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width - d_strp_left_displ]; + for(sint64 j=0; j= 0 && j - d_strp_left_displ < stripesCoords[row_index].bottom_right.H) + *buffer_ptr = *dstripe_ptr; } - } - //non-overlapping zone - // 2017-08-19. Giulio. @CHANGED only requested data is copied of first stripe if subvol_V_top_delta > 0 and of last stripe if subvol_V_bottom_delta > 0 - buffer_ptr = &buffer[k*height*width+((row_index==stitcher->ROW_START ? subvol_V_top_delta : u_strp_bottom_displ))*width]; - for(sint64 i=(row_index==stitcher->ROW_START ? subvol_V_top_delta : u_strp_bottom_displ); i<(row_index==stitcher->ROW_END? height-subvol_V_bottom_delta : dd_strp_top_displ); i++) - { - dstripe_ptr = &stripe_down[std::max((i-d_strp_top_displ),d_strp_V_top_delta)*d_strp_width - d_strp_left_displ]; - for(sint64 j=0; j= 0 && j - d_strp_left_displ < stripesCoords[row_index].bottom_right.H) - *buffer_ptr = *dstripe_ptr; + //moving to bottom stripe_up + delete stripe_up; + stripe_up=stripe_down; } - - //moving to bottom stripe_up - delete stripe_up; - stripe_up=stripe_down; + //releasing last stripe_down + delete stripe_down; } - //releasing last stripe_down - delete stripe_down; - } + } // 2018-03-03. Giulio. ENDIF of: special cases of buffers if ( cb->cacheSubvolume(current_channel,V0,V1,H0,H1,D0,D1,buffer,(height*width*depth)) ) internal_buffer_deallocate = false; else internal_buffer_deallocate = true; - } // 2018-01-20. Giulio. check if the requested region is outside the selected matrix of tiles + } // 2018-01-20. Giulio. ENDIF of: check if the requested region is outside the selected matrix of tiles } else { internal_buffer_deallocate = false; diff --git a/src/imagemanager/VirtualVolume.h b/src/imagemanager/VirtualVolume.h index ac92c4b8..7343fc84 100644 --- a/src/imagemanager/VirtualVolume.h +++ b/src/imagemanager/VirtualVolume.h @@ -88,7 +88,7 @@ class iim::VirtualVolume { src += totalChanSize; cc++; } - memcpy(dst,src,totalChanSize); + memcpy(dst,src,(size_t)totalChanSize); } } diff --git a/src/iomanager/ioplugins.h b/src/iomanager/ioplugins.h index 69592213..14802751 100755 --- a/src/iomanager/ioplugins.h +++ b/src/iomanager/ioplugins.h @@ -1,5 +1,5 @@ -// Include plugins headers -#include "plugins/dcimg/dcimg.h" -#include "plugins/IMS_HDF5/IMS_HDF5.h" -#include "plugins/tiff2D/tiff2D.h" -#include "plugins/tiff3D/tiff3D.h" +// Include plugins headers +#include "plugins/dcimg/dcimg.h" +#include "plugins/IMS_HDF5/IMS_HDF5.h" +#include "plugins/tiff2D/tiff2D.h" +#include "plugins/tiff3D/tiff3D.h" diff --git a/src/ui/CLI.cpp b/src/ui/CLI.cpp index 92d6d09c..200bbc30 100644 --- a/src/ui/CLI.cpp +++ b/src/ui/CLI.cpp @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED an option to set a path and a name for the mdata.bin file generated when volumes are created from data * 2018-01-30. Giulio. @FIXED flags disabling last row and colum were not initialized in non-parallel executions * 2018-01-28. Giulio. @CHANGED the checks about the image input channel * 2018-01-23. Giulio. @ADDED check to set always the input format of a MultiVolume dataset as a non-interleaved input format @@ -84,6 +85,7 @@ void TeraStitcherCLI::readParams(int argc, char** argv) throw (iom::exception) TCLAP::SwitchArg p_isotropic("","isotropic","Generate lowest resolution with voxels as much isotropic as possible. Use this flag when the high resolution image has highy anistropic voxels",false); TCLAP::SwitchArg p_dump("d","dump","Print the entire content of metadata file mdata.bin",false); TCLAP::SwitchArg p_pluginsinfo("p","pluginsinfo","Display plugins informations",false); + TCLAP::ValueArg p_mdata_fname("","mdata_bin","Path and name of mdata.bin file.",false,"","string"); TCLAP::ValueArg p_vol_in_path("","volin","Directory path where the volume is stored.",false,"null","string"); TCLAP::ValueArg p_vol_out_path("","volout","Directory path where to save the stitched volume.",false,"null","string"); TCLAP::ValueArg p_vol_in_plugin("","volin_plugin",vm::strprintf("Plugin that manages the input volume format/organization. Available plugins are: {%s}. Default is \"%s\".", vm::VirtualVolumeFactory::registeredPlugins().c_str(), vm::VOLUME_INPUT_FORMAT_PLUGIN.c_str()),false,vm::VOLUME_INPUT_FORMAT_PLUGIN,"string"); @@ -211,6 +213,7 @@ void TeraStitcherCLI::readParams(int argc, char** argv) throw (iom::exception) cmd.add(p_vol_out_path); cmd.add(p_vol_in_plugin); cmd.add(p_vol_in_path); + cmd.add(p_mdata_fname); cmd.add(p_pluginsinfo); cmd.add(p_dump); cmd.add(p_stitch); @@ -520,6 +523,7 @@ void TeraStitcherCLI::readParams(int argc, char** argv) throw (iom::exception) this->thresholddisplacements = p_thresholdisplacements.getValue(); this->placetiles = p_placetiles.getValue(); this->mergetiles = p_merge.getValue(); + this->mdata_fname = p_mdata_fname.getValue(); this->volume_load_path = p_vol_in_path.getValue(); this->volume_save_path = p_vol_out_path.getValue(); this->projfile_load_path = p_proj_in_path.getValue(); diff --git a/src/ui/CLI.h b/src/ui/CLI.h index 09a0165d..4296fd3a 100644 --- a/src/ui/CLI.h +++ b/src/ui/CLI.h @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED an option to set a path and a name for the mdata.bin file generated when volumes are created from data * 2018-01-23. Giulio. @ADDED include of MCVolume.h * 2017-06-30. Giulio. @ADDED control over displacement computation of last row and last column of tiles * 2016-09-04. Giulio. @ADDED the options for setting the configuration of the LibTIFF library @@ -66,6 +67,7 @@ class TeraStitcherCLI bool isotropic; //generate lowest resolutiona with voxels as much isotropic as possible //STITCHING pipeline parameters + string mdata_fname; //path & file mane of mdata.bin file string volume_load_path; //directory path where the volume is stored used during the volume import step string volume_save_path; //directory path where to save the stitched volume string projfile_load_path; //file path of the project XML file to be loaded diff --git a/src/ui/main.cpp b/src/ui/main.cpp index 59fc86c7..2b89bf4a 100644 --- a/src/ui/main.cpp +++ b/src/ui/main.cpp @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file generated when volumes are created from data * 2018-01-23. Giulio. @ADDED check to set always the input format of a MultiVolume dataset as a non-interleaved input format * 2017-12-01. Giulio @ADDED conditional code to activate the new merge step * 2017-06-30. Giulio. @FIXED the coding of iom::CHANS was not coherent with the one used internally by vmVirtualVolume @@ -190,7 +191,7 @@ int main(int argc, char** argv) throw iom::exception(vm::strprintf("Volume \"%s\" is incomplete or not coherent", volume->getSTACKS_DIR()).c_str()); } else if(cli.import || (cli.computedisplacements && cli.projfile_load_path.compare("null")==0) || cli.stitch || cli.test) { - volume = volumemanager::VirtualVolumeFactory::createFromData(vm::VOLUME_INPUT_FORMAT_PLUGIN, cli.volume_load_path.c_str(), cli.reference_system, cli.VXL_1, cli.VXL_2, cli.VXL_3, true); + volume = volumemanager::VirtualVolumeFactory::createFromData(vm::VOLUME_INPUT_FORMAT_PLUGIN, cli.volume_load_path.c_str(), cli.reference_system, cli.VXL_1, cli.VXL_2, cli.VXL_3, true, cli.mdata_fname); if ( !volume->check(fillPath(cli.errlogfile_path, volume->getSTACKS_DIR(), "err_log_file", "txt").c_str()) ) { // save xml for further checking volume->saveXML(0, fillPath(cli.projfile_save_path, volume->getSTACKS_DIR(), "xml_import", "xml").c_str()); diff --git a/src/volumemanager/vmBlockVolume.cpp b/src/volumemanager/vmBlockVolume.cpp index 6d5c1a93..774adbf0 100644 --- a/src/volumemanager/vmBlockVolume.cpp +++ b/src/volumemanager/vmBlockVolume.cpp @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file * 2018-02-03. Giulio. @ADDED call to 'adjustDisplacements' in method reading the xml file to force all displacements of adjacent tile symmetric * 2017-06-27. Giulio. @CHANGED If the attributes 'resolution' and 'timepoint' in section 'subimage' of xml file are present additional parameters are always enabled * 2017-04-27. Giulio. @ADDED code to get and initialize the input plugin from the xml if specified @@ -90,7 +91,7 @@ const std::string BlockVolume::creator_id1 = volumemanager::VirtualVolumeFactory const std::string BlockVolume::creator_id2 = volumemanager::VirtualVolumeFactory::registerPluginCreatorData(&createFromData, BlockVolume::id); -BlockVolume::BlockVolume(const char* _stacks_dir, vm::ref_sys _reference_system, float VXL_1, float VXL_2, float VXL_3, bool overwrite_mdata) throw (iom::exception) +BlockVolume::BlockVolume(const char* _stacks_dir, vm::ref_sys _reference_system, float VXL_1, float VXL_2, float VXL_3, bool overwrite_mdata, std::string mdata_fname) throw (iom::exception) : VirtualVolume(_stacks_dir, _reference_system, VXL_1, VXL_2, VXL_3) { #if VM_VERBOSE > 3 @@ -104,7 +105,12 @@ BlockVolume::BlockVolume(const char* _stacks_dir, vm::ref_sys _reference_system, //trying to unserialize an already existing metadata file, if it doesn't exist the full initialization procedure is performed and metadata is saved char mdata_filepath[VM_STATIC_STRINGS_SIZE]; - sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + if ( mdata_fname == "" ) { // no metadata file name present in xml file, use default folder and name + sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + } + else { + strcpy(mdata_filepath,mdata_fname.c_str()); + } if(fileExists(mdata_filepath) && !overwrite_mdata) loadBinaryMetadata(mdata_filepath); else @@ -164,7 +170,16 @@ BlockVolume::BlockVolume(const char *xml_filepath, bool overwrite_mdata) throw ( //trying to unserialize an already existing metadata file, if it doesn't exist the full initialization procedure is performed and metadata is saved char mdata_filepath[2000]; - sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + pelem = hRoot.FirstChildElement("mdata_bin").Element(); + + if ( pelem == ((TiXmlElement *)0) ) { // no metadata file name present in xml file, use default folder and name + sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + } + else { + strcpy(mdata_filepath, pelem->Attribute("value")); + } + + xml.Clear(); // 2014-09-20. Alessandro. @ADDED overwrite_mdata flag if(fileExists(mdata_filepath) && !overwrite_mdata) diff --git a/src/volumemanager/vmBlockVolume.h b/src/volumemanager/vmBlockVolume.h index 86b18e96..d0d30e1d 100644 --- a/src/volumemanager/vmBlockVolume.h +++ b/src/volumemanager/vmBlockVolume.h @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file * 2017-06-26. Giulio. @ADDED methods to set active resolution and active timepoint * 2017-04-12. Giulio. @ADDED method to release all buffers allocated in VirtualStack * 2016-10-27. Giulio. @ADDED string fields for control over the subimage to be exposed through the xml import file @@ -54,8 +55,8 @@ class vm::BlockVolume : public vm::VirtualVolume // 2014-09-10. Alessandro. @ADDED plugin creation/registration functions to make 'StackedVolume' a volume format plugin. static const std::string creator_id1, creator_id2; static vm::VirtualVolume* createFromXML(const char* xml_path, bool ow_mdata) { return new BlockVolume(xml_path, ow_mdata); } - static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata) { - return new BlockVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata); + static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata, std::string mdata_fname) { + return new BlockVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata,mdata_fname); } vm::Block ***BLOCKS; //2-D array of @@ -96,7 +97,7 @@ class vm::BlockVolume : public vm::VirtualVolume //CONSTRUCTORS-DECONSTRUCTOR BlockVolume() : vm::VirtualVolume(){} - BlockVolume(const char* _stacks_dir, vm::ref_sys reference_system, float VXL_1=0, float VXL_2=0, float VXL_3=0, bool overwrite_mdata=false) throw (iom::exception); + BlockVolume(const char* _stacks_dir, vm::ref_sys reference_system, float VXL_1=0, float VXL_2=0, float VXL_3=0, bool overwrite_mdata=false, std::string mdata_fname="") throw (iom::exception); BlockVolume(const char *xml_filepath, bool overwrite_mdata=false) throw (iom::exception); ~BlockVolume(); diff --git a/src/volumemanager/vmMCVolume.cpp b/src/volumemanager/vmMCVolume.cpp index cad90a98..99e6bca3 100755 --- a/src/volumemanager/vmMCVolume.cpp +++ b/src/volumemanager/vmMCVolume.cpp @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-01. Giulio. @FIXED global variable 'vm::VOLUME_INPUT_FORMAT_PLUGIN' is set to vm::MCVolume::id in the constructor to signal that it is a non interleaved channel representation * 2018-01-20. Giulio. @CREATED */ @@ -77,6 +78,9 @@ MCVolume::MCVolume(const char* _stacks_dir, vm::ref_sys _reference_system, float _stacks_dir,reference_system.first, reference_system.second, reference_system.third, VXL_1, VXL_2, VXL_3); #endif + // 2018-03-01. Giulio. @FIXED global variable 'vm::VOLUME_INPUT_FORMAT_PLUGIN' has to be set to vm::MCVolume::id to signal that it is a non interleaved channel representation + vm::VOLUME_INPUT_FORMAT_PLUGIN = vm::MCVolume::id; + checked = false; aligned = false; // no guarantee that subvolumes are aligned @@ -118,6 +122,9 @@ MCVolume::MCVolume(const char *xml_filepath, bool overwrite_mdata) throw (iom::e #if VM_VERBOSE > 3 printf("\t\t\t\tin MCVolume::MCVolume(xml_filepath=%s)\n", xml_filepath); #endif + + // 2018-03-01. Giulio. @FIXED global variable 'vm::VOLUME_INPUT_FORMAT_PLUGIN' has to be set to vm::MCVolume::id to signal that it is a non interleaved channel representation + vm::VOLUME_INPUT_FORMAT_PLUGIN = vm::MCVolume::id; checked = false; aligned = false; // no guarantee that subvolumes are aligned diff --git a/src/volumemanager/vmMCVolume.h b/src/volumemanager/vmMCVolume.h index 050ba077..b322664b 100755 --- a/src/volumemanager/vmMCVolume.h +++ b/src/volumemanager/vmMCVolume.h @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED a parameter to set a path and a name for the mdata.bin file for compatibility, but it is not used * 2018-01-20. Giulio. @CREATED */ @@ -47,8 +48,8 @@ class vm::MCVolume : public vm::VirtualVolume static const std::string creator_id1, creator_id2; static vm::VirtualVolume* createFromXML(const char* xml_path, bool ow_mdata = false) { return new MCVolume(xml_path, ow_mdata); } // 2018-01-21. Giulio @ADDED default parameters to support creation from data (folder containing xml import files) - static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref = vm::ref_sys(vm::axis(0),vm::axis(0),vm::axis(0)), float vxl1 = 0, float vxl2 = 0, float vxl3 = 0, bool ow_mdata = false) { - return new MCVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata); + static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref = vm::ref_sys(vm::axis(0),vm::axis(0),vm::axis(0)), float vxl1 = 0, float vxl2 = 0, float vxl3 = 0, bool ow_mdata = false, std::string mdata_fname = "") { + return new MCVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata); // the mdata_fname parameter is not used for MCVolumes } vm::VirtualVolume **subvolumes; diff --git a/src/volumemanager/vmStackedVolume.cpp b/src/volumemanager/vmStackedVolume.cpp index 6fda3e88..5d907b18 100644 --- a/src/volumemanager/vmStackedVolume.cpp +++ b/src/volumemanager/vmStackedVolume.cpp @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file * 2018-02-03. Giulio. @ADDED call to 'adjustDisplacements' in method reading the xml file to force all displacements of adjacent tile symmetric * 2017-04-27. Giulio. @ADDED code to get and initialize the input plugin from the xml if specified * 2017-04-12. Giulio. @ADDED method to release all buffers allocated in VirtualStack @@ -91,7 +92,7 @@ const std::string StackedVolume::id = "TiledXY|2Dseries"; const std::string StackedVolume::creator_id1 = volumemanager::VirtualVolumeFactory::registerPluginCreatorXML(&createFromXML, StackedVolume::id); const std::string StackedVolume::creator_id2 = volumemanager::VirtualVolumeFactory::registerPluginCreatorData(&createFromData, StackedVolume::id); -StackedVolume::StackedVolume(const char* _stacks_dir, vm::ref_sys _reference_system, float VXL_1, float VXL_2, float VXL_3, bool overwrite_mdata) throw (iom::exception) +StackedVolume::StackedVolume(const char* _stacks_dir, vm::ref_sys _reference_system, float VXL_1, float VXL_2, float VXL_3, bool overwrite_mdata, std::string mdata_fname) throw (iom::exception) : VirtualVolume(_stacks_dir, _reference_system, VXL_1, VXL_2, VXL_3) { #if VM_VERBOSE > 3 @@ -100,8 +101,13 @@ StackedVolume::StackedVolume(const char* _stacks_dir, vm::ref_sys _reference_sys #endif //trying to unserialize an already existing metadata file, if it doesn't exist the full initialization procedure is performed and metadata is saved - char mdata_filepath[VM_STATIC_STRINGS_SIZE]; - sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + char mdata_filepath[VM_STATIC_STRINGS_SIZE]; + if ( mdata_fname == "" ) { // no metadata file name present in xml file, use default folder and name + sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + } + else { + strcpy(mdata_filepath,mdata_fname.c_str()); + } if(fileExists(mdata_filepath) && !overwrite_mdata) loadBinaryMetadata(mdata_filepath); else @@ -155,13 +161,21 @@ StackedVolume::StackedVolume(const char *xml_filepath, bool overwrite_mdata) thr TiXmlElement * pelem = hRoot.FirstChildElement("stacks_dir").Element(); this->stacks_dir = new char[strlen(pelem->Attribute("value"))+1]; strcpy(this->stacks_dir, pelem->Attribute("value")); - xml.Clear(); - //trying to unserialize an already existing metadata file, if it doesn't exist the full initialization procedure is performed and metadata is saved - char mdata_filepath[2000]; - sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + //trying to unserialize an already existing metadata file, if it doesn't exist the full initialization procedure is performed and metadata is saved + char mdata_filepath[VM_STATIC_STRINGS_SIZE]; + pelem = hRoot.FirstChildElement("mdata_bin").Element(); + + if ( pelem == ((TiXmlElement *)0) ) { // no metadata file name present in xml file, use default folder and name + sprintf(mdata_filepath, "%s/%s", stacks_dir, vm::BINARY_METADATA_FILENAME.c_str()); + } + else { + strcpy(mdata_filepath, pelem->Attribute("value")); + } + + xml.Clear(); - // 2014-09-20. Alessandro. @ADDED overwrite_mdata flag + // 2014-09-20. Alessandro. @ADDED overwrite_mdata flag if(fileExists(mdata_filepath) && !overwrite_mdata) { // load mdata.bin content and xml content, also perform consistency check between mdata.bin and xml content diff --git a/src/volumemanager/vmStackedVolume.h b/src/volumemanager/vmStackedVolume.h index 04508162..b04bb03a 100644 --- a/src/volumemanager/vmStackedVolume.h +++ b/src/volumemanager/vmStackedVolume.h @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file * 2017-04-12. Giulio. @ADDED method to release all buffers allocated in VirtualStack * 2015-06-12. Giulio @ADDED 'check' method to check completeness and coherence of a volume * 2015-02-26. Giulio. @ADDED initChannels private method to initialize fields DIM_C and BYTESxCHAN @@ -58,8 +59,8 @@ class vm::StackedVolume : public vm::VirtualVolume // 2014-09-10. Alessandro. @ADDED plugin creation/registration functions to make 'StackedVolume' a volume format plugin. static const std::string creator_id1, creator_id2; static vm::VirtualVolume* createFromXML(const char* xml_path, bool ow_mdata) { return new StackedVolume(xml_path, ow_mdata); } - static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata) { - return new StackedVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata); + static vm::VirtualVolume* createFromData(const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata, std::string mdata_fname) { + return new StackedVolume(data_path, ref, vxl1, vxl2, vxl3, ow_mdata, mdata_fname); } @@ -91,7 +92,7 @@ class vm::StackedVolume : public vm::VirtualVolume //CONSTRUCTORS-DECONSTRUCTOR StackedVolume() : vm::VirtualVolume(){} - StackedVolume(const char* _stacks_dir, vm::ref_sys reference_system, float VXL_1=0, float VXL_2=0, float VXL_3=0, bool overwrite_mdata=false) throw (iom::exception); + StackedVolume(const char* _stacks_dir, vm::ref_sys reference_system, float VXL_1=0, float VXL_2=0, float VXL_3=0, bool overwrite_mdata=false, std::string mdata_fname="") throw (iom::exception); StackedVolume(const char *xml_filepath, bool overwrite_mdata=false) throw (iom::exception); ~StackedVolume(); diff --git a/src/volumemanager/vmVirtualStack.h b/src/volumemanager/vmVirtualStack.h index d39785cd..200ad173 100644 --- a/src/volumemanager/vmVirtualStack.h +++ b/src/volumemanager/vmVirtualStack.h @@ -28,6 +28,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-03. Giulio. @ADDED method 'releaseImageSteckOwnership' to manage cases when the ownership of the internal buffer must be given to other modules * 2017-07-06. Giulio. @ADDED method 'loadImageStack2' to enable selective reads of data * 2015-02-28. Giulio. @ADDED fields N_CHANS and BYTESxCHAN * 2015-01-17. Alessandro. @ADDED support for all-in-one-folder data (import from xml only). @@ -179,6 +180,7 @@ class vm::VirtualStack virtual iom::real_t* loadImageStack(int first_file=-1, int last_file=-1) throw (iom::exception) = 0; virtual iom::real_t* loadImageStack2(int first_file=-1, int last_file=-1, int V0=-1, int V1=-1, int H0=-1, int H1=-1) throw (iom::exception) = 0; virtual void releaseImageStack()= 0; + void releaseImageStackOwnership() { STACKED_IMAGE = 0; } // return true if the given range [z0,z1] does not contain missing slices/blocks virtual bool isComplete(int z0, int z1); diff --git a/src/volumemanager/vmVirtualVolume.h b/src/volumemanager/vmVirtualVolume.h index 51d15b2e..e775933a 100644 --- a/src/volumemanager/vmVirtualVolume.h +++ b/src/volumemanager/vmVirtualVolume.h @@ -25,6 +25,7 @@ /****************** * CHANGELOG * ******************* +* 2018-03-02. Giulio. @ADDED the possibility to set a path and a name for the mdata.bin file generated when volumes are created from data * 2018-02-03. Giulio. @ADDED internal method to correct non symmetric displacements between tiles * 2018-01-20. Giulio. @CHANGED some methods to virtual and the type of a few data members * 2017-04-27. Giulio. @ADDED static method to get the input plugin from the xml if specified @@ -209,7 +210,7 @@ class volumemanager::VirtualVolume // define new type: VirtualVolume plugin creator functions typedef volumemanager::VirtualVolume* (*VolumeCreatorXML)(const char*, bool); -typedef volumemanager::VirtualVolume* (*VolumeCreatorData)(const char*, vm::ref_sys, float, float, float, bool); +typedef volumemanager::VirtualVolume* (*VolumeCreatorData)(const char*, vm::ref_sys, float, float, float, bool, std::string); // Factory for plugins' registration and instantiation class volumemanager::VirtualVolumeFactory @@ -256,11 +257,11 @@ class volumemanager::VirtualVolumeFactory return (instance()->creators_xml[id])(xml_path, ow_mdata); } - static VirtualVolume* createFromData(std::string id, const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata) throw (iom::exception) + static VirtualVolume* createFromData(std::string id, const char* data_path, vm::ref_sys ref, float vxl1, float vxl2, float vxl3, bool ow_mdata, std::string mdata_fname="") throw (iom::exception) { if(instance()->creators_data.find(id) == instance()->creators_data.end()) throw iom::exception(iom::strprintf("Cannot find VirtualVolume(data) plugin \"%s\": no such plugin", id.c_str()).c_str()); - return (instance()->creators_data[id])(data_path, ref, vxl1, vxl2, vxl3, ow_mdata); + return (instance()->creators_data[id])(data_path, ref, vxl1, vxl2, vxl3, ow_mdata, mdata_fname); } // get list of registered plugins