public interface NDArray extends ArrayDescription
This interface defines the methods used to enquire information about an NDArray and to acquire access to its pixels for read and/or write.
The bulk data of an NDArray can be considered as a vector of values
of a given primitive type each labelled with a scalar offset (starting
at zero), or as an N-dimensional hyper-rectangle of such primitive values
each labelled with an N-element coordinate vector. The mapping between
the offsets and the coordinates is determined by an OrderedNDShape
object belonging to the NDArray.
To obtain acess to the pixel data itself it is necessary to obtain
an ArrayAccess object using the getAccess()
method. This provides
methods to move around within the NDArray and read/write arrays full
of pixels.
It is possible to access data a pixel at a time in this way, but this
is generally not very efficient, and it is better to read/write a
block of pixels to/from an array of moderate size. Since there
may be a large number of pixels (perhaps >2**31) in an NDArray
it is not in general possible to read/write all the pixel data
to/from a single primitive array, so for general processing it is
necessary to step through the pixel data processing chunks at a time.
The ChunkStepper
utility class is provided as a convenience
for this sort of processing. Here is a code snippet which uses
this technique to calculate statistics on all the pixels in an NDArray:
// Obtain the NDArray from somewhere. NDArray nda = ... // Get a reader object to access the pixel data. ArrayAccess reader = nda.getAccess(); // Get a ChunkStepper to assist in working through the data. long npix = nda.getShape().getNumPixels(); ChunkStepper chunkIt = new ChunkStepper( npix ); // Create a primitive buffer array of the right type for the NDArray, // long enough to hold the biggest chunk. Object buffer = nda.getType().newArray( chunkIt.getSize() ); // Step through the array in chunks, reading then processing a // buffer-full each time. for ( chunkIt.hasNext(); chunkIt.next() ) { int size = chunkIt.getSize(); reader.read( buffer, 0, size ); accumulateStatistics( buffer, 0, size ); } // Relinquish the reader to allow resources to be reclaimed. reader.close();In the above the
Type.newArray(int)
method is used to obtain a
buffer array of the same primitive type as the NDArray - this makes
it easier to write code which can process multiple numeric types
without having to write special cases for each numeric type.
However, if the NDArray was known to have a type of Type.FLOAT say,
this line could be replaced by
float[] buffer = new float[ chunkIt.getSize() ];
Read and write access are not always available; use the
ArrayDescription.isReadable()
and ArrayDescription.isWritable()
methods to determine
read/writablity.
While all NDArrays support one-time sequential access to the pixels from start to finish, some support other access modes.
ArrayDescription.isRandom()
method returns true,
then it is possible to use the ArrayAccess.setPosition(long[])
or
ArrayAccess.setOffset(long)
methods of the reader/writer to move backwards within the array
as well as forwards between accesses.
multipleAccess()
returns true,
it is possible to call the getAccess method more than once
for independent accesses to the data. This will always be the
case if isRandom is true.
ArrayAccess.isMapped()
method of the obtained ArrayAccess
object returns true, the NDArray
provides mapped access. This means that the
ArrayAccess.getMapped()
method will return a java primitive array
containing the entire content of the NDArray
If mapped access exists, it will be the most efficent way of accessing the data. The following code calculates statistics as above in the most efficent way it can, by using mapped access if available.
ArrayAccess reader = nda.getAccess(); if ( reader.isMapped() ) { accumulateStatistics( reader.getMapped() ); } else { ... step through in chunks as previous example }
An NDArray is normally created using the NDArrayFactory
class.
This class can also be used to obtain an NDArray with random access
from one which doesn't have it.
Modifier and Type | Method and Description |
---|---|
void |
close()
Declares that this NDArray will not be required for further use;
in particular that no further invocations will be made of the
getAccess method.
|
ArrayAccess |
getAccess()
Returns an object which can read and/or write the pixels of this
NDArray.
|
HdxFacade |
getHdxFacade(HdxResourceType hdxType)
Obtains a DOMFacade representing this array.
|
URL |
getURL()
Returns the URL of this NDArray, or null if it does not have one.
|
boolean |
multipleAccess()
Indicates whether multiple calls to the getAccess method may be
made.
|
getBadHandler, getShape, getType, isRandom, isReadable, isWritable
URL getURL()
boolean multipleAccess()
ArrayDescription.isRandom()
method returns true, but may do so even for non-random arrays.ArrayAccess getAccess() throws IOException
Each call to this method returns a new and independent
ArrayAccess object. However it may or may not be possible to
call it more than once; the multipleAccess()
method
indicates whether this is the case.
IOException
- if there is some I/O errorIllegalStateException
- if close has been called on this
NDArrayUnsupportedOperationException
- if multipleAccess returns
false and getAccess has already been invoked oncevoid close() throws IOException
This method should be invoked on an NDArray when it is no longer required for pixel access. This allows reclamation of non-memory resources, and in the case of writable arrays it may also be required to ensure that data is flushed from buffers back to the actual pixel array.
An array should not however be closed if some other object might
still require pixel access to it via a retained reference.
The general rule is that an application
which obtains a new NDArray from a URL should arrange for
close
to be called
on it at the end of its lifetime, but that utility routines which
perform operations on an NDArray should not close it after use
(though they should close any ArrayAccess
objects
which they take out).
Note that closing an NDArray will normally result in closing any
arrays which it wraps.
Multiple calls of this method may harmlessly be made.
IOException
- if some I/O error occurredHdxFacade getHdxFacade(HdxResourceType hdxType)
Since the array does not `know' which type of element it is
representing, this must be passed to it when the
DOMFacade
is created.
hdxType
- the type of the element which this array is
to representCopyright © 2024 Central Laboratory of the Research Councils. All Rights Reserved.