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