/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
/*
RH looks interesting up to 10000 m
MR better near boundary layer (but tighter color range)
*/
package visad.aeri;
import visad.*;
import visad.util.*;
import visad.DisplayImpl;
import visad.java3d.DisplayImplJ3D;
import visad.java3d.TwoDDisplayRendererJ3D;
import visad.data.netcdf.*;
import visad.bom.WindPolarCoordinateSystem;
import visad.data.mcidas.BaseMapAdapter;
import visad.data.visad.VisADSerialForm;
import visad.data.mcidas.AreaAdapter;
import visad.meteorology.ImageSequenceManager;
import visad.meteorology.NavigatedImage;
import visad.meteorology.ImageSequence;
import java.rmi.RemoteException;
import java.io.IOException;
import java.io.File;
// JFC packages
import javax.swing.*;
// AWT packages
import java.awt.*;
import java.awt.event.*;
public class Qdiv
implements ScalarMapListener
{
RealType latitude;
RealType longitude;
RealType altitude;
//- (lon,lat,alt)
//
RealTupleType spatial_domain;
RealType time;
RealType stn_idx;
RealType temp;
RealType dwpt;
RealType wvmr;
RealType RH;
RealType theta;
RealType thetaE;
RealType u_wind;
RealType v_wind;
RealType wvmr_u;
RealType wvmr_v;
RealType band1;
RealType div_qV;
RealType q_divV;
RealType qAdvct;
RealType shape;
RealTupleType wind_aeri;
RealTupleType div_qV_comps;
FunctionType alt_to_wind_aeri;
FunctionType time_to_alt_to_wind_aeri;
FunctionType alt_to_divqV;
FunctionType time_to_alt_to_divqV;
FieldImpl advect_field;
FieldImpl stations_field;
FieldImpl divqV_field;
ImageSequence image_seq;
Set timeDomain;
int n_stations = 3;
double[] station_lat;
double[] station_lon;
double[] station_alt;
double[] station_id;
double[] stat_xoffset = new double[n_stations];
double[] stat_yoffset = new double[n_stations];
double[][] centroid_ll;
BaseMapAdapter baseMap;
DataReference map_ref;
ScalarMap xmap;
ScalarMap ymap;
ScalarMap zmap;
ScalarMap img_map;
boolean xmapEvent = false;
boolean ymapEvent = false;
boolean imgEvent = false;
boolean firstEvent = false;
boolean first_img_Event = false;
float latmin, latmax;
float lonmin, lonmax;
float del_lat, del_lon;
double[] x_range, y_range;
int height_limit = 4000; //- meters
int time_intrvl = 900; //- seconds
boolean rh = false;
boolean tm = false;
boolean pt = false;
boolean ept = false;
int start_date = 0;
double start_time = 0.0;
double[] scale_offset_x = new double[2];
double[] scale_offset_y = new double[2];
AnimationControl ani_cntrl;
int alt_factor = 8;
int n_hres_alt_samples;
float alt_min;
float alt_max;
public static void main(String args[])
throws VisADException, RemoteException, IOException
{
Qdiv qdiv = new Qdiv(args);
}
public Qdiv(String[] args)
throws VisADException, RemoteException, IOException
{
String vadfile = null;
String baseDate = "19991226";
for (int i=0; i max) max = array[ii];
if (array[ii] < min) min = array[ii];
}
min_max[0] = min;
min_max[1] = max;
return min_max;
}
double hgt_max = -Double.MAX_VALUE;
DataImpl makePoles()
throws VisADException, RemoteException
{
SampledSet[] set_s = new SampledSet[n_stations];
int ii = 0;
float[][] locs = new float[3][2];
for ( int kk = 0; kk < n_stations; kk++ ) {
boolean any = false;
float hgt = -Float.MAX_VALUE;
FieldImpl station = (FieldImpl) stations_field.getSample(kk);
if (station == null) continue;
int len = station.getLength();
for (int i=0; i hgt) hgt = hi[0];
if (!any && samples[0][0] == samples[0][0])
{
any = true;
locs[0][0] = (float) station_lon[kk];
locs[1][0] = (float) station_lat[kk];
locs[0][1] = locs[0][0];
locs[1][1] = locs[1][0];
}
}
if (any) {
locs[2][0] = 0.0f;
locs[2][1] = hgt;
set_s[ii++] = new Gridded3DSet(spatial_domain, locs, 2, null, null, null);
// System.out.println("set_s[" + kk + "] = " + set_s[kk]);
if (hgt > hgt_max) hgt_max = hgt;
}
}
SampledSet[] set_ss = new SampledSet[ii];
System.arraycopy(set_s, 0, set_ss, 0, ii);
return new UnionSet(spatial_domain, set_ss);
}
public void mapChanged(ScalarMapEvent e)
throws VisADException, RemoteException
{
if ( xmap.equals(e.getScalarMap()) ) {
xmapEvent = true;
}
else if ( ymap.equals(e.getScalarMap()) ) {
ymapEvent = true;
}
else if ( img_map.equals(e.getScalarMap()) ) {
imgEvent = true;
}
if (( xmapEvent && ymapEvent ) && !(firstEvent) ) {
double[] minmax = getArrayMinMax(station_lat);
latmin = (float)minmax[0];
latmax = (float)minmax[1];
minmax = getArrayMinMax(station_lon);
lonmin = (float) minmax[0];
lonmax = (float) minmax[1];
firstEvent = true;
xmap.setRange(lonmin, lonmax);
ymap.setRange(latmin, latmax);
double[] so = new double[2];
double[] data = new double[2];
double[] display = new double[2];
xmap.getScale(so, data, display);
scale_offset_x[0] = so[0];
scale_offset_x[1] = so[1];
ymap.getScale(so, data, display);
scale_offset_y[0] = so[0];
scale_offset_y[1] = so[1];
}
if ( imgEvent && !first_img_Event ) {
double[] i_range = img_map.getRange();
System.out.println(i_range[0]+" "+i_range[1]);
first_img_Event = true;
img_map.setRange(i_range[1], i_range[0]);
}
}
public void controlChanged(ScalarMapControlEvent e)
{
}
FieldImpl[] makeWinds(String[] files)
throws VisADException, RemoteException, IOException
{
DataImpl[] file_data = new DataImpl[n_stations];
FieldImpl[] time_field = new FieldImpl[n_stations];
double[][] time_offset = null;
double[] base_date = new double[n_stations];
double[] base_time = new double[n_stations];
Gridded1DSet d_set = null;
FlatField new_ff = null;
RealType alt;
RealType spd;
RealType dir;
//- create a new netcdf reader
Plain plain = new Plain();
//- retrieve file data objects
for ( int kk = 0; kk < n_stations; kk++) {
file_data[kk] = plain.open(files[kk]);
}
//- make sub mathtype for file objects
MathType file_type = file_data[0].getType();
System.out.println(file_type.prettyString());
System.out.println();
FunctionType f_type0 =
(FunctionType)((TupleType)file_type).getComponent(2);
int n_comps = ((TupleType)f_type0.getRange()).getDimension();
FunctionType f_type1 =
(FunctionType)((TupleType)f_type0.getRange()).getComponent(n_comps-1);
RealTupleType rt_type = (RealTupleType) f_type1.getRange();
int alt_idx = rt_type.getIndex("Altitude");
altitude = (RealType) rt_type.getComponent(alt_idx);
int ws_idx = rt_type.getIndex("windSpeed");
spd = (RealType) rt_type.getComponent(ws_idx);
int wd_idx = rt_type.getIndex("windDir");
dir = (RealType) rt_type.getComponent(wd_idx);
RealType[] r_types = { dir, spd };
/* WLH 28 Dec 99 */
RealType[] uv_types = { u_wind, v_wind };
// EarthVectorType uv = new EarthVectorType(uv_types); WLH meeds m/s
RealTupleType uv = new RealTupleType(uv_types);
CoordinateSystem cs = new WindPolarCoordinateSystem(uv);
RealTupleType ds = new RealTupleType(r_types, cs, null);
FunctionType alt_to_ds = new FunctionType(altitude, ds);
FunctionType alt_to_uv = new FunctionType(altitude, uv);
RealType domain_type = (RealType)
((TupleType)f_type0.getRange()).getComponent(0);
//-time = domain_type;
time = RealType.Time;
FunctionType new_type = new FunctionType(RealType.Time, alt_to_uv);
//-FunctionType new_type = new FunctionType(time, alt_to_uv);
FieldImpl[] winds = new FieldImpl[n_stations];
for ( int ii = 0; ii < n_stations; ii++ )
{
base_date[ii] = (double)
((Real)((Tuple)file_data[ii]).getComponent(0)).getValue();
base_time[ii] = (double)
((Real)((Tuple)file_data[ii]).getComponent(1)).getValue();
time_field[ii] = (FieldImpl)
((Tuple)file_data[ii]).getComponent(2);
station_lat[ii] =
((Real)((Tuple)time_field[ii].getSample(0)).getComponent(6)).getValue();
station_lon[ii] =
-((Real)((Tuple)time_field[ii].getSample(0)).getComponent(7)).getValue();
station_alt[ii] =
((Real)((Tuple)time_field[ii].getSample(0)).getComponent(8)).getValue();
station_id[ii] =
((Real)((Tuple)time_field[ii].getSample(0)).getComponent(9)).getValue();
if (ii == 0) {
start_time = base_time[0];
start_date = (int) base_date[0];
}
/*
System.out.println("wind " + ii + " date: " + base_date[ii] +
" time: " + base_time[ii]);
wind 0 date: 1.9991226E7 time: 9.461664E8
wind 1 date: 1.9991226E7 time: 9.461664E8
wind 2 date: 1.9991226E7 time: 9.461664E8
wind 3 date: 1.9991226E7 time: 9.461664E8
wind 4 date: 1.9991226E7 time: 9.461664E8
looks like 19991226 and seconds since 1-1-70
time_offset looks like seconds since 0Z
*/
int length = time_field[ii].getLength();
double[][] times = new double[1][length];
time_offset = new double[1][length];
FlatField[] range_data = new FlatField[length];
double[][] samples = null; // WLH
int n_not_all_miss = 0;
for ( int jj = 0; jj < length; jj++ )
{
Tuple range = (Tuple) time_field[ii].getSample(jj);
time_offset[0][jj] = (double)((Real)range.getComponent(0)).getValue();
FlatField p_field = (FlatField) range.getComponent(n_comps-1);
double[][] values =
p_field.getValues(); // WLH - (alt, ?, ?, dir, spd, ???)
double[][] new_values = new double[2][values[0].length];
if ( jj == 0 ) //- only once, vertical range gates don't change
{
samples = new double[1][values[0].length]; // WLH
System.arraycopy(values[alt_idx], 0, samples[0], 0, samples[0].length);
d_set = new Gridded1DSet(altitude, Set.doubleToFloat(samples),
samples[0].length);
}
new_ff = new FlatField(alt_to_uv, d_set);
/* WLH - fill in missing winds - this also extrapolates to missing
start or end altitudes - but it does nothing if all winds are missing */
int n_not_miss = 0;
int n_levels = values[0].length;
int[] not_miss = new int[n_levels];
for ( int mm = 0; mm < n_levels; mm++ )
{
if ( values[wd_idx][mm] <= -9999 ) {
new_values[0][mm] = Float.NaN;
}
else {
new_values[0][mm] = values[wd_idx][mm];
}
if ( values[ws_idx][mm] <= -9999 ) {
new_values[1][mm] = Float.NaN;
}
else {
new_values[1][mm] = values[ws_idx][mm];
}
//-System.out.println("("+mm+", "+jj+") "+new_values[0][mm]+", "+new_values[1][mm]);
if (new_values[0][mm] == new_values[0][mm] &&
new_values[1][mm] == new_values[1][mm]) {
not_miss[n_not_miss] = mm;
n_not_miss++;
}
}
//-if ( (n_levels - 3) < n_not_miss && n_not_miss < n_levels) {
if ( (n_levels - 7) < n_not_miss && n_not_miss <= n_levels) {
int nn = n_not_miss;
if (not_miss[0] > 0) nn += not_miss[0];
int endlen = values[0].length - (not_miss[n_not_miss-1]+1);
if (endlen > 0) nn += endlen;
float[][] newer_values = new float[2][nn];
float[][] newer_samples = new float[1][nn];
// fill in non-missing values
for (int i=0; i (alt) -> (U,V,T,TD,WV)
//
FieldImpl time_wind_aeri = new FieldImpl(time_to_alt_to_wind_aeri, timeDomain);
//- resample winds to timeDomain
//
wind_to_timeDomain = (FieldImpl)
winds[kk].resample(timeDomain,
Data.WEIGHTED_AVERAGE,
Data.NO_ERRORS );
//- resample rtvls to timeDomain
rtvl_to_timeDomain = (FieldImpl)
rtvls[kk].resample(timeDomain,
Data.WEIGHTED_AVERAGE,
Data.NO_ERRORS );
/**
rtvl_to_timeDomain = linearInterp(rtvls[kk], timeDomain);
**/
//- resample rtvls domain (altitude) to winds at each rtvl time
//
int dim =
((RealTupleType)
((FunctionType)time_to_alt_to_wind_aeri.getRange()).getRange()).getDimension();
int n_times = timeDomain.getLength();
Set ds = null;
int nn = 0;
for ( int tt = 0; tt < n_times; tt++ )
{
alt_to_rtvl = (FieldImpl) rtvl_to_timeDomain.getSample(tt);
alt_to_wind = (FieldImpl) wind_to_timeDomain.getSample(tt);
if ( tt == 0 ) { //- these won't change over time
ds = alt_to_wind.getDomainSet();
/**--- WLH height limit ---*/
float[][] samples = ds.getSamples();
float[] ns = new float[samples[0].length];
for (int i=0; i
Ads help maintain this website.