github.com/janelia-flyem/dvid@v1.0.0/datatype/imagetile/push.go (about)

     1  package imagetile
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/janelia-flyem/dvid/datastore"
     8  	"github.com/janelia-flyem/dvid/datatype/roi"
     9  	"github.com/janelia-flyem/dvid/dvid"
    10  	"github.com/janelia-flyem/dvid/storage"
    11  )
    12  
    13  // PushData does an imagetile-specific push using optional ROI and tile filters.
    14  func (d *Data) PushData(p *datastore.PushSession) error {
    15  	return datastore.PushData(d, p)
    16  }
    17  
    18  // --- dvid.Filterer implementation -----
    19  
    20  // NewFilter returns a Filter for use with a push of key-value pairs.
    21  func (d *Data) NewFilter(fs storage.FilterSpec) (storage.Filter, error) {
    22  	filter := &Filter{Data: d, fs: fs}
    23  
    24  	// if there's no filter, just use base Data send.
    25  	roidata, roiV, roiFound, err := roi.DataByFilter(fs)
    26  	if err != nil {
    27  		return nil, fmt.Errorf("No filter found that was parsable (%s): %v\n", fs, err)
    28  	}
    29  	filter.roi = roidata
    30  	tilespec, tilespecFound := fs.GetFilterSpec("tile")
    31  
    32  	if (!roiFound || roidata == nil) && !tilespecFound {
    33  		dvid.Debugf("No ROI or tile filter found for imagetile push, so using generic data push.\n")
    34  		return nil, nil
    35  	}
    36  	if tilespecFound {
    37  		filter.planes = strings.Split(tilespec, ",")
    38  	}
    39  
    40  	// Get the spans once from datastore.
    41  	filter.spans, err = roidata.GetSpans(roiV)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	return filter, nil
    47  }
    48  
    49  // --- dvid.Filter implementation ----
    50  
    51  type Filter struct {
    52  	*Data
    53  	fs     storage.FilterSpec
    54  	roi    *roi.Data
    55  	spans  dvid.Spans
    56  	planes []string
    57  }
    58  
    59  func (f *Filter) Check(tkv *storage.TKeyValue) (skip bool, err error) {
    60  	tileCoord, plane, scale, err := DecodeTKey(tkv.K)
    61  	if err != nil {
    62  		return true, fmt.Errorf("key (%v) cannot be decoded as tile: %v", tkv.K, err)
    63  	}
    64  	if len(f.planes) != 0 {
    65  		var allowed bool
    66  		for _, allowedPlane := range f.planes {
    67  			if allowedPlane == "xy" && plane.Equals(dvid.XY) {
    68  				allowed = true
    69  				break
    70  			}
    71  			if allowedPlane == "xz" && plane.Equals(dvid.XZ) {
    72  				allowed = true
    73  				break
    74  			}
    75  			if allowedPlane == "yz" && plane.Equals(dvid.YZ) {
    76  				allowed = true
    77  				break
    78  			}
    79  		}
    80  		if !allowed {
    81  			return true, nil
    82  		}
    83  	}
    84  	extents, err := f.computeVoxelBounds(tileCoord, plane, scale)
    85  	if err != nil {
    86  		return true, fmt.Errorf("Error computing voxel bounds of tile: %v\n", err)
    87  	}
    88  	if inside, err := roi.VoxelBoundsInside(extents, f.roi.BlockSize, f.spans); err != nil {
    89  		return true, fmt.Errorf("can't determine intersection of tile and roi: %v\n", err)
    90  	} else if !inside {
    91  		return true, nil
    92  	}
    93  	return false, nil
    94  }