All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.ma2.ArrayStructureMA Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */
package ucar.ma2;

import ucar.nc2.Structure;
import ucar.nc2.Variable;
import ucar.nc2.Sequence;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Concrete implementation of ArrayStructure, data storage is in member arrays, which are converted to
 * StructureData member data on the fly.
 * This defers object creation for efficiency. Use getJavaArrayXXX() and getScalarXXX() data accessors if
 * possible.
 *
 * How to create:
 * 
 * 
 * ArrayStructureMA asma = new ArrayStructureMA(smembers, getShape());
 * for (int i = 0; i < orgVariables.size(); i++) {
 *   Variable v = (Variable) orgVariables.get(i);
 *   Array data = v.read();
 *   asma.setMemberArray(v.getName(), data);
 * }
 * 
* * How to do Nested Structures: * *
  Structure {
    float f1;
    short f2(3);

    Structure {
      int g1;
      double(2) g2;
      double(3,4) g3;

      Structure {
        int h1;
        double(2) h2;
      } nested2(7);

    } nested1(12);
  } s(4);
 * 
*
    *
  • For f1, you need an ArrayFloat of shape {4} *
  • For f2, you need an ArrayShort of shape {4, 3} . *
  • For nested1, you need an ArrayStructure of shape {4, 12}. * Use an ArrayStructureMA that has 3 members: *
      *
    • For g1, you need an ArrayInt of shape (4, 12} *
    • For g2, you need an ArrayDouble of shape {4, 12, 2}. *
    • For g3, you need an ArrayDouble of shape {4, 12, 3, 4}. *
    *
  • For nested2, you need an ArrayStructure of shape {4, 12, 7}. * Use an ArrayStructureMA that has 2 members: *
      *
    • For h1, you need an ArrayInt of shape (4, 12, 7} *
    • For h2, you need an ArrayDouble of shape {4, 12, 7, 2}. *
    *
* Example code: * *
 * public void testMA() throws IOException, InvalidRangeException {
 *   StructureMembers members = new StructureMembers("s");
 * 
 *   StructureMembers.Member m = members.addMember("f1", "desc", CDM.UNITS, DataType.FLOAT, new int[] {1});
 *   Array data = Array.factory(DataType.FLOAT, new int[] {4});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("f2", "desc", CDM.UNITS, DataType.SHORT, new int[] {3});
 *   data = Array.factory(DataType.SHORT, new int[] {4, 3});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("nested1", "desc", CDM.UNITS, DataType.STRUCTURE, new int[] {9});
 *   data = makeNested1(m);
 *   m.setDataArray(data);
 * 
 *   ArrayStructureMA as = new ArrayStructureMA(members, new int[] {4});
 *   new TestStructureArray().testArrayStructure(as);
 * 
 *   // get f2 out of the 3nd "s"
 *   StructureMembers.Member f2 = as.getStructureMembers().findMember("f2");
 *   short[] f2data = as.getJavaArrayShort(2, f2);
 *   assert f2data[0] == 20;
 *   assert f2data[1] == 21;
 *   assert f2data[2] == 22;
 * 
 *   // get nested1 out of the 3nd "s"
 *   StructureMembers.Member nested1 = as.getStructureMembers().findMember("nested1");
 *   ArrayStructure nested1Data = as.getArrayStructure(2, nested1);
 * 
 *   // get g1 out of the 7th "nested1"
 *   StructureMembers.Member g1 = nested1Data.getStructureMembers().findMember("g1");
 *   int g1data = nested1Data.getScalarInt(6, g1);
 *   assert g1data == 26;
 * 
 *   // get nested2 out of the 7th "nested1"
 *   StructureMembers.Member nested2 = nested1Data.getStructureMembers().findMember("nested2");
 *   ArrayStructure nested2Data = nested1Data.getArrayStructure(6, nested2);
 * 
 *   // get h1 out of the 4th "nested2"
 *   StructureMembers.Member h1 = nested2Data.getStructureMembers().findMember("h1");
 *   int val = nested2Data.getScalarInt(4, h1);
 *   assert (val == 264);
 * }
 * 
 * 
 * public ArrayStructure makeNested1(StructureMembers.Member parent) throws IOException, InvalidRangeException {
 *   StructureMembers members = new StructureMembers(parent.getName());
 *   parent.setStructureMembers(members);
 * 
 *   StructureMembers.Member m = members.addMember("g1", "desc", CDM.UNITS, DataType.INT, new int[] {1});
 *   Array data = Array.factory(DataType.INT, new int[] {4, 9});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("g2", "desc", CDM.UNITS, DataType.DOUBLE, new int[] {2});
 *   data = Array.factory(DataType.DOUBLE, new int[] {4, 9, 2});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("g3", "desc", CDM.UNITS, DataType.DOUBLE, new int[] {3, 4});
 *   data = Array.factory(DataType.DOUBLE, new int[] {4, 9, 3, 4});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("nested2", "desc", CDM.UNITS, DataType.STRUCTURE, new int[] {7});
 *   data = makeNested2(m);
 *   m.setDataArray(data);
 * 
 *   return new ArrayStructureMA(members, new int[] {4, 9});
 * }
 * 
 * public ArrayStructure makeNested2(StructureMembers.Member parent) throws IOException, InvalidRangeException {
 *   StructureMembers members = new StructureMembers(parent.getName());
 *   parent.setStructureMembers(members);
 * 
 *   StructureMembers.Member m = members.addMember("h1", "desc", CDM.UNITS, DataType.INT, new int[] {1});
 *   Array data = Array.factory(DataType.INT, new int[] {4, 9, 7});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   m = members.addMember("h2", "desc", CDM.UNITS, DataType.DOUBLE, new int[] {2});
 *   data = Array.factory(DataType.DOUBLE, new int[] {4, 9, 7, 2});
 *   m.setDataArray(data);
 *   fill(data);
 * 
 *   return new ArrayStructureMA(members, new int[] {4, 9, 7});
 * }
 * 
* * @author caron * @see Array */ public class ArrayStructureMA extends ArrayStructure { /* * Implementation notes * Most of the methods are now the default methods in the superclass, so that other subclasses can call them. * This happens when the data is "enhanced", member arrays are set and must override the other possible storage * methods. */ /** * Create a new Array of type StructureData and the given members and shape. *

* You must set the data Arrays on each of the Members, using setDataObject(). These data Arrays contain the data * for that member Variable, for all the StructureData. Therefore it has rank one greater that the Members. The extra * dimension must be the outermost (slowest varying) dimension. ie, if some member has shape [3,10], the array would * have * shape [nrows, 3, 10]. * * @param members a description of the structure members * @param shape the shape of the Array. */ public ArrayStructureMA(StructureMembers members, int[] shape) { super(members, shape); } public ArrayStructureMA(StructureMembers members, int[] shape, StructureData[] sdata) { super(members, shape); if (nelems != sdata.length) throw new IllegalArgumentException("StructureData length= " + sdata.length + "!= shape.length=" + nelems); this.sdata = sdata; } /** * Turn any ArrayStructure into a ArrayStructureMA * * @param from copy from here. If from is a ArrayStructureMA, return it. * @return equivalent ArrayStructureMA * @throws java.io.IOException on error reading a sequence */ public static ArrayStructureMA factoryMA(ArrayStructure from) throws IOException { if (from instanceof ArrayStructureMA) return (ArrayStructureMA) from; // To create an ArrayStructureMA that we can iterate over later, we need to know the shape of "from". if (from.getSize() > 0) { ArrayStructureMA to = new ArrayStructureMA(from.getStructureMembers().toBuilder(false).build(), from.getShape()); for (StructureMembers.Member m : from.getMembers()) { to.setMemberArray(m.getName(), from.extractMemberArray(m)); } return to; } // from.getSize() <= 0. This usually means that "from" is an ArraySequence, and that we won't know its size until // we iterate over it. extractMemberArray() will do that iteration for us, and then we can use the size of the // array it returns to determine the shape of "from". int numRecords = -1; Map memberArrayMap = new LinkedHashMap<>(); for (StructureMembers.Member m : from.getMembers()) { Array array = from.extractMemberArray(m); assert array.getSize() > 0 : "array's size should have been computed in extractMemberArray()."; int firstDimLen = array.getShape()[0]; if (numRecords == -1) { numRecords = firstDimLen; } else { assert numRecords == firstDimLen : String.format( "Expected all structure members to have the same first" + "dimension length, but %d != %d.", numRecords, firstDimLen); } memberArrayMap.put(m.getName(), array); } int[] shape; if (numRecords == -1) { shape = new int[] {0}; // "from" really was empty. } else { shape = new int[] {numRecords}; } ArrayStructureMA to = new ArrayStructureMA(from.getStructureMembers().toBuilder(false).build(), shape); for (Map.Entry entry : memberArrayMap.entrySet()) { to.setMemberArray(entry.getKey(), entry.getValue()); } return to; } @Override protected StructureData makeStructureData(ArrayStructure as, int index) { return new StructureDataA(as, index); } /** * Set the data array for this member. * * @param memberName name of member * @param data Array for this member. */ public void setMemberArray(String memberName, Array data) { StructureMembers.Member m = members.findMember(memberName); m.setDataArray(data); } public Array getArray(int recno, StructureMembers.Member m) { if (m.isVariableLength()) { Array data = m.getDataArray(); if (data instanceof ArrayObject) { ArrayObject ao = (ArrayObject) data; Object dao = ao.getObject(recno); assert dao instanceof Array; return (Array) dao; } } return super.getArray(recno, m); } /** * Create an ArrayStructure for a Structure. Allow nested Structures. * Create the data arrays, and an iterator. * * @param from copy from here. If from is a ArrayStructureMA, return it. * @param shape the shape of the ArrayStructure * @return equivilent ArrayStructureMA */ public static ArrayStructureMA factoryMA(Structure from, int[] shape) { StructureMembers sm = from.makeStructureMembers(); for (Variable v : from.getVariables()) { Array data; if (v instanceof Sequence) { data = Array.factory(DataType.SEQUENCE, shape); // an array sequence - one for each parent element // Structure s = (Structure) v; // StructureMembers smn = s.makeStructureMembers(); // data = new ArraySequenceNested(smn, (int) Index.computeSize(v.getShapeAll())); // ?? } else if (v instanceof Structure) data = ArrayStructureMA.factoryMA((Structure) v, combine(shape, v.getShape())); else data = Array.factory(v.getDataType(), combine(shape, v.getShape())); StructureMembers.Member m = sm.findMember(v.getShortName()); m.setDataArray(data); } return new ArrayStructureMA(sm, shape); } private static int[] combine(int[] shape1, int[] shape2) { int[] result = new int[shape1.length + shape2.length]; System.arraycopy(shape1, 0, result, 0, shape1.length); System.arraycopy(shape2, 0, result, shape1.length, shape2.length); return result; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy