From c181170caef298b46d306aaba1d572c1fae27fee Mon Sep 17 00:00:00 2001 From: Bill Katz Date: Fri, 6 May 2022 23:23:41 -0400 Subject: [PATCH] add /supervoxel-sizes and improve /sizes; fixes #262 --- datatype/labelmap/equiv.go | 2 + datatype/labelmap/labelidx.go | 62 ++++++++++++++++++++----------- datatype/labelmap/labelmap.go | 64 ++++++++++++++++++++++++++++++++ datatype/labelmap/mutate_test.go | 31 +++++++++++++++- 4 files changed, 137 insertions(+), 22 deletions(-) diff --git a/datatype/labelmap/equiv.go b/datatype/labelmap/equiv.go index 07a49455..833a0d0d 100644 --- a/datatype/labelmap/equiv.go +++ b/datatype/labelmap/equiv.go @@ -474,6 +474,7 @@ func (d *Data) GetMapStats(ctx *datastore.VersionedCtx) (jsonBytes []byte, err e if ds, err = datastore.GetDataByDataUUID(dataUUID); err != nil { return } + svm.RLock() maxVersion := 0 for _, v := range svm.versions { if int(v) > maxVersion { @@ -486,6 +487,7 @@ func (d *Data) GetMapStats(ctx *datastore.VersionedCtx) (jsonBytes []byte, err e NumVersions: len(svm.versions), MaxVersion: maxVersion, } + svm.RUnlock() } return json.Marshal(stats) } diff --git a/datatype/labelmap/labelidx.go b/datatype/labelmap/labelidx.go index fc982670..a1ec74a2 100644 --- a/datatype/labelmap/labelidx.go +++ b/datatype/labelmap/labelidx.go @@ -437,28 +437,52 @@ func GetLabelSize(d dvid.Data, v dvid.VersionID, label uint64, isSupervoxel bool return idx.NumVoxels(), nil } -// GetLabelSizes returns the # of voxels in the given labels. If isSupervoxel = true, the given -// labels are interpreted as supervoxel ids and the sizes are of a supervoxel. If a label doesn't -// exist, a zero (not error) is returned. -func GetLabelSizes(d dvid.Data, v dvid.VersionID, labels []uint64, isSupervoxel bool) ([]uint64, error) { - var supervoxels []uint64 - if isSupervoxel { - svmap, err := getMapping(d, v) - if err != nil { - return nil, fmt.Errorf("couldn't get mapping for data %q, version %d: %v", d.DataName(), v, err) - } - supervoxels = make([]uint64, len(labels)) - copy(supervoxels, labels) +func getSupervoxelSizes(d dvid.Data, v dvid.VersionID, supervoxels []uint64) ([]uint64, error) { + svmap, err := getMapping(d, v) + if err != nil { + return nil, fmt.Errorf("couldn't get mapping for data %q, version %d: %v", d.DataName(), v, err) + } + labelsets := make(map[uint64][]uint64) // maps labels -> set of supervoxels in it. + labels, _, err := svmap.MappedLabels(v, supervoxels) + if err != nil { + return nil, err + } + for i, label := range labels { + labelsets[label] = append(labelsets[label], supervoxels[i]) + } - labels, _, err = svmap.MappedLabels(v, labels) + sizemap := make(map[uint64]uint64, len(supervoxels)) + for label, svlist := range labelsets { + idx, err := GetLabelIndex(d, v, label, false) if err != nil { return nil, err } + if idx == nil { + for _, sv := range svlist { + sizemap[sv] = 0 + } + } else { + svcounts := idx.GetSupervoxelCounts() + for _, sv := range svlist { + sizemap[sv] = svcounts[sv] + } + } } - // TODO -- could optimize by doing unique set of labels if supervoxels, since multiple supervoxels - // may be in same label. However, caching might simply remove this optimization issue since label - // index will already be cached. - sizes := make([]uint64, len(labels)) + sizes := make([]uint64, len(supervoxels)) + for i, sv := range supervoxels { + sizes[i] = sizemap[sv] + } + return sizes, nil +} + +// GetLabelSizes returns the # of voxels in the given labels. If isSupervoxel = true, the given +// labels are interpreted as supervoxel ids and the sizes are of a supervoxel. If a label doesn't +// exist, a zero (not error) is returned. +func GetLabelSizes(d dvid.Data, v dvid.VersionID, labels []uint64, isSupervoxel bool) (sizes []uint64, err error) { + if isSupervoxel { + return getSupervoxelSizes(d, v, labels) + } + sizes = make([]uint64, len(labels)) for i, label := range labels { idx, err := GetLabelIndex(d, v, label, false) if err != nil { @@ -466,10 +490,6 @@ func GetLabelSizes(d dvid.Data, v dvid.VersionID, labels []uint64, isSupervoxel } if idx == nil { sizes[i] = 0 - continue - } - if isSupervoxel { - sizes[i] = idx.GetSupervoxelCount(supervoxels[i]) } else { sizes[i] = idx.NumVoxels() } diff --git a/datatype/labelmap/labelmap.go b/datatype/labelmap/labelmap.go index b177c647..c0c1d330 100644 --- a/datatype/labelmap/labelmap.go +++ b/datatype/labelmap/labelmap.go @@ -951,6 +951,23 @@ GET /node///sizes[?supervoxels=true] supervoxels If "true", interprets the given labels as a supervoxel ids. hash MD5 hash of request body content in hexidecimal string format. +GET /node///supervoxel-sizes/