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