001    /*
002     * This file is part of McIDAS-V
003     *
004     * Copyright 2007-2013
005     * Space Science and Engineering Center (SSEC)
006     * University of Wisconsin - Madison
007     * 1225 W. Dayton Street, Madison, WI 53706, USA
008     * https://www.ssec.wisc.edu/mcidas
009     * 
010     * All Rights Reserved
011     * 
012     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013     * some McIDAS-V source code is based on IDV and VisAD source code.  
014     * 
015     * McIDAS-V is free software; you can redistribute it and/or modify
016     * it under the terms of the GNU Lesser Public License as published by
017     * the Free Software Foundation; either version 3 of the License, or
018     * (at your option) any later version.
019     * 
020     * McIDAS-V is distributed in the hope that it will be useful,
021     * but WITHOUT ANY WARRANTY; without even the implied warranty of
022     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023     * GNU Lesser Public License for more details.
024     * 
025     * You should have received a copy of the GNU Lesser Public License
026     * along with this program.  If not, see http://www.gnu.org/licenses.
027     */
028    
029    package edu.wisc.ssec.mcidasv.data.hydra;
030    
031    import visad.FlatField;
032    import visad.VisADException;
033    import visad.RealType;
034    import visad.SetType;
035    import visad.FunctionType;
036    import visad.Set;
037    import java.rmi.RemoteException;
038    import java.util.HashMap;
039    import java.util.Iterator;
040    
041    public abstract class MultiDimensionAdapter {
042    
043       MultiDimensionReader reader = null;
044       HashMap metadata = null;
045       String arrayName = null;
046       String[] array_dim_names = null;
047       int[] array_dim_lengths  = null;
048       int array_rank;
049       Class arrayType;
050    
051       HashMap<String, String> dimNameMap = new HashMap<String, String>();
052    
053       RealType rangeType;
054    
055       RangeProcessor rangeProcessor = null;
056    
057       public MultiDimensionAdapter() {
058       }
059    
060       public MultiDimensionAdapter(MultiDimensionReader reader, HashMap metadata) {
061         this.reader = reader;
062         this.metadata = metadata;
063         this.init();
064       }
065    
066       public abstract HashMap getDefaultSubset();
067    
068       public abstract Set makeDomain(Object subset) throws Exception;
069    
070       private void init() {
071         this.arrayName = (String) metadata.get("array_name");
072    
073         String[] suppliedDimNames = (String[]) metadata.get("array_dimension_names");
074         if (suppliedDimNames != null) {
075           array_dim_names = suppliedDimNames;
076         }
077         else {
078           array_dim_names = reader.getDimensionNames(arrayName);
079         }
080    
081         array_dim_lengths = reader.getDimensionLengths(arrayName);
082         array_rank = array_dim_lengths.length;
083         arrayType = reader.getArrayType(arrayName);
084    
085         for (int i=0; i<array_rank; i++) {
086           dimNameMap.put(array_dim_names[i], array_dim_names[i]);
087         }
088    
089         Iterator iter = metadata.keySet().iterator();
090         while (iter.hasNext()) {
091           String key = (String) iter.next();
092           Object val = metadata.get(key);
093           if (!(val instanceof String)) continue;
094           String name = (String) val; 
095           for (int kk=0; kk<array_rank; kk++) {
096             if (array_dim_names[kk].equals(name)) {
097               dimNameMap.put(array_dim_names[kk], key);
098             }
099           }
100         }
101    
102       }
103    
104       public Subset getIndexes(HashMap select) {
105         Subset subset = new Subset(array_rank);
106         int[] start = subset.getStart();
107         int[] count = subset.getCount();
108         int[] stride = subset.getStride();
109    
110         Iterator iter = select.keySet().iterator();
111         while (iter.hasNext()) {
112           String key = (String) iter.next();
113           String name = (String) metadata.get(key);
114    
115           if (name == null) name = key;
116    
117           for (int kk=0; kk<array_rank; kk++) {
118             if (array_dim_names[kk].equals(name)) {
119               double[] coords = (double[]) select.get(key);
120    
121               if (array_dim_lengths[kk] == 1) {
122                 start[kk] = 0;
123                 count[kk] = 1;
124                 stride[kk] = 1;
125               }
126               else {
127                 start[kk] = (int) coords[0];
128                 count[kk] = (int) ((coords[1] - coords[0])/coords[2] + 1f);
129                 stride[kk] = (int) coords[2];
130               }
131    
132             }
133           }
134         }
135         return subset;
136       }
137    
138       public FlatField getData(Object subset) throws Exception {
139         Set domainSet = makeDomain(subset);
140         return makeFlatField(domainSet, subset);
141       }
142    
143       private FlatField makeFlatField(Set domainSet, float[][] range) throws VisADException, RemoteException {
144         FlatField f_field = makeFlatField(domainSet);
145         f_field.setSamples(range, false);
146         return f_field;
147       }
148    
149       private FlatField makeFlatField(Set domainSet, double[][] range) throws VisADException, RemoteException {
150         FlatField f_field = makeFlatField(domainSet);
151         f_field.setSamples(range, false);
152         return f_field;
153       }
154    
155       private FlatField makeFlatField(Set domainSet) throws VisADException, RemoteException {
156         FlatField f_field = new FlatField(new FunctionType(((SetType)domainSet.getType()).getDomain(), rangeType), domainSet);
157         return f_field;
158       }
159    
160       public FlatField makeFlatField(Set domainSet, Object subset) throws Exception {
161         FlatField f_field = null;
162    
163         Object range = readArray(subset);
164    
165         if (range instanceof float[]) {
166           float[] new_range = processRange((float[]) range, subset);
167           f_field = makeFlatField(domainSet, new float[][] {new_range});
168         }
169         else if (range instanceof double[]) {
170           double[] new_range = processRange((double[]) range, subset);
171           f_field = makeFlatField(domainSet, new double[][] {new_range});
172         }
173         else if (range instanceof short[]) {
174           float[] float_range = processRange((short[])range, subset);
175           f_field = makeFlatField(domainSet, new float[][] {float_range});
176         }
177         else if (range instanceof byte[]) {
178           float[] float_range = processRange((byte[])range, subset);
179           f_field = makeFlatField(domainSet, new float[][] {float_range});
180         }
181    
182         return f_field;
183       }
184    
185       public RangeProcessor getRangeProcessor() {
186         return rangeProcessor;
187       }
188    
189       public void setRangeProcessor(RangeProcessor rangeProcessor) {
190         this.rangeProcessor = rangeProcessor;
191       }
192    
193       public float[] processRange(short[] range, Object subset) {
194         if (rangeProcessor == null) {
195           float[] f_range = new float[range.length];
196           for (int i=0; i<range.length;i++) f_range[i] = (float) range[i]; 
197           return f_range;
198         }
199         else { 
200           return rangeProcessor.processRange(range, (HashMap)subset);
201         }
202       }
203    
204       public float[] processRange(byte[] range, Object subset) {
205         if (rangeProcessor == null) {
206           float[] f_range = new float[range.length];
207           for (int i=0; i<range.length;i++) f_range[i] = (float) range[i];
208           return f_range;
209         }
210         else {
211           return rangeProcessor.processRange(range, (HashMap)subset);
212         }
213       }
214    
215       public float[] processRange(float[] range, Object subset) {
216         if (rangeProcessor == null) {
217           return range;
218         }
219         else {
220           return rangeProcessor.processRange(range, (HashMap)subset);
221         }
222       }
223    
224       public double[] processRange(double[] range, Object subset) {
225         if (rangeProcessor == null) {
226           return range;
227         }
228         else {
229           return rangeProcessor.processRange(range, (HashMap)subset);
230         }
231       }
232    
233    
234       public Object readArray(Object subset) throws Exception {
235         Subset select = getIndexes((HashMap)subset);
236         int[] start = select.getStart();
237         int[] count = select.getCount();
238         int[] stride = select.getStride();
239    
240         return reader.getArray(arrayName, start, count, stride);
241       }
242    
243       public MultiDimensionReader getReader() {
244         return reader;
245       }
246    
247       public Object getMetadata() {
248         return metadata;
249       }
250    
251       String getArrayName() {
252         return arrayName;
253       }
254    
255       public RealType getRangeType() {
256         return rangeType;
257       }
258       
259       public HashMap getSubsetFromLonLatRect(HashMap subset, double minLat, double maxLat,
260                                                              double minLon, double maxLon) {
261         return subset;
262       }
263    
264       public HashMap getSubsetFromLonLatRect(double minLat, double maxLat,
265                                              double minLon, double maxLon) {
266         return null;
267       }
268    
269       public HashMap getSubsetFromLonLatRect(double minLat, double maxLat,
270                                              double minLon, double maxLon,
271                                              int xStride, int yStride, int zStride) {
272         return null;
273       }
274    
275    }