ucar.ma2.ArrayStructure Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of netcdf Show documentation
Show all versions of netcdf Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
The newest version!
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "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 UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.ma2;
import java.io.IOException;
import java.util.Formatter;
import java.util.List;
import java.nio.ByteBuffer;
/**
* Superclass for implementations of Array of StructureData.
*
* The general way to access data in an ArrayStructure is to use
* StructureData getStructureData(Index index).
*
* For 1D arrays (or by caclulating your own recnum for nD arrays), you can also use:
* StructureData getStructureData(int recnum).
*
* Once you have a StructureData object, you can access data in a general way by using:
* Array StructureData.getArray(Member m)
*
* When dealing with large arrays of Structures, there can be significant overhead in using the generic interfaces.
* A number of convenience routines may be able to avoid extra Object creation, and so are recommended for efficiency.
* The following may avoid the overhead of creating the StructureData object:
* Array getArray(int recno, StructureMembers.Member m)
*
* The following can be convenient for accessing all the data in the ArrayStructure for one member, but its efficiency
* depends on the implementation:
* Array getMemberArray(StructureMembers.Member m)
*
* These require that you know the data types of the member data, but they are the most efficent:
*
* getScalarXXX(int recnum, Member m)
* getJavaArrayXXX(int recnum, Member m)
* where XXX is Byte, Char, Double, Float, Int, Long, Short, or String. For members that are themselves Structures,
* the equivilent is:
*
* StructureData getScalarStructure(int recnum, Member m)
* ArrayStructure getArrayStructure(int recnum, Member m)
*
* These will return any compatible type as a double or float, but will have extra overhead when the types dont match:
*
* convertScalarXXX(int recnum, Member m)
* convertJavaArrayXXX(int recnum, Member m)
* where XXX is Double or Float
*
* @author caron
* @see Array
* @see StructureData
*/
public abstract class ArrayStructure extends Array {
/* Implementation notes
ArrayStructure contains the default implementation of storing the data in individual member arrays.
ArrayStructureMA uses all of these.
ArrayStructureW uses some of these.
ArrayStructureBB override all such methods.
*/
protected StructureMembers members;
protected int nelems;
protected StructureData[] sdata;
/**
* Create a new Array of type StructureData and the given members and shape.
* dimensions.length determines the rank of the new Array.
*
* @param members a description of the structure members
* @param shape the shape of the Array.
*/
protected ArrayStructure(StructureMembers members, int[] shape) {
super(shape);
this.members = members;
this.nelems = (int) indexCalc.getSize();
}
// for subclasses to create views
protected ArrayStructure(StructureMembers members, Index ima) {
super(ima);
this.members = members;
this.nelems = (int) indexCalc.getSize();
}
// copy from javaArray to storage using the iterator: used by factory( Object);
protected void copyFrom1DJavaArray(IndexIterator iter, Object javaArray) {
Object[] ja = (Object[]) javaArray;
for (Object aJa : ja)
iter.setObjectNext(aJa);
}
// copy to javaArray from storage using the iterator: used by copyToNDJavaArray;
protected void copyTo1DJavaArray(IndexIterator iter, Object javaArray) {
Object[] ja = (Object[]) javaArray;
for (int i = 0; i < ja.length; i++)
ja[i] = iter.getObjectNext();
}
public Class getElementType() {
return StructureData.class;
}
/**
* Get the StructureMembers object.
* @return the StructureMembers object.
*/
public StructureMembers getStructureMembers() {
return members;
}
/**
* Get a list of structure members.
* @return the structure members.
*/
public List getMembers() {
return members.getMembers();
}
/**
* Get a list structure member names.
* @return the structure members.
*/
public List getStructureMemberNames() {
return members.getMemberNames();
}
/**
* Find a member by its name.
*
* @param memberName find member with this name
* @return StructureMembers.Member matching the name, or null if not found
*/
public StructureMembers.Member findMember(String memberName) {
return members.findMember(memberName);
}
@Override
public long getSizeBytes() {
return indexCalc.getSize() * members.getStructureSize();
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param i which one to get, specified by an Index.
* @return object of type StructureData.
*/
public Object getObject(Index i) {
return getObject(i.currentElement());
}
/**
* Set one of the StructureData of this ArrayStructure.
*
* @param i which one to set, specified by an Index.
* @param value must be type StructureData.
*/
public void setObject(Index i, Object value) {
setObject(i.currentElement(), value);
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param index which one to get, specified by an integer.
* @return object of type StructureData.
*/
public Object getObject(int index) {
return getStructureData(index);
}
/**
* Set the index-th StructureData of this ArrayStructure.
*
* @param index which one to set.
* @param value must be type StructureData.
*/
public void setObject(int index, Object value) {
if (sdata == null)
sdata = new StructureData[nelems];
sdata[index] = (StructureData) value;
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param i which one to get, specified by an Index.
* @return object of type StructureData.
*/
public StructureData getStructureData(Index i) {
return getStructureData(i.currentElement());
}
/**
* Get the index-th StructureData of this ArrayStructure.
*
* @param index which one to get, specified by an integer.
* @return object of type StructureData.
*/
public StructureData getStructureData(int index) {
if (sdata == null)
sdata = new StructureData[nelems];
if (index >= sdata.length)
throw new IllegalArgumentException(index + " > " + sdata.length);
if (sdata[index] == null)
sdata[index] = makeStructureData(this, index);
return sdata[index];
}
public Object getStorage() {
// this fills the sdata array
for (int i = 0; i < nelems; i++)
getStructureData(i);
return sdata;
}
abstract protected StructureData makeStructureData(ArrayStructure as, int recno);
/**
* Get the size of each StructureData object in bytes.
*
* @return the size of each StructureData object in bytes.
*/
public int getStructureSize() {
return members.getStructureSize();
}
public StructureDataIterator getStructureDataIterator() { // throws java.io.IOException {
return new ArrayStructureIterator();
}
public class ArrayStructureIterator implements StructureDataIterator {
private int count = 0;
private int size = (int) getSize();
@Override
public boolean hasNext() throws IOException {
return count < size;
}
@Override
public StructureData next() throws IOException {
return getStructureData(count++);
}
@Override
public void setBufferSize(int bytes) {
}
@Override
public StructureDataIterator reset() {
count = 0;
return this;
}
@Override
public int getCurrentRecno() {
return count-1;
}
@Override
public void finish() {
}
// debugging
public ArrayStructure getArrayStructure() { return ArrayStructure.this; }
}
///////////////////////////////////////////////////////////////////////////////
/**
* Get member data of any type for a specific record as an Array.
* This may avoid the overhead of creating the StructureData object, but is equivilent to
* getStructure(recno).getArray( Member m).
*
* @param recno get data from the recnum-th StructureData of the ArrayStructure. Must be less than getSize();
* @param m get data from this StructureMembers.Member.
* @return Array values.
*/
public Array getArray(int recno, StructureMembers.Member m) {
DataType dataType = m.getDataType();
if (dataType == DataType.DOUBLE) {
double[] pa = getJavaArrayDouble(recno, m);
return Array.factory(double.class, m.getShape(), pa);
} else if (dataType == DataType.FLOAT) {
float[] pa = getJavaArrayFloat(recno, m);
return Array.factory(float.class, m.getShape(), pa);
} else if ((dataType == DataType.BYTE) || (dataType == DataType.ENUM1)) {
byte[] pa = getJavaArrayByte(recno, m);
return Array.factory(byte.class, m.getShape(), pa);
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = getJavaArrayShort(recno, m);
return Array.factory(short.class, m.getShape(), pa);
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = getJavaArrayInt(recno, m);
return Array.factory(int.class, m.getShape(), pa);
} else if (dataType == DataType.LONG) {
long[] pa = getJavaArrayLong(recno, m);
return Array.factory(long.class, m.getShape(), pa);
} else if (dataType == DataType.CHAR) {
char[] pa = getJavaArrayChar(recno, m);
return Array.factory(char.class, m.getShape(), pa);
} else if (dataType == DataType.STRING) {
String[] pa = getJavaArrayString(recno, m);
return Array.factory(String.class, m.getShape(), pa);
} else if (dataType == DataType.STRUCTURE) {
return getArrayStructure(recno, m);
} else if (dataType == DataType.SEQUENCE) {
return getArraySequence(recno, m);
} else if (dataType == DataType.OPAQUE) {
return getArrayObject(recno, m);
}
throw new RuntimeException("Dont have implemenation for " + dataType);
}
/**
* Set data for one member, over all structures.
* This is used by VariableDS to do scale/offset.
*
* @param m set data for this StructureMembers.Member.
* @param memberArray Array values.
*/
public void setMemberArray(StructureMembers.Member m, Array memberArray) {
m.setDataArray(memberArray);
if (memberArray instanceof ArrayStructure) { // LOOK
ArrayStructure as = (ArrayStructure) memberArray;
m.setStructureMembers( as.getStructureMembers());
}
}
/**
* Extract data for one member, over all structures.
*
* @param m get data from this StructureMembers.Member.
* @return Array values.
* @throws java.io.IOException on read error (only happens for Sequences, otherwise data is already read)
*/
public Array extractMemberArray(StructureMembers.Member m) throws IOException {
if (m.getDataArray() != null)
return m.getDataArray();
DataType dataType = m.getDataType();
/* special handling for sequences
if (dataType == DataType.SEQUENCE) {
List sdataList = new ArrayList();
for (int recno=0; recno