// GetSparseCoarseVol returns an encoded sparse volume given a label. The encoding has the // following format where integers are little endian: // byte Set to 0 // uint8 Number of dimensions // uint8 Dimension of run (typically 0 = X) // byte Reserved (to be used later) // uint32 # Blocks [TODO. 0 for now] // uint32 # Spans // Repeating unit of: // int32 Block coordinate of run start (dimension 0) // int32 Block coordinate of run start (dimension 1) // int32 Block coordinate of run start (dimension 2) // int32 Length of run // func GetSparseCoarseVol(ctx storage.Context, label uint64) ([]byte, error) { store, err := storage.SmallDataStore() if err != nil { return nil, fmt.Errorf("Data type labelvol had error initializing store: %v\n", err) } // Create the sparse volume header buf := new(bytes.Buffer) buf.WriteByte(dvid.EncodingBinary) binary.Write(buf, binary.LittleEndian, uint8(3)) // # of dimensions binary.Write(buf, binary.LittleEndian, byte(0)) // dimension of run (X = 0) buf.WriteByte(byte(0)) // reserved for later binary.Write(buf, binary.LittleEndian, uint32(0)) // Placeholder for # blocks encoding := buf.Bytes() // Get the start/end indices for this body's KeyLabelSpatialMap (b + s) keys. begTKey := NewTKey(label, dvid.MinIndexZYX.ToIZYXString()) endTKey := NewTKey(label, dvid.MaxIndexZYX.ToIZYXString()) // Process all the b+s keys and their values, which contain RLE runs for that label. var numBlocks uint32 var span *dvid.Span var spans dvid.Spans keys, err := store.KeysInRange(ctx, begTKey, endTKey) if err != nil { return nil, fmt.Errorf("Cannot get keys for coarse sparse volume: %v", err) } for _, tk := range keys { numBlocks++ _, blockStr, err := DecodeTKey(tk) if err != nil { return nil, fmt.Errorf("Error retrieving RLE runs for label %d: %v", label, err) } indexZYX, err := blockStr.IndexZYX() if err != nil { return nil, fmt.Errorf("Error decoding block coordinate (%v) for sparse volume: %v\n", blockStr, err) } x, y, z := indexZYX.Unpack() if span == nil { span = &dvid.Span{z, y, x, x} } else if !span.Extends(x, y, z) { spans = append(spans, *span) span = &dvid.Span{z, y, x, x} } } if err != nil { return nil, err } if span != nil { spans = append(spans, *span) } spansBytes, err := spans.MarshalBinary() if err != nil { return nil, err } encoding = append(encoding, spansBytes...) dvid.Debugf("[%s] coarse subvol for label %d: found %d blocks\n", ctx, label, numBlocks) return encoding, nil }
func TestTuples(t *testing.T) { tup := dvid.Span{10, 11, 20, 30} if tup.Less(dvid.ChunkPoint3d{20, 11, 10}) { t.Errorf("Bad tuple.Less()\n") } if tup.Less(dvid.ChunkPoint3d{30, 11, 10}) { t.Errorf("Bad tuple.Less()\n") } if !tup.Less(dvid.ChunkPoint3d{31, 11, 10}) { t.Errorf("Bad tuple.Less()\n") } if !tup.Less(dvid.ChunkPoint3d{20, 11, 11}) { t.Errorf("Bad tuple.Less()\n") } if tup.Less(dvid.ChunkPoint3d{20, 11, 9}) { t.Errorf("Bad tuple.Less()\n") } if !tup.Less(dvid.ChunkPoint3d{20, 11, 11}) { t.Errorf("Bad tuple.Less()\n") } if tup.Includes(dvid.ChunkPoint3d{19, 11, 10}) { t.Errorf("Bad tuple.Includes()\n") } if !tup.Includes(dvid.ChunkPoint3d{20, 11, 10}) { t.Errorf("Bad tuple.Includes()\n") } if !tup.Includes(dvid.ChunkPoint3d{30, 11, 10}) { t.Errorf("Bad tuple.Includes()\n") } if tup.Includes(dvid.ChunkPoint3d{31, 11, 10}) { t.Errorf("Bad tuple.Includes()\n") } if tup.Includes(dvid.ChunkPoint3d{25, 11, 11}) { t.Errorf("Bad tuple.Includes()\n") } if tup.Includes(dvid.ChunkPoint3d{25, 11, 9}) { t.Errorf("Bad tuple.Includes()\n") } if tup.Includes(dvid.ChunkPoint3d{25, 10, 10}) { t.Errorf("Bad tuple.Includes()\n") } if tup.Includes(dvid.ChunkPoint3d{25, 12, 10}) { t.Errorf("Bad tuple.Includes()\n") } }
func (d *Data) foregroundROI(v dvid.VersionID, dest *roi.Data, background dvid.PointNd) { dest.Ready = false store, err := storage.MutableStore() if err != nil { dvid.Criticalf("Data type imageblk had error initializing store: %v\n", err) return } timedLog := dvid.NewTimeLog() timedLog.Infof("Starting foreground ROI %q for %s", dest.DataName(), d.DataName()) // Iterate through all voxel blocks, loading and then checking blocks // for any foreground voxels. ctx := datastore.NewVersionedCtx(d, v) backgroundBytes := make([]byte, len(background)) for i, b := range background { backgroundBytes[i] = byte(b) } const BATCH_SIZE = 1000 var numBatches int var span *dvid.Span spans := []dvid.Span{} var f storage.ChunkFunc = func(chunk *storage.Chunk) error { if chunk == nil || chunk.V == nil { return nil } data, _, err := dvid.DeserializeData(chunk.V, true) if err != nil { return fmt.Errorf("Error decoding block: %v\n", err) } numVoxels := d.BlockSize().Prod() var foreground bool for i := int64(0); i < numVoxels; i++ { isBackground := false for _, b := range backgroundBytes { if data[i] == b { isBackground = true break } } if !isBackground { foreground = true break } } if foreground { indexZYX, err := DecodeTKey(chunk.K) if err != nil { return fmt.Errorf("Error decoding voxel block key: %v\n", err) } x, y, z := indexZYX.Unpack() if span == nil { span = &dvid.Span{z, y, x, x} } else if !span.Extends(x, y, z) { spans = append(spans, *span) if len(spans) >= BATCH_SIZE { init := (numBatches == 0) numBatches++ go func(spans []dvid.Span) { if err := dest.PutSpans(v, spans, init); err != nil { dvid.Errorf("Error in storing ROI: %v\n", err) } else { timedLog.Debugf("-- Wrote batch %d of spans for foreground ROI %q", numBatches, dest.DataName()) } }(spans) spans = []dvid.Span{} } span = &dvid.Span{z, y, x, x} } } server.BlockOnInteractiveRequests("voxels [compute foreground ROI]") return nil } minTKey := storage.MinTKey(keyImageBlock) maxTKey := storage.MaxTKey(keyImageBlock) err = store.ProcessRange(ctx, minTKey, maxTKey, &storage.ChunkOp{}, f) if err != nil { dvid.Errorf("Error in processing chunks in ROI: %v\n", err) return } if span != nil { spans = append(spans, *span) } // Save new ROI if len(spans) > 0 { if err := dest.PutSpans(v, spans, numBatches == 0); err != nil { dvid.Errorf("Error in storing ROI: %v\n", err) return } } timedLog.Infof("Created foreground ROI %q for %s", dest.DataName(), d.DataName()) dest.Ready = true }