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

     1  package imageblk
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/json"
     7  	"fmt"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/janelia-flyem/dvid/datastore"
    12  	"github.com/janelia-flyem/dvid/dvid"
    13  	"github.com/janelia-flyem/dvid/server"
    14  )
    15  
    16  var (
    17  	floatimgT datastore.TypeService
    18  )
    19  
    20  func newFloatVolume(t *testing.T, offset, size dvid.Point3d) *testVolume {
    21  	var buf bytes.Buffer
    22  	for i := int64(0); i < size.Prod(); i++ {
    23  		if err := binary.Write(&buf, binary.LittleEndian, float32(i)); err != nil {
    24  			t.Fatalf("couldn't write to float volume: %v\n", err)
    25  		}
    26  	}
    27  	return &testVolume{
    28  		data:   buf.Bytes(),
    29  		offset: offset,
    30  		size:   size,
    31  	}
    32  }
    33  
    34  func createFloatTestVolume(t *testing.T, uuid dvid.UUID, name string, offset, size dvid.Point3d) *testVolume {
    35  	volume := newFloatVolume(t, offset, size)
    36  
    37  	// Send data over HTTP to populate a data instance
    38  	volume.put(t, uuid, name)
    39  	return volume
    40  }
    41  
    42  func TestFloatInstanceCreation(t *testing.T) {
    43  	if err := server.OpenTest(); err != nil {
    44  		t.Fatalf("can't open test server: %v\n", err)
    45  	}
    46  	defer server.CloseTest()
    47  
    48  	uuid, _ := datastore.NewTestRepo()
    49  
    50  	// Create new voxels instance with optional parameters
    51  	name := "weights"
    52  	metadata := fmt.Sprintf(`{
    53  		"typename": "float32blk",
    54  		"dataname": %q,
    55  		"blocksize": "64,43,28",
    56  		"VoxelSize": "13.1, 14.2, 15.3",
    57  		"VoxelUnits": "picometers,nanometers,microns"
    58  	}`, name)
    59  	apiStr := fmt.Sprintf("%srepo/%s/instance", server.WebAPIPath, uuid)
    60  	server.TestHTTP(t, "POST", apiStr, bytes.NewBufferString(metadata))
    61  
    62  	// Get metadata and make sure optional settings have been set.
    63  	apiStr = fmt.Sprintf("%snode/%s/%s/info", server.WebAPIPath, uuid, name)
    64  	result := server.TestHTTP(t, "GET", apiStr, nil)
    65  	var parsed = struct {
    66  		Base struct {
    67  			TypeName, Name string
    68  		}
    69  		Extended struct {
    70  			BlockSize  dvid.Point3d
    71  			VoxelSize  dvid.NdFloat32
    72  			VoxelUnits dvid.NdString
    73  		}
    74  	}{}
    75  	if err := json.Unmarshal(result, &parsed); err != nil {
    76  		t.Fatalf("Error parsing JSON response of new instance metadata: %v\n", err)
    77  	}
    78  	if parsed.Base.Name != name {
    79  		t.Errorf("Parsed new instance has unexpected name: %s != %s (expected)\n",
    80  			parsed.Base.Name, name)
    81  	}
    82  	if parsed.Base.TypeName != "float32blk" {
    83  		t.Errorf("Parsed new instance has unexpected type name: %s != uint8blk (expected)\n",
    84  			parsed.Base.TypeName)
    85  	}
    86  	if !parsed.Extended.BlockSize.Equals(dvid.Point3d{64, 43, 28}) {
    87  		t.Errorf("Bad block size in new uint8blk instance: %s\n", parsed.Extended.BlockSize)
    88  	}
    89  	if !parsed.Extended.VoxelSize.Equals(dvid.NdFloat32{13.1, 14.2, 15.3}) {
    90  		t.Errorf("Bad voxel size in new uint8blk instance: %s\n", parsed.Extended.VoxelSize)
    91  	}
    92  	if parsed.Extended.VoxelUnits[0] != "picometers" {
    93  		t.Errorf("Got %q for X voxel units, not picometers\n", parsed.Extended.VoxelUnits[0])
    94  	}
    95  	if parsed.Extended.VoxelUnits[1] != "nanometers" {
    96  		t.Errorf("Got %q for X voxel units, not picometers\n", parsed.Extended.VoxelUnits[0])
    97  	}
    98  	if parsed.Extended.VoxelUnits[2] != "microns" {
    99  		t.Errorf("Got %q for X voxel units, not picometers\n", parsed.Extended.VoxelUnits[0])
   100  	}
   101  }
   102  
   103  func TestFloatDirectCalls(t *testing.T) {
   104  	if err := server.OpenTest(); err != nil {
   105  		t.Fatalf("can't open test server: %v\n", err)
   106  	}
   107  	defer server.CloseTest()
   108  
   109  	uuid, versionID := initTestRepo()
   110  
   111  	server.CreateTestInstance(t, uuid, "float32blk", "floatimg", dvid.Config{})
   112  	dataservice, err := datastore.GetDataByUUIDName(uuid, "floatimg")
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	floatimg, ok := dataservice.(*Data)
   117  	if !ok {
   118  		t.Fatalf("Can't convert dataservice %v into imageblk.Data\n", dataservice)
   119  	}
   120  	ctx := datastore.NewVersionedCtx(floatimg, versionID)
   121  
   122  	// Create a block-aligned 8-bit grayscale image
   123  	offset := dvid.Point3d{512, 32, 1024}
   124  	size := dvid.Point3d{128, 96, 64}
   125  	subvol := dvid.NewSubvolume(offset, size)
   126  	testvol := createFloatTestVolume(t, uuid, "floatimg", offset, size)
   127  	origData := make([]byte, len(testvol.data))
   128  	copy(origData, testvol.data)
   129  
   130  	// Store it into datastore at root
   131  	v, err := floatimg.NewVoxels(subvol, testvol.data)
   132  	if err != nil {
   133  		t.Fatalf("Unable to make new floatimg voxels: %v\n", err)
   134  	}
   135  	if err = floatimg.IngestVoxels(versionID, 1, v, ""); err != nil {
   136  		t.Errorf("Unable to put voxels for %s: %v\n", ctx, err)
   137  	}
   138  
   139  	// Read the stored image
   140  	v2, err := floatimg.NewVoxels(subvol, nil)
   141  	if err != nil {
   142  		t.Errorf("Unable to make new grayscale ExtHandler: %v\n", err)
   143  	}
   144  	if err = floatimg.GetVoxels(versionID, v2, ""); err != nil {
   145  		t.Errorf("Unable to get voxels for %s: %v\n", ctx, err)
   146  	}
   147  
   148  	// Make sure the retrieved image matches the original
   149  	if v.Stride() != v2.Stride() {
   150  		t.Errorf("Stride in retrieved subvol incorrect\n")
   151  	}
   152  	if v.Interpolable() != v2.Interpolable() {
   153  		t.Errorf("Interpolable bool in retrieved subvol incorrect\n")
   154  	}
   155  	if !reflect.DeepEqual(v.Size(), v2.Size()) {
   156  		t.Errorf("Size in retrieved subvol incorrect: %s vs expected %s\n",
   157  			v2.Size(), v.Size())
   158  	}
   159  	if v.NumVoxels() != v2.NumVoxels() {
   160  		t.Errorf("# voxels in retrieved is different: %d vs expected %d\n",
   161  			v2.NumVoxels(), v.NumVoxels())
   162  	}
   163  	if len(v.Data()) != len(v2.Data()) {
   164  		t.Errorf("Expected %d bytes in retrieved data, got %d bytes\n", len(v.Data()), len(v2.Data()))
   165  	}
   166  	received := v2.Data()
   167  	//dvid.PrintNonZero("original value", origData)
   168  	//dvid.PrintNonZero("returned value", data)
   169  	for i := int64(0); i < v2.NumVoxels(); i++ {
   170  		if received[i] != origData[i] {
   171  			t.Logf("Data returned != data stored for voxel %d\n", i)
   172  			t.Logf("Size of data: %d bytes from GET, %d bytes in PUT\n", len(received), len(origData))
   173  			t.Fatalf("GET subvol (%d) != PUT subvol (%d) @ index %d", received[i], origData[i], i)
   174  		}
   175  	}
   176  }
   177  
   178  func TestFloat32RepoPersistence(t *testing.T) {
   179  	if err := server.OpenTest(); err != nil {
   180  		t.Fatalf("can't open test server: %v\n", err)
   181  	}
   182  	defer server.CloseTest()
   183  
   184  	uuid, _ := initTestRepo()
   185  
   186  	// Make grayscale and set various properties
   187  	config := dvid.NewConfig()
   188  	config.Set("BlockSize", "12,13,14")
   189  	config.Set("VoxelSize", "1.1,2.8,11")
   190  	config.Set("VoxelUnits", "microns,millimeters,nanometers")
   191  	dataservice, err := datastore.NewData(uuid, floatimgT, "floatimg", config)
   192  	if err != nil {
   193  		t.Errorf("Unable to create float32 instance: %s\n", err)
   194  	}
   195  	floatimg, ok := dataservice.(*Data)
   196  	if !ok {
   197  		t.Errorf("Can't cast float32 data service into Data\n")
   198  	}
   199  	oldData := *floatimg
   200  
   201  	// Restart test datastore and see if datasets are still there.
   202  	if err = datastore.SaveDataByUUID(uuid, floatimg); err != nil {
   203  		t.Fatalf("Unable to save repo during floatimg persistence test: %v\n", err)
   204  	}
   205  	datastore.CloseReopenTest()
   206  
   207  	dataservice2, err := datastore.GetDataByUUIDName(uuid, "floatimg")
   208  	if err != nil {
   209  		t.Fatalf("Can't get floatimg instance from reloaded test db: %v\n", err)
   210  	}
   211  	floatimg2, ok := dataservice2.(*Data)
   212  	if !ok {
   213  		t.Errorf("Returned new data instance 2 is not imageblk.Data\n")
   214  	}
   215  	if !oldData.Equals(floatimg2) {
   216  		t.Errorf("Expected %v, got %v\n", oldData, *floatimg2)
   217  	}
   218  }