001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 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 */ 028package edu.wisc.ssec.mcidasv.data; 029 030 031import edu.wisc.ssec.mcidasv.data.hydra.NetCDFFile; 032import visad.Data; 033import visad.Unit; 034import visad.Gridded3DSet; 035import visad.Gridded1DDoubleSet; 036import visad.Gridded1DSet; 037import visad.Set; 038import visad.UnionSet; 039import visad.RealTupleType; 040import visad.RealType; 041import visad.FlatField; 042import visad.FieldImpl; 043import visad.Integer1DSet; 044import visad.FunctionType; 045import visad.CoordinateSystem; 046import visad.VisADException; 047import visad.DateTime; 048import visad.data.units.Parser; 049import visad.data.units.ParseException; 050 051import java.rmi.RemoteException; 052import java.util.Hashtable; 053import java.util.List; 054 055import ucar.unidata.util.Misc; 056import ucar.unidata.util.Range; 057 058import ucar.unidata.data.DataUtil; 059import ucar.unidata.data.DataChoice; 060import ucar.unidata.data.DataDataChoice; 061import ucar.unidata.data.DirectDataChoice; 062import ucar.unidata.data.DataSelection; 063import ucar.unidata.data.DataCategory; 064import ucar.unidata.data.DataSourceImpl; 065import ucar.unidata.data.DataSourceDescriptor; 066 067 068 069public 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 {@link DataChoice DataChoices} for this {@code DataSource}. 214 */ 215 public void doMakeDataChoices() { 216 try { 217 for (int k=0; k<paramList.length; k++) { 218 DataChoice choice = doMakeDataChoice(k); 219 if (choice != null) { 220 addDataChoice(choice); 221 } 222 } 223 } 224 catch(Exception e) { 225 e.printStackTrace(); 226 } 227 } 228 229 private DataChoice doMakeDataChoice(int idx) throws Exception { 230 String name = paramList[idx]; 231 DirectDataChoice ddc = null; 232 if (ncFile.hasArray(name)) { 233 ddc = new DirectDataChoice(this, new Integer(idx), name, name, null, new Hashtable()); 234 } 235 return ddc; 236 } 237 238 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 239 DataSelection dataSelection, 240 Hashtable requestProperties) 241 throws VisADException, RemoteException { 242 243 String paramName = dataChoice.getName(); 244 245 FieldImpl trajField = new FieldImpl( 246 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels)); 247 248 FieldImpl trajTimeField = new FieldImpl(new FunctionType(RealType.Time, trajField.getType()), timeSet); 249 250 lonRange.setMin(Float.MAX_VALUE); 251 lonRange.setMax(-Float.MAX_VALUE); 252 latRange.setMin(Float.MAX_VALUE); 253 latRange.setMax(-Float.MAX_VALUE); 254 paramRange.setMin(Float.MAX_VALUE); 255 paramRange.setMax(-Float.MAX_VALUE); 256 257 try { 258 for (int t=0; t<numTimes; t++) { 259 trajField = new FieldImpl( 260 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels)); 261 for (int k=0; k<numParcels/4; k++) { 262 FlatField fld = singleTraj(paramName, k*4, 0, t+1, 1); 263 trajField.setSample(k, fld); 264 } 265 trajTimeField.setSample(t, trajField); 266 } 267 return trajTimeField; 268 } 269 catch (Exception e) { 270 e.printStackTrace(); 271 return null; 272 } 273 } 274 275 public static float[] minmax(float[] values, float min, float max) { 276 for (int k = 0; k < values.length; k++) { 277 float val = values[k]; 278 if ((val == val) && (val < Float.POSITIVE_INFINITY) && (val > Float.NEGATIVE_INFINITY)) { 279 if (val < min) min = val; 280 if (val > max) max = val; 281 } 282 } 283 return new float[] {min, max}; 284 } 285 286 public Range getLonRange() { 287 return lonRange; 288 } 289 290 public Range getLatRange() { 291 return latRange; 292 } 293 294 public Range getParamRange() { 295 return paramRange; 296 } 297 298}