001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
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
029package edu.wisc.ssec.mcidasv.data.hydra;
030
031import visad.FlatField;
032import visad.VisADException;
033import visad.RealType;
034import visad.SetType;
035import visad.FunctionType;
036import visad.Set;
037import java.rmi.RemoteException;
038import java.util.HashMap;
039import java.util.Iterator;
040
041public 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}