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 package edu.wisc.ssec.mcidasv.data; 029 030 031 import edu.wisc.ssec.mcidasv.data.hydra.NetCDFFile; 032 import visad.Data; 033 import visad.Unit; 034 import visad.Gridded3DSet; 035 import visad.Gridded1DDoubleSet; 036 import visad.Gridded1DSet; 037 import visad.Set; 038 import visad.UnionSet; 039 import visad.RealTupleType; 040 import visad.RealType; 041 import visad.FlatField; 042 import visad.FieldImpl; 043 import visad.Integer1DSet; 044 import visad.FunctionType; 045 import visad.CoordinateSystem; 046 import visad.VisADException; 047 import visad.DateTime; 048 import visad.data.units.Parser; 049 import visad.data.units.ParseException; 050 051 import java.rmi.RemoteException; 052 import java.util.Hashtable; 053 import java.util.List; 054 055 import ucar.unidata.util.Misc; 056 import ucar.unidata.util.Range; 057 058 import ucar.unidata.data.DataUtil; 059 import ucar.unidata.data.DataChoice; 060 import ucar.unidata.data.DataDataChoice; 061 import ucar.unidata.data.DirectDataChoice; 062 import ucar.unidata.data.DataSelection; 063 import ucar.unidata.data.DataCategory; 064 import ucar.unidata.data.DataSourceImpl; 065 import ucar.unidata.data.DataSourceDescriptor; 066 067 068 069 public class NearCastTrajDataSource extends DataSourceImpl { 070 071 private static final String DATA_DESCRIPTION = "NearCastTrajectory"; 072 073 public static String parcelDimName = "parcel"; 074 public static String timeDimName = "times"; 075 public static String lonName = "lon"; 076 public static String latName = "lat"; 077 078 NetCDFFile ncFile = null; 079 String pressName = "pres"; 080 String timeName = "times"; 081 082 083 int[] start = new int[2]; 084 int[] count = new int[2]; 085 int[] stride = new int[2]; 086 087 088 int parcelDimIdx = 0; 089 int timeDimIdx = 1; 090 091 String[] paramList = null; 092 093 String fileName = null; 094 095 CoordinateSystem presToHeightCS = null; 096 097 Unit timeUnit; 098 Set timeSet; 099 100 int numTimes; 101 int numParcels; 102 103 Range lonRange = new Range(); 104 Range latRange = new Range(); 105 Range paramRange = new Range(); 106 107 public NearCastTrajDataSource() { 108 } 109 110 public NearCastTrajDataSource(String filename) throws VisADException { 111 this(null, Misc.newList(filename), null); 112 } 113 114 public NearCastTrajDataSource(DataSourceDescriptor descriptor, 115 String fileName, Hashtable properties) throws VisADException { 116 this(descriptor, Misc.newList(fileName), properties); 117 } 118 119 public NearCastTrajDataSource(DataSourceDescriptor descriptor, 120 List newSources, Hashtable properties) throws VisADException { 121 122 super(descriptor, DATA_DESCRIPTION, DATA_DESCRIPTION, properties); 123 124 presToHeightCS = DataUtil.getPressureToHeightCS(DataUtil.STD_ATMOSPHERE); 125 126 fileName = (String) newSources.get(0); 127 128 try { 129 ncFile = new NetCDFFile(fileName); 130 } 131 catch (Exception e) { 132 e.printStackTrace(); 133 } 134 135 paramList = new String[] {"temp", "q", "the", "tp", "MS", "MQ", "MTe", "TP"}; 136 137 138 String unitStr = ncFile.getArrayUnitString(timeName); 139 try { 140 timeUnit = Parser.parse(unitStr); 141 } 142 catch (ParseException e) { 143 System.out.println(e); 144 } 145 146 numTimes = ncFile.getDimensionLength(timeDimName); 147 numParcels = ncFile.getDimensionLength(parcelDimName); 148 149 try { 150 Class type = ncFile.getArrayType(timeName); 151 if (type == Double.TYPE) { 152 double[] timeValues = ncFile.getDoubleArray(timeName, new int[] {0}, new int[] {numTimes}, new int[] {1}); 153 timeSet = new Gridded1DDoubleSet( 154 RealType.Time, new double[][] {timeValues}, numTimes, null, new Unit[] {timeUnit}, null); 155 } 156 else if (type == Float.TYPE) { 157 float[] timeValues = ncFile.getFloatArray(timeName, new int[] {0}, new int[] {numTimes}, new int[] {1}); 158 timeSet = new Gridded1DSet(RealType.Time, new float[][] {timeValues}, numTimes, null, new Unit[] {timeUnit}, null); 159 160 } 161 } 162 catch (Exception e) { 163 e.printStackTrace(); 164 } 165 } 166 167 168 public FlatField[] createVisADData(String paramName) { 169 return null; 170 } 171 172 public FlatField singleTraj(String paramName, int parcelIndex, int timeStart, int timeCount, int timeStride) throws Exception { 173 174 start[parcelDimIdx] = parcelIndex; 175 start[timeDimIdx] = timeStart; 176 177 count[parcelDimIdx] = 1; 178 count[timeDimIdx] = timeCount; 179 180 stride[parcelDimIdx] = 1; 181 stride[timeDimIdx] = 1; 182 183 float[] lons = ncFile.getFloatArray(lonName, start, count, stride); 184 float[] lats = ncFile.getFloatArray(latName, start, count, stride); 185 186 float[] minmax = minmax(lons, (float)lonRange.getMin(), (float)lonRange.getMax()); 187 lonRange.setMin(minmax[0]); 188 lonRange.setMax(minmax[1]); 189 minmax = minmax(lats, (float)latRange.getMin(), (float)latRange.getMax()); 190 latRange.setMin(minmax[0]); 191 latRange.setMax(minmax[1]); 192 193 float[] pres = ncFile.getFloatArray(pressName, start, count, stride); 194 float[] param = ncFile.getFloatArray(paramName, start, count, stride); 195 minmax = minmax(param, (float)paramRange.getMin(), (float)paramRange.getMax()); 196 paramRange.setMin(minmax[0]); 197 paramRange.setMax(minmax[1]); 198 199 float[] alt = (presToHeightCS.toReference(new float[][] {pres}))[0]; 200 201 float[][] trajCoords = new float[][] {lons, lats, alt}; 202 203 Gridded3DSet domain = new Gridded3DSet(RealTupleType.SpatialEarth3DTuple, trajCoords, trajCoords[0].length); 204 205 FunctionType fncType = new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName)); 206 FlatField traj = new FlatField(fncType, domain); 207 traj.setSamples(new float[][] {param}, false); 208 209 return traj; 210 } 211 212 /** 213 * Make and insert the <code>DataChoice</code>-s for this 214 * <code>DataSource</code>. 215 */ 216 public void doMakeDataChoices() { 217 try { 218 for (int k=0; k<paramList.length; k++) { 219 DataChoice choice = doMakeDataChoice(k); 220 if (choice != null) { 221 addDataChoice(choice); 222 } 223 } 224 } 225 catch(Exception e) { 226 e.printStackTrace(); 227 } 228 } 229 230 private DataChoice doMakeDataChoice(int idx) throws Exception { 231 String name = paramList[idx]; 232 DirectDataChoice ddc = null; 233 if (ncFile.hasArray(name)) { 234 ddc = new DirectDataChoice(this, new Integer(idx), name, name, null, new Hashtable()); 235 } 236 return ddc; 237 } 238 239 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 240 DataSelection dataSelection, 241 Hashtable requestProperties) 242 throws VisADException, RemoteException { 243 244 String paramName = dataChoice.getName(); 245 246 FieldImpl trajField = new FieldImpl( 247 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels)); 248 249 FieldImpl trajTimeField = new FieldImpl(new FunctionType(RealType.Time, trajField.getType()), timeSet); 250 251 lonRange.setMin(Float.MAX_VALUE); 252 lonRange.setMax(-Float.MAX_VALUE); 253 latRange.setMin(Float.MAX_VALUE); 254 latRange.setMax(-Float.MAX_VALUE); 255 paramRange.setMin(Float.MAX_VALUE); 256 paramRange.setMax(-Float.MAX_VALUE); 257 258 try { 259 for (int t=0; t<numTimes; t++) { 260 trajField = new FieldImpl( 261 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels)); 262 for (int k=0; k<numParcels/4; k++) { 263 FlatField fld = singleTraj(paramName, k*4, 0, t+1, 1); 264 trajField.setSample(k, fld); 265 } 266 trajTimeField.setSample(t, trajField); 267 } 268 return trajTimeField; 269 } 270 catch (Exception e) { 271 e.printStackTrace(); 272 return null; 273 } 274 } 275 276 public static float[] minmax(float[] values, float min, float max) { 277 for (int k = 0; k < values.length; k++) { 278 float val = values[k]; 279 if ((val == val) && (val < Float.POSITIVE_INFINITY) && (val > Float.NEGATIVE_INFINITY)) { 280 if (val < min) min = val; 281 if (val > max) max = val; 282 } 283 } 284 return new float[] {min, max}; 285 } 286 287 public Range getLonRange() { 288 return lonRange; 289 } 290 291 public Range getLatRange() { 292 return latRange; 293 } 294 295 public Range getParamRange() { 296 return paramRange; 297 } 298 299 }