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

     1  package labelvol
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/janelia-flyem/dvid/datastore"
     7  	"github.com/janelia-flyem/dvid/datatype/roi"
     8  	"github.com/janelia-flyem/dvid/dvid"
     9  	"github.com/janelia-flyem/dvid/storage"
    10  )
    11  
    12  // PushData does a labelvol-specific push using optional ROI filters.
    13  func (d *Data) PushData(p *datastore.PushSession) error {
    14  	return datastore.PushData(d, p)
    15  }
    16  
    17  // --- dvid.Filterer implementation -----
    18  
    19  // NewFilter returns a Filter for use with a push of key-value pairs.
    20  func (d *Data) NewFilter(fs storage.FilterSpec) (storage.Filter, error) {
    21  	filter := &Filter{Data: d, fs: fs}
    22  
    23  	// Get associated labelblk.  If none, we can't use roi filter so just do standard data send.
    24  	lblk, err := d.GetSyncedLabelblk()
    25  	if err != nil {
    26  		dvid.Infof("Unable to get synced labelblk for labelvol %q.  Unable to do any ROI-based filtering.\n", d.DataName())
    27  		return nil, nil
    28  	}
    29  
    30  	roiIterator, _, found, err := roi.NewIteratorBySpec(fs, lblk)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	if !found || roiIterator == nil {
    35  		dvid.Debugf("No ROI found so using generic data push for data %q.\n", d.DataName())
    36  		return nil, nil
    37  	}
    38  	filter.it = roiIterator
    39  
    40  	return filter, nil
    41  }
    42  
    43  // --- dvid.Filter implementation ----
    44  
    45  type Filter struct {
    46  	*Data
    47  	fs       storage.FilterSpec
    48  	it       *roi.Iterator
    49  	curLabel uint64
    50  }
    51  
    52  func (f *Filter) Check(tkv *storage.TKeyValue) (skip bool, err error) {
    53  	if f.Data == nil {
    54  		return false, fmt.Errorf("bad filter %q: no data", f.fs)
    55  	}
    56  	if f.it == nil {
    57  		return true, nil
    58  	}
    59  
    60  	// Only filter label block RLE kv pairs.
    61  	class, err := tkv.K.Class()
    62  	if err != nil {
    63  		return true, err
    64  	}
    65  	if class != keyLabelBlockRLE {
    66  		return false, nil
    67  	}
    68  
    69  	// Check the label block against any ROI.
    70  	label, block, err := DecodeTKey(tkv.K)
    71  	if err != nil {
    72  		return true, fmt.Errorf("key (%v) cannot be decoded as labelvol key: %v", tkv.K, err)
    73  	}
    74  	indexZYX, err := block.IndexZYX()
    75  	if err != nil {
    76  		return true, fmt.Errorf("unable to convert labelvol block %s into IndexZYX", block)
    77  	}
    78  	if label != f.curLabel {
    79  		f.it.Reset()
    80  		f.curLabel = label
    81  	}
    82  	if !f.it.InsideFast(indexZYX) {
    83  		return true, nil
    84  	}
    85  	return false, nil
    86  }