
example.DataViews Maven / Gradle / Ivy
/*
* Zorbage: an algebraic data hierarchy for use in numeric processing.
*
* Copyright (c) 2016-2021 Barry DeZonia All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* Neither the name of the nor the names of its contributors may
* be used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package example;
import nom.bdezonia.zorbage.algebra.G;
import nom.bdezonia.zorbage.algorithm.GridIterator;
import nom.bdezonia.zorbage.data.DimensionedDataSource;
import nom.bdezonia.zorbage.data.DimensionedStorage;
import nom.bdezonia.zorbage.datasource.IndexedDataSource;
import nom.bdezonia.zorbage.dataview.FiveDView;
import nom.bdezonia.zorbage.dataview.OneDView;
import nom.bdezonia.zorbage.dataview.ThreeDView;
import nom.bdezonia.zorbage.dataview.TwoDView;
import nom.bdezonia.zorbage.sampling.IntegerIndex;
import nom.bdezonia.zorbage.sampling.SamplingIterator;
import nom.bdezonia.zorbage.storage.Storage;
import nom.bdezonia.zorbage.storage.array.ArrayStorageSignedInt16;
import nom.bdezonia.zorbage.type.integer.int16.SignedInt16Member;
import nom.bdezonia.zorbage.type.real.float32.Float32Member;
/**
*
* @author Barry DeZonia
*
*/
class DataViews {
// Zorbage defines a very fast data accessor facility for multidimensional
// data known as data views. When your algorithm knows the exact number of
// dimensions it works in it can take a data source of those same number
// of dimensions and wrap a view around it.
// Views come in many dimensions. There is one for every dimension (at the
// moment) between 1 and 21. A 1-d view is defined by the OneDView class.
// A 4-d view is defined by the FourDView class. You can probably guess
// what a 21-d view is defined as.
// One reason to use views is because they are very simple to declare and
// use to make clear algorithms. Sometimes the regular DimensionedDataSource
// approach is slow and unclear. Maybe an example will help.
void example1() {
// create a 5-d float32 data source
Float32Member value = G.FLT.construct();
long X = 200;
long Y = 200;
long Z = 40;
long C = 4;
long T = 100;
long[] dims = new long[] {X, Y, Z, C, T};
DimensionedDataSource dataSource =
DimensionedStorage.allocate(G.FLT.construct(), dims);
// set every value to 3:
// note: you would never do it this way. use the Fill algo on DS.RawData.
value.setV(3);
SamplingIterator iter = GridIterator.compute(dataSource);
IntegerIndex idx = new IntegerIndex(dataSource.numDimensions());
while (iter.hasNext()) {
iter.next(idx);
dataSource.set(idx, value);
}
// this is successful but can be quite slow
}
// an example that uses a data view
void example2() {
// create a 5-d float32 data source
Float32Member value = G.FLT.construct();
long X = 200;
long Y = 200;
long Z = 40;
long C = 4;
long T = 100;
long[] dims = new long[] {X, Y, Z, C, T};
DimensionedDataSource dataSource =
DimensionedStorage.allocate(G.FLT.construct(), dims);
// set every value to 3:
// note: much clearer and faster way: still use the Fill algo on DS.RawData.
value.setV(3);
FiveDView view = new FiveDView<>(dataSource);
for (long t = 0; t < view.d4(); t++) {
for (long c = 0; c < view.d3(); c++) {
for (long z = 0; z < view.d2(); z++) {
for (long y = 0; y < view.d1(); y++) {
for (long x = 0; x < view.d0(); x++) {
view.set(x, y, z, c, t, value);
}
}
}
}
}
value.setV(-1);
view.get(X-1, Y-1, Z-1, C-1, T-1, value);
if (value.v() != 2) System.out.println("View failed");
// this code is successful and can run as much as 10X faster
// than the default multidimensional code above
}
// One thing about data views is that they allow you to grab any subset
// of data you can express in nested for loops.
void example3() {
// create a 3-d float32 data source
long X = 200;
long Y = 200;
long Z = 40;
long[] dims = new long[] {X, Y, Z};
DimensionedDataSource dataSource =
DimensionedStorage.allocate(G.FLT.construct(), dims);
// find the sum of values in a 3x3 box in upper left corner of 4th z plane
Float32Member sum = G.FLT.construct();
Float32Member tmp = G.FLT.construct();
ThreeDView view = new ThreeDView<>(dataSource);
long z = 4-1; // 4th plane is at index 3
for (long y = 0; y < 3; y++) {
for (long x = 0; x < 3; x++) {
view.get(x, y, z, tmp);
G.FLT.add().call(sum, tmp, sum);
}
}
System.out.println(sum);
}
// One can define all kinds of regions via for loops such as pipeds,
// planes, volumes (plane collections), hypervolumes, one channel of
// a whole multichannel dataset, etc. You can take every 5th value
// along the time axis etc.
// You can construct data views from a DimensionedDataSource or an
// IndexedDataSource. Data views do not respect out of bounds
// policies for a given source. It is assumed you will always access
// a data view in bounds. You can call the safeSet()/safeGet()
// methods. They bounds check but simply abort their operation
// with an error exception.
// Here is an example of this using an IndexedDataSource
void example4() {
IndexedDataSource data =
Storage.allocate(G.FLT.construct(), 100);
OneDView view = new OneDView<>(data.size(),data);
Float32Member value = G.FLT.construct();
value.setV(0);
view.get(-data.size(), value); // may poke a random memory location
view.safeGet(-data.size(), value); // will throw an index oob exception
view.get(data.size()*2, value); // may poke a random memory location
view.safeGet(data.size()*2, value); // will throw an index oob exception
}
// And here is an example of this using a DimensionedDataSource
void example5() {
long[] dims = new long[] {100, 100, 25}; // x, y, z
DimensionedDataSource dds =
DimensionedStorage.allocate(G.FLT.construct(), dims);
ThreeDView view = new ThreeDView<>(dds);
Float32Member value = G.FLT.construct();
view.get(50, 50, -1, value); // may poke a random memory location
view.safeGet(50, 50, -1, value); // will throw an index oob exception
view.get(50, 50, 1000000, value); // may poke a random memory location
view.safeGet(50, 50, 1000000, value); // will throw an index oob exception
}
// One nice thing about a data view is that you can enforce a shape to
// the data you might prefer. For instance, given a 1-d list of storage
// you might want to wrap it like a 2-d dataset and manipulate values
// as you desire.
void example6() {
IndexedDataSource nums =
new ArrayStorageSignedInt16<>(G.INT16.construct(), 64);
TwoDView view = new TwoDView<>(8, 8, nums);
SignedInt16Member value = G.INT16.construct();
for (long y = 0; y < view.d1(); y++) {
for (long x = 0; x < view.d0(); x++) {
value.setV((int) x);
view.set(x, y, value);
}
}
// Note that this is also possible with DimensionedDataSources
// in an indirect fashion. Normally a view that takes a
// DimensionedDataSource as input just uses the dimensions of
// the source. But you can create a redimensioned source by
// passing the dimensionedDataSource.rawData() to a view
// constructor and specify the new dimensions.
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy