Hi,
Thanks for your reply!
This example seems to be similar but in my case it still doesn’t work, don’t know why.
Here are the methods I use:
Create:
public static void CreateDataArray(string arrayUri, double minX, double maxX, double minY, double maxY, double xTileSize, double yTileSize)
{
// Create context
using TileDB.Context ctx = new TileDB.Context();
// Create array if doesn't exist
using TileDB.VFS vfs = new TileDB.VFS(ctx);
if (!vfs.is_dir(arrayUri))
{
// Create domain and add a dimension
using TileDB.Domain dom = new TileDB.Domain(ctx);
dom.add_double_dimension("x", minX, maxX, xTileSize);
dom.add_double_dimension("y", minY, maxY, yTileSize);
// Create array schema for a dense array, add domain and set tile and cell order
using TileDB.ArraySchema schema = new TileDB.ArraySchema(ctx, TileDB.ArrayType.TILEDB_SPARSE);
schema.set_domain(dom);
schema.set_order(TileDB.LayoutType.TILEDB_ROW_MAJOR, TileDB.LayoutType.TILEDB_ROW_MAJOR);
schema.set_allows_dups(true);
// Create and add data attribute and compression filter to schema
using TileDB.Attribute attr1 = TileDB.Attribute.create_attribute(ctx, "data", TileDB.DataType.TILEDB_STRING_ASCII);
using TileDB.Filter compression = new TileDB.Filter(ctx, TileDB.FilterType.TILEDB_FILTER_GZIP);
using TileDB.FilterList filterList = new TileDB.FilterList(ctx);
filterList.add_filter(compression);
attr1.set_filter_list(filterList);
schema.add_attribute(attr1);
// Create the array
TileDB.Array.create(arrayUri, schema);
}
}
Write:
// Coordinate and data arrays contain the same amount of elements
// String elements may contain different number of characters but not more than 12 characters
public static void WriteToArray(string arrayUri, double[] xCoords, double[] yCoords, string[] data)
{
// Create context
using TileDB.Context ctx = new TileDB.Context();
// Create char vector to split string array to char array and long vector to store offsets
using TileDB.VectorDouble xVector = new TileDB.VectorDouble(xCoords);
using TileDB.VectorDouble yVector = new TileDB.VectorDouble(yCoords);
using TileDB.VectorChar dataVector = new TileDB.VectorChar();
using TileDB.VectorUInt64 dataOffsets = new TileDB.VectorUInt64();
// Fill vectors with data array to write
uint offset = 0;
foreach (string value in data)
{
dataVector.AddRange(new TileDB.VectorChar(value.ToCharArray()));
dataOffsets.Add(offset);
offset += (uint)value.Length;
}
// Open array for writing
using TileDB.Array array = new TileDB.Array(ctx, arrayUri, TileDB.QueryType.TILEDB_WRITE);
// Create the query
using TileDB.Query query = new TileDB.Query(ctx, array, TileDB.QueryType.TILEDB_WRITE);
query.set_layout(TileDB.LayoutType.TILEDB_UNORDERED);
query.set_char_vector_buffer_with_offsets("data", dataVector, dataOffsets);
query.set_double_vector_buffer("x", xVector);
query.set_double_vector_buffer("y", yVector);
// Submit query
query.submit();
// Close the array
array.close();
}
Read:
// Have tried different min and max values but it works only when integer part of each variable is increased/decreased
private static (double[], double[], string[]) ReadDataArray(string arrayUri, int elementCount, double minX, double maxX, double minY, double maxY)
{
// Create context
using TileDB.Context ctx = new TileDB.Context();
// Vector to store coordinates, data and character offset. Multiplication value may be changed depending on the largest value size
using TileDB.VectorDouble xCoords = TileDB.VectorDouble.Repeat(0, elementCount);
using TileDB.VectorDouble yCoords = TileDB.VectorDouble.Repeat(0, elementCount);
using TileDB.VectorUInt64 dataOffset = TileDB.VectorUInt64.Repeat(0, elementCount);
using TileDB.VectorChar data = TileDB.VectorChar.Repeat(' ', elementCount * 12);
// Open array for read
using TileDB.Array array = new TileDB.Array(ctx, arrayUri, TileDB.QueryType.TILEDB_READ);
TileDB.ArraySchema schema = new TileDB.ArraySchema(ctx, arrayUri);
// Construct the query
using TileDB.Query query = new TileDB.Query(ctx, array, TileDB.QueryType.TILEDB_READ);
query.set_layout(TileDB.LayoutType.TILEDB_GLOBAL_ORDER);
query.set_double_vector_buffer("x", xCoords);
query.set_double_vector_buffer("y", yCoords);
query.set_char_vector_buffer_with_offsets("data", data, dataOffset);
TileDB.VectorString range1 = new TileDB.VectorString() { minX.ToString(), maxX.ToString() };
query.add_range_from_str_vector(0, range1);
TileDB.VectorString range2 = new TileDB.VectorString() { minY.ToString(), maxY.ToString() };
query.add_range_from_str_vector(1, range2);
query.submit();
query.finalize();
using TileDB.MapStringVectorUInt64 bufferElements = query.result_buffer_elements();
array.close();
// This output already returns less elements than expected
Console.WriteLine($"bufferElements[0]: {bufferElements["data"][0]}");
// Parse the result to an array
ulong resultElementOffset = bufferElements["data"][0];
ulong resultElementSize = bufferElements["data"][1];
using TileDB.VectorUInt64 dataSizes = new TileDB.VectorUInt64();
for (int i = 0; i < ((int)resultElementOffset - 1); ++i)
{
dataSizes.Add(dataOffset[i + 1] - dataOffset[i]);
}
dataSizes.Add(resultElementSize * TileDB.EnumUtil.datatype_size(TileDB.DataType.TILEDB_CHAR) - dataOffset[(int)resultElementOffset - 1]);
string[] dataArray = new string[(int)resultElementOffset];
for (int i = 0; i < (int)resultElementOffset; ++i)
{
dataArray[i] = new string(data.GetRange((int)dataOffset[i], (int)dataSizes[i]).ToArray());
}
// This output matches previous one
Console.WriteLine(dataArray.Length);
// Clean up unused elements in vectors
xCoords.RemoveRange(dataArray.Length, elementCount - dataArray.Length);
yCoords.RemoveRange(dataArray.Length, elementCount - dataArray.Length);
return (xCoords.ToArray(), yCoords.ToArray(), dataArray);
}