//
// GoesCollaboration.java
//
package visad.paoloa;
// VisAD packages
import visad.*;
import visad.util.Delay;
import visad.util.VisADSlider;
import visad.java3d.DisplayImplJ3D;
import visad.java3d.TwoDDisplayRendererJ3D;
import visad.java3d.DirectManipulationRendererJ3D;
// Java packages
import java.io.File;
import java.rmi.RemoteException;
import java.rmi.NotBoundException;
import java.rmi.AccessException;
import java.rmi.Naming;
import java.net.MalformedURLException;
// JFC packages
import javax.swing.*;
import javax.swing.border.*;
// AWT packages
import java.awt.*;
import java.awt.event.*;
/**
GoesCollaboration implements the interactive and collaborative
Goes satellite sounding retrieval application using VisAD 2.0.
It is rewritten from the IRGS.v application developed for
VisAD 1.1 by Paolo Antonelli.<P>
*/
public class GoesCollaboration extends Object {
/** RemoteServerImpl for server
this GoesCollaboration is a server if server_server != null */
RemoteServerImpl server_server;
/** RemoteServer for client
this GoesCollaboration is a client if client_server != null */
RemoteServer client_server;
/** declare MathTypes */
RealType nchan;
RealType indx;
RealType nl;
RealType tbc;
RealType tbc_d;
RealType wfn;
RealType pres;
RealType temp;
RealType mixr;
RealType ozone;
RealType pressure;
RealType data_real;
RealType diff;
/** declare DataReferences */
DataReference wfna_ref;
DataReference tempa_ref;
DataReference mixra_ref;
DataReference ozonea_ref;
DataReference presa_ref;
DataReference diff_col_ref;
DataReference diff_ref;
DataReference zero_line_ref;
DataReference smr_ref;
DataReference real_tbc_ref;
DataReference wfnb_ref;
DataReference wfna_old_ref;
/** slider DataReferences */
DataReference gzen_ref;
DataReference tskin_ref;
DataReference in_dx_ref;
/** the width and height of the UI frame */
public static int WIDTH = 1200;
public static int HEIGHT = 1000;
/** type 'java visad.paoloa.GoesCollaboration' to run this application;
the main thread just exits, since Display, Cell and JFC threads
run the application */
public static void main(String args[])
throws VisADException, RemoteException {
// construct GoesCollaboration application
GoesCollaboration goes = new GoesCollaboration(args);
if (goes.client_server != null) {
goes.setupClient();
}
else if (goes.server_server != null) {
// load native method library (only needed for server)
System.loadLibrary("GoesCollaboration");
goes.setupServer();
}
else {
// stand-alone (neither client nor server)
// load native method library
System.loadLibrary("GoesCollaboration");
goes.setupServer();
}
}
/**
Construct the GoesCollaboration application, including Data
objects, Display objects, Cell (computational) objects,
and JFC (slider) user interface objects. The Display,
Cell and JFC objects include threads and links to Data
objects (via DataReference objects). Display and Cell
threads wake up when linked Data objects change. Display
and JFC objects wake up on mouse events. Display, Cell
and JFC objects cause changes to Data objects.<P>
Here's a summary of the event logic among Data, Displays,
Cells, and JSliders:<P>
<PRE>
initialization ->
zero_line = 0 -> display4
slider <--> in_dx
slider <--> gzen
slider <--> tskin
slider <--> save_config
in_dx -> real_tbcCell
real_tbc = re_read_1_c(in_dx)
month = 6
lat = real_tbc[18];
(tempa, mixra, ozonea, presa) =
get_profil_c(lat, month) -> display2
direct_manipualtion (in display2) ->
(tempa, mixra, ozonea) -> display2
gzen, tskin, tempa, mixra, ozonea, presa -> wfnbCell
wfnb = goesrte_2_c(gzen, tskin, tempa, mixra, ozonea, presa)
wfnb, real_tbc -> wfnaCell
wfna = wfnb.wfn -> display1
diff_DATA = wfnb.tbc[nl=1] - real_tbc -> display4
smr = RootMeanSquare(diff_DATA) -> display4
save_config -> wfna_oldCell
wfna_old = wfna
wfna, wfna_old -> diff_colCell
diff_col = wfna - wfna_old -> display3
</PRE>
*/
public GoesCollaboration(String args[])
throws VisADException, RemoteException {
if (args.length > 0) {
// this is a client
// try to connect to RemoteServer
String domain = "//" + args[0] + "/GoesCollaboration";
try {
client_server = (RemoteServer) Naming.lookup(domain);
}
catch (MalformedURLException e) {
System.out.println("Cannot connect to server");
System.exit(0);
}
catch (NotBoundException e) {
System.out.println("Cannot connect to server");
System.exit(0);
}
catch (AccessException e) {
System.out.println("Cannot connect to server");
System.exit(0);
}
catch (RemoteException e) {
System.out.println("Cannot connect to server");
System.exit(0);
}
}
else { // args.length == 0
// this is a server
/* CTR: 30 Sep 1998 */
// check for the existence of necessary data files
{
File f1 = new File("data_obs_1.dat");
File f2 = new File("goesrtcf");
if (!f1.exists() || !f2.exists()) {
System.out.println("This program requires the data files " +
"\"data_obs_1.dat\"");
System.out.println("and \"goesrtcf\", available at:");
System.out.println(" ftp://ftp.ssec.wisc.edu/pub/visad-2.0/" +
"paoloa-files.tar.Z");
System.exit(1);
}
if (!f2.exists()) {
System.out.println("");
System.exit(2);
}
}
// try to set up a RemoteServer
server_server = new RemoteServerImpl();
try {
Naming.rebind("///GoesCollaboration", server_server);
}
catch (MalformedURLException e) {
System.out.println("Cannot set up server - running as stand-alone");
server_server = null;
}
catch (AccessException e) {
System.out.println("Cannot set up server - running as stand-alone");
server_server = null;
}
catch (RemoteException e) {
System.out.println("Cannot set up server - running as stand-alone");
server_server = null;
}
}
}
/** set up as server */
void setupServer() throws VisADException, RemoteException {
//
// construct function domain sampling Sets
//
// construct 1-D Sets
Set linear18 = new Linear1DSet(1.0, 18.0, 18);
Set linear19 = new Linear1DSet(1.0, 19.0, 19);
Set linear40 = new Linear1DSet(1.0, 40.0, 40);
// construct 2-D Set
Set linear40x18 = new Linear2DSet(1.0, 40.0, 40, 1.0, 18.0, 18);
//
// construct MathTypes for Data objects
//
// construct RealTypes used as Function domains
// with null Units but non-null default Sets (for
// function domain samplings)
nchan = RealType.getRealType("nchan", null, linear18);
indx = RealType.getRealType("indx", null, linear19);
nl = RealType.getRealType("nl", null, linear40);
// construct RealTypes used as Function ranges
// or for simple Real values, with null Units
// and null default Sets
tbc = RealType.getRealType("tbc");
tbc_d = RealType.getRealType("tbc_d");
wfn = RealType.getRealType("wfn");
pres = RealType.getRealType("pres");
temp = RealType.getRealType("temp");
mixr = RealType.getRealType("mixr");
ozone = RealType.getRealType("ozone");
pressure = RealType.getRealType("pressure");
data_real = RealType.getRealType("data_real");
diff = RealType.getRealType("diff");
// construct RealTupleType used as a Function domain
// with non-null default Set
RealTupleType nl_nchan = new RealTupleType(nl, nchan, null, linear40x18);
// construct FunctionTypes
FunctionType obs_data = new FunctionType(indx, data_real);
FunctionType wfn_big = new FunctionType(nl_nchan,
new RealTupleType(wfn, tbc));
FunctionType tbc_array_dif = new FunctionType(nchan, tbc_d);
FunctionType wfn_array = new FunctionType(nl_nchan, wfn);
FunctionType temp_array = new FunctionType(nl, temp);
FunctionType mixr_array = new FunctionType(nl, mixr);
FunctionType ozone_array = new FunctionType(nl, ozone);
FunctionType pres_array = new FunctionType(nl, pressure);
//
// construct Data objects and DataReferences to them
//
// construct weighting function Data object and DataReference
FlatField wfna = new FlatField(wfn_array);
wfna_ref = new DataReferenceImpl("wfna");
wfna_ref.setData(wfna);
// construct temperature profile Data object and DataReference
FlatField tempa = new FlatField(temp_array);
tempa_ref = new DataReferenceImpl("tempa");
tempa_ref.setData(tempa);
// construct mixing ratio profile Data object and DataReference
FlatField mixra = new FlatField(mixr_array);
mixra_ref = new DataReferenceImpl("mixra");
mixra_ref.setData(mixra);
// construct ozone profile Data object and DataReference
FlatField ozonea = new FlatField(ozone_array);
ozonea_ref = new DataReferenceImpl("ozonea");
ozonea_ref.setData(ozonea);
// construct pressure profile Data object and DataReference
FlatField presa = new FlatField(pres_array);
presa_ref = new DataReferenceImpl("presa");
presa_ref.setData(presa);
// construct weighting function difference Data object
// and DataReference
FlatField diff_col = new FlatField(wfn_array);
diff_col_ref = new DataReferenceImpl("diff_col");
diff_col_ref.setData(diff_col);
// construct brightness temperature error Data object
// and DataReference
FlatField diff_DATA = new FlatField(tbc_array_dif);
diff_ref = new DataReferenceImpl("diff");
diff_ref.setData(diff_DATA);
// construct zero line Data object and DataReference
FlatField zero_line = new FlatField(tbc_array_dif);
zero_line_ref = new DataReferenceImpl("zero_line");
zero_line_ref.setData(zero_line);
// construct brightness temperature error root mean square
// Data object and DataReference
Real smr = new Real(tbc_d);
smr_ref = new DataReferenceImpl("smr");
smr_ref.setData(smr);
// construct observed brightness temperature Data object
// and DataReference
FlatField real_tbc = new FlatField(obs_data);
real_tbc_ref = new DataReferenceImpl("real_tbc");
real_tbc_ref.setData(real_tbc);
// construct compound weighting function Data object
// and DataReference
FlatField wfnb = new FlatField(wfn_big);
wfnb_ref = new DataReferenceImpl("wfnb");
wfnb_ref.setData(wfnb);
// construct saved weighting function Data object
// and DataReference
FlatField wfna_old = new FlatField(wfn_array);
wfna_old_ref = new DataReferenceImpl("wfna_old");
wfna_old_ref.setData(wfna);
//
// construct DataReference objects linked to VisADSliders (the
// JSlider constructors will construct Real data objects for
// these, so there is no point in constructing Real data objects
// here)
//
// DataReference for zenith angle
gzen_ref = new DataReferenceImpl("gzen");
// DataReference for skin temperature
tskin_ref = new DataReferenceImpl("tskin");
// DataReference for index into model atmospheres
in_dx_ref = new DataReferenceImpl("in_dx");
// DataReference used to trigger copying wfna to wfna_old
DataReference save_config_ref = new DataReferenceImpl("save_config");
// set up Displays for server
DisplayImpl[] displays = new DisplayImpl[4];
setupDisplays(displays);
if (server_server != null) {
for (int i = 0; i < displays.length; i++) {
server_server.addDisplay(new RemoteDisplayImpl(displays[i]));
}
}
// set up user interface
setupUI(displays, in_dx_ref, save_config_ref, gzen_ref, tskin_ref);
// initialize zero reference line for brightness temperature errors
double[][] zero_line_x = zero_line.getValues();
for (int i=0; i<zero_line_x[0].length; i++) zero_line_x[0][i] = 0.0;
zero_line.setSamples(zero_line_x);
// make sure Data are initialized
new Delay(1000);
gzen_ref.incTick();
save_config_ref.incTick();
new Delay(1000);
//
// construct computational Cells and links to DataReferences
// that trigger them
//
// construct a real_tbcCell
real_tbcCell real_tbc_cell = new real_tbcCell();
real_tbc_cell.addReference(in_dx_ref);
new Delay(500);
// construct a wfnbCell
wfnbCell wfnb_cell = new wfnbCell();
wfnb_cell.addReference(gzen_ref);
wfnb_cell.addReference(tskin_ref);
wfnb_cell.addReference(tempa_ref);
wfnb_cell.addReference(mixra_ref);
wfnb_cell.addReference(ozonea_ref);
wfnb_cell.addReference(presa_ref);
new Delay(500);
// construct a wfnaCell
wfnaCell wfna_cell = new wfnaCell();
wfna_cell.addReference(wfnb_ref);
wfna_cell.addReference(real_tbc_ref);
new Delay(500);
// construct a wfna_oldCell
wfna_oldCell wfna_old_cell = new wfna_oldCell();
wfna_old_cell.addReference(save_config_ref);
new Delay(500);
// construct a diff_colCell
diff_colCell diff_col_cell = new diff_colCell();
diff_col_cell.addReference(wfna_ref);
diff_col_cell.addReference(wfna_old_ref);
new Delay(500);
if (server_server != null) {
// set RemoteDataReferenceImpls in RemoteServer
RemoteDataReferenceImpl[] refs =
new RemoteDataReferenceImpl[4];
refs[0] =
new RemoteDataReferenceImpl((DataReferenceImpl) gzen_ref);
refs[1] =
new RemoteDataReferenceImpl((DataReferenceImpl) tskin_ref);
refs[2] =
new RemoteDataReferenceImpl((DataReferenceImpl) in_dx_ref);
refs[3] =
new RemoteDataReferenceImpl((DataReferenceImpl) save_config_ref);
server_server.setDataReferences(refs);
}
// make sure Data are initialized (again)
new Delay(1000);
gzen_ref.incTick();
save_config_ref.incTick();
}
/** set up as client */
void setupClient() throws VisADException, RemoteException {
//
// get RemoteDataReferences
//
RemoteDataReference[] refs = client_server.getDataReferences();
if (refs == null) {
System.out.println("Cannot connect to server");
System.exit(0);
}
gzen_ref = refs[0];
tskin_ref = refs[1];
in_dx_ref = refs[2];
DataReference save_config_ref = refs[3];
// set up Displays for client
DisplayImpl[] displays = new DisplayImpl[4];
displays[0] = new DisplayImplJ3D(client_server.getDisplay("display1"));
displays[1] = new DisplayImplJ3D(client_server.getDisplay("display2"));
displays[2] = new DisplayImplJ3D(client_server.getDisplay("display3"));
displays[3] = new DisplayImplJ3D(client_server.getDisplay("display4"));
// set up user interface
setupUI(displays, in_dx_ref, save_config_ref, gzen_ref, tskin_ref);
}
/** set up Displays; return constructed Displays in displays array */
void setupDisplays(DisplayImpl[] displays)
throws VisADException, RemoteException {
//
// construct Displays and link to Data objects
//
// construct Display 1 (using default DisplayRenderer);
// the text name is used only for debugging
DisplayImplJ3D display1 = new DisplayImplJ3D("display1");
// construct ScalarMaps for Display 1;
// explicitly set data range for nl values (in order to
// invert scale)
ScalarMap map1nl = new ScalarMap(nl, Display.YAxis);
map1nl.setRange(40.0, 1.0);
display1.addMap(map1nl);
// setRange is not invoked for other ScalarMaps - they will
// use auto-scaling from actual data values
display1.addMap(new ScalarMap(nchan, Display.XAxis));
display1.addMap(new ScalarMap(wfn, Display.Green));
display1.addMap(new ScalarMap(wfn, Display.ZAxis));
display1.addMap(new ConstantMap(0.5f, Display.Red));
display1.addMap(new ConstantMap(0.5f, Display.Blue));
GraphicsModeControl mode1 = display1.getGraphicsModeControl();
mode1.setScaleEnable(true);
// link weighting function Data object to display1
// (using default DataRenderer and a null array of ConstantMaps)
display1.addReference(wfna_ref);
// construct Display 2 and its ScalarMaps (using non-default
// 2-D DisplayRenderer)
DisplayImplJ3D display2 =
new DisplayImplJ3D("display2", new TwoDDisplayRendererJ3D());
// explicitly set data range for nl values (in order to
// invert scale)
ScalarMap map2nl = new ScalarMap(nl, Display.YAxis);
map2nl.setRange(40.0, 1.0);
display2.addMap(map2nl);
// map temp, mixr and ozone to XAxis and
// set axis scale colors
ScalarMap map2temp = new ScalarMap(temp, Display.XAxis);
display2.addMap(map2temp);
map2temp.setScaleColor(new float[] {1.0f, 0.0f, 0.0f});
ScalarMap map2mixr = new ScalarMap(mixr, Display.XAxis);
display2.addMap(map2mixr);
map2mixr.setScaleColor(new float[] {0.0f, 1.0f, 0.0f});
ScalarMap map2ozone = new ScalarMap(ozone, Display.XAxis);
display2.addMap(map2ozone);
map2ozone.setScaleColor(new float[] {0.0f, 0.0f, 1.0f});
display2.addMap(new ScalarMap(pressure, Display.XAxis));
GraphicsModeControl mode2 = display2.getGraphicsModeControl();
mode2.setLineWidth(2.0f);
mode2.setScaleEnable(true);
// color temperature profile red
ConstantMap[] tmaps = {new ConstantMap(1.0f, Display.Red),
new ConstantMap(0.0f, Display.Green),
new ConstantMap(0.0f, Display.Blue)};
// color mixing ratio profile green
ConstantMap[] mmaps = {new ConstantMap(0.0f, Display.Red),
new ConstantMap(1.0f, Display.Green),
new ConstantMap(0.0f, Display.Blue)};
// color ozone profile blue
ConstantMap[] omaps = {new ConstantMap(0.0f, Display.Red),
new ConstantMap(0.0f, Display.Green),
new ConstantMap(1.0f, Display.Blue)};
// color pressure profile white
ConstantMap[] pmaps = {new ConstantMap(1.0f, Display.Red),
new ConstantMap(1.0f, Display.Green),
new ConstantMap(1.0f, Display.Blue)};
// enable direct manipulation for temperature, mixing ratio
// and ozone profiles; do not enable direct manipulation for
// pressure;
// note that addReferences rather than addReference is
// invoked for non-default DataRenderers (in this case,
// DirectManipulationRendererJ3D);
// note also that addReference and addReferences may take
// an array of ConstantMaps that apply only to one Data
// object
display2.addReferences(new DirectManipulationRendererJ3D(),
tempa_ref, tmaps);
display2.addReferences(new DirectManipulationRendererJ3D(),
mixra_ref, mmaps);
display2.addReferences(new DirectManipulationRendererJ3D(),
ozonea_ref, omaps);
display2.addReference(presa_ref, pmaps);
// construct Display 3 and its ScalarMaps
DisplayImplJ3D display3 = new DisplayImplJ3D("display3");
// explicitly set data range for nl values (in order to
// invert scale)
ScalarMap map3nl = new ScalarMap(nl, Display.YAxis);
map3nl.setRange(40.0, 1.0);
display3.addMap(map3nl);
display3.addMap(new ScalarMap(nchan, Display.XAxis));
display3.addMap(new ScalarMap(wfn, Display.ZAxis));
display3.addMap(new ScalarMap(wfn, Display.Green));
display3.addMap(new ConstantMap(0.5f, Display.Red));
display3.addMap(new ConstantMap(0.5f, Display.Blue));
GraphicsModeControl mode3 = display3.getGraphicsModeControl();
mode3.setScaleEnable(true);
// link weighting function difference Data object to display3
display3.addReference(diff_col_ref);
// construct Display 4 and its ScalarMaps (using non-default
// 2-D DisplayRenderer)
DisplayImplJ3D display4 =
new DisplayImplJ3D("display4", new TwoDDisplayRendererJ3D());
display4.addMap(new ScalarMap(nchan, Display.XAxis));
// explicitly set data range for tbc_d values
ScalarMap map4tbc_d = new ScalarMap(tbc_d, Display.YAxis);
map4tbc_d.setRange(-40.0, 40.0);
display4.addMap(map4tbc_d);
// set pointSize = 5 in display4 to make single Real value smr
// easily visible
GraphicsModeControl mode4 = display4.getGraphicsModeControl();
mode4.setPointSize(5.0f);
mode4.setLineWidth(2.0f);
mode4.setScaleEnable(true);
// link brightness temperature error, zero line and brightness
// temperature error root mean square Data objects to display4
display4.addReference(diff_ref);
display4.addReference(zero_line_ref);
display4.addReference(smr_ref);
// return DisplayImpls
displays[0] = display1;
displays[1] = display2;
displays[2] = display3;
displays[3] = display4;
}
/** construct user interface using JFC */
void setupUI(DisplayImpl[] displays, DataReference in_dx_ref,
DataReference save_config_ref, DataReference gzen_ref,
DataReference tskin_ref)
throws VisADException, RemoteException {
//
// construct JFC user interface with JSliders linked to
// Data objects, and embed Displays into JFC JFrame
//
// create a JFrame
JFrame frame = new JFrame("GoesCollaboration");
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
};
frame.addWindowListener(l);
frame.setSize(WIDTH, HEIGHT);
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(screenSize.width/2 - WIDTH/2,
screenSize.height/2 - HEIGHT/2);
// create big_panel JPanel in frame
JPanel big_panel = new JPanel();
big_panel.setLayout(new BoxLayout(big_panel, BoxLayout.X_AXIS));
big_panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
big_panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
frame.getContentPane().add(big_panel);
// create left hand side JPanel for sliders and text
JPanel left = new JPanel(); // FlowLayout and double buffer
left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS));
left.setAlignmentY(JPanel.TOP_ALIGNMENT);
left.setAlignmentX(JPanel.LEFT_ALIGNMENT);
big_panel.add(left);
// construct JLabels
// (JTextArea does not align in BoxLayout well, so use JLabels)
left.add(new JLabel("Interactive GOES satellite sounding " +
"retrieval"));
left.add(new JLabel("using VisAD - see:"));
left.add(new JLabel(" "));
left.add(new JLabel(" http://www.ssec.wisc.edu/~billh/visad.html"));
left.add(new JLabel(" "));
left.add(new JLabel("for more information about VisAD."));
left.add(new JLabel(" "));
left.add(new JLabel("Bill Hibbard, Paolo Antonelli and Bob Aune"));
left.add(new JLabel("Space Science and Engineering Center"));
left.add(new JLabel("University of Wisconsin - Madison"));
left.add(new JLabel(" "));
left.add(new JLabel(" "));
left.add(new JLabel("Move index slider to retrieve a new model"));
left.add(new JLabel("atmosphere."));
left.add(new JLabel(" "));
left.add(new JLabel("Touch ref. conf. slider to save a new"));
left.add(new JLabel("reference for weighting function " +
"difference."));
left.add(new JLabel(" "));
left.add(new JLabel("Move zenith angle and skin T sliders to"));
left.add(new JLabel("to modify atmosphere conditions."));
left.add(new JLabel(" "));
left.add(new JLabel("Rotate scenes with left mouse button."));
left.add(new JLabel(" "));
left.add(new JLabel("Redraw temperature, water vapor and ozone " +
"with"));
left.add(new JLabel("right mouse button to modify model " +
"atmosphere."));
left.add(new JLabel(" "));
left.add(new JLabel(" "));
// create sliders JPanel
JPanel sliders = new JPanel();
sliders.setName("GoesCollaboration Sliders");
sliders.setFont(new Font("Dialog", Font.PLAIN, 12));
sliders.setLayout(new BoxLayout(sliders, BoxLayout.Y_AXIS));
sliders.setAlignmentY(JPanel.TOP_ALIGNMENT);
sliders.setAlignmentX(JPanel.LEFT_ALIGNMENT);
left.add(sliders);
// construct VisADSliders linked to Real Data objects and embedded
// in sliders JPanel
sliders.add(new VisADSlider("index", 1, 2234, 1, 1.0, in_dx_ref,
RealType.Generic));
sliders.add(new JLabel(" "));
sliders.add(new VisADSlider("save as ref. conf.?", 0, 1000, 0, 1.0,
save_config_ref, RealType.Generic));
sliders.add(new JLabel(" "));
sliders.add(new VisADSlider("zenith angle (deg)", 0, 65, 35, 1.0,
gzen_ref, RealType.Generic));
sliders.add(new JLabel(" "));
sliders.add(new VisADSlider("skin T (K)", 250, 340, 300, 1.0,
tskin_ref, RealType.Generic));
// construct JPanel and sub-panels for Displays
JPanel display_panel = new JPanel();
display_panel.setLayout(new BoxLayout(display_panel,
BoxLayout.X_AXIS));
display_panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
display_panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
big_panel.add(display_panel);
JPanel display_left = new JPanel();
display_left.setLayout(new BoxLayout(display_left,
BoxLayout.Y_AXIS));
display_left.setAlignmentY(JPanel.TOP_ALIGNMENT);
display_left.setAlignmentX(JPanel.LEFT_ALIGNMENT);
display_panel.add(display_left);
JPanel display_right = new JPanel();
display_right.setLayout(new BoxLayout(display_right,
BoxLayout.Y_AXIS));
display_right.setAlignmentY(JPanel.TOP_ALIGNMENT);
display_right.setAlignmentX(JPanel.LEFT_ALIGNMENT);
display_panel.add(display_right);
// get Display panels
JPanel panel1 = (JPanel) displays[0].getComponent();
JPanel panel2 = (JPanel) displays[1].getComponent();
JPanel panel3 = (JPanel) displays[2].getComponent();
JPanel panel4 = (JPanel) displays[3].getComponent();
// make borders for Displays and embed in display_panel JPanel
Border etchedBorder10 =
new CompoundBorder(new EtchedBorder(),
new EmptyBorder(10, 10, 10, 10));
panel1.setBorder(etchedBorder10);
panel2.setBorder(etchedBorder10);
panel3.setBorder(etchedBorder10);
panel4.setBorder(etchedBorder10);
// make labels for Displays
JLabel display1_label = new JLabel("weighting function");
JLabel display1a_label =
new JLabel("vertical level (Y) vs channel (X)");
JLabel display2_label = new JLabel("model atmosphere profile");
JLabel display2a_label =
new JLabel("temperature (red), ozone (blue),");
JLabel display2b_label =
new JLabel("water vapor (green), pressure (white)");
JLabel display3_label = new JLabel("weighting function difference");
JLabel display3a_label =
new JLabel("vertical level (Y) vs channel (X)");
JLabel display4_label = new JLabel("brightness temperature errors");
JLabel display4a_label = new JLabel("with zero reference line and");
JLabel display4b_label =
new JLabel("root mean square error (single point)");
// embed Displays and their labels in display_panel JPanel
display_left.add(panel1);
display_left.add(display1_label);
display_left.add(display1a_label);
display_left.add(panel2);
display_left.add(display2_label);
display_left.add(display2a_label);
display_left.add(display2b_label);
display_right.add(panel3);
display_right.add(display3_label);
display_right.add(display3a_label);
display_right.add(panel4);
display_right.add(display4_label);
display_right.add(display4a_label);
display_right.add(display4b_label);
// make the JFrame visible
frame.setVisible(true);
}
/** get observed brightness temperatures, as well as temperature,
water-vapor mixing-ratio, ozone and pressure profiles */
class real_tbcCell extends CellImpl {
public void doAction() throws VisADException, RemoteException {
// get index into model atmospheres
int in_dx = (int) ((Real) in_dx_ref.getData()).getValue();
if (in_dx < 1 || in_dx > 2234) return;
// read observed brightness temperatures from data_obs_1.dat
float[][] data_b = new float[1][19];
re_read_1_c(in_dx, data_b[0]);
((FlatField) real_tbc_ref.getData()).setSamples(data_b);
// obtain climatological temperature, water-vapor mixing-ratio,
// and ozone mixing-ratio profiles by interpolating in month
// and latitude amongst the FASCODE model atmospheres;
// also get fixed pressure levels
float lat = data_b[0][18];
int month = 6;
float[][] t_x = new float[1][40];
float[][] m_x = new float[1][40];
float[][] o_x = new float[1][40];
float[][] p_x = new float[1][40];
get_profil_c(lat, month, t_x[0], m_x[0], o_x[0], p_x[0]);
((FlatField) tempa_ref.getData()).setSamples(t_x);
((FlatField) mixra_ref.getData()).setSamples(m_x);
((FlatField) ozonea_ref.getData()).setSamples(o_x);
((FlatField) presa_ref.getData()).setSamples(p_x);
}
}
/** compute weighting function of channel versus vertical level */
class wfnbCell extends CellImpl {
public void doAction() throws VisADException, RemoteException {
// get zenith angle and skin temperature
float gzen = (float) ((Real) gzen_ref.getData()).getValue();
float tskin = (float) ((Real) tskin_ref.getData()).getValue();
// compute weighting function of channel versus vertical level
float[][] t_x = Set.doubleToFloat(((FlatField)
tempa_ref.getData()).getValues());
float[][] m_x = Set.doubleToFloat(((FlatField)
mixra_ref.getData()).getValues());
float[][] o_x = Set.doubleToFloat(((FlatField)
ozonea_ref.getData()).getValues());
float[][] p_x = Set.doubleToFloat(((FlatField)
presa_ref.getData()).getValues());
float[][] wfn = new float[2][40*18];
goesrte_2_c(gzen, tskin, t_x[0], m_x[0], o_x[0], p_x[0],
wfn[0], wfn[1]);
((FlatField) wfnb_ref.getData()).setSamples(wfn);
}
}
/** compute brightness temperature errors and root mean square */
class wfnaCell extends CellImpl {
public void doAction() throws VisADException, RemoteException {
// compute brightness temperature errors
float[][] t_x = new float[1][];
float[][] wfn =
Set.doubleToFloat(((FlatField) wfnb_ref.getData()).getValues());
t_x[0] = wfn[0];
((FlatField) wfna_ref.getData()).setSamples(t_x);
float[][] real_tbc_x = Set.doubleToFloat(((FlatField)
real_tbc_ref.getData()).getValues());
float[][] diff_DATA_x = new float[1][18];
float squ_mod = 0.0f;
for (int c=0; c<18; c++) {
diff_DATA_x[0][c] = wfn[1][0 + 40 * c] - real_tbc_x[0][c];
squ_mod += diff_DATA_x[0][c] * diff_DATA_x[0][c] / 18.0f;
}
((FlatField) diff_ref.getData()).setSamples(diff_DATA_x);
// smr is root mean square of brightness temperature errors
smr_ref.setData(new Real(tbc_d, Math.sqrt(squ_mod)));
}
}
/** save a copy of wfna in wfna_old */
class wfna_oldCell extends CellImpl {
public void doAction() throws VisADException, RemoteException {
// save a copy of wfna in wfna_old (i.e., wfna_old = wfna)
wfna_old_ref.setData(
(FlatField) ((FlatField) wfna_ref.getData()).clone());
}
}
/** compute diff_col = wfna - wfna_old */
class diff_colCell extends CellImpl {
public void doAction() throws VisADException, RemoteException {
// compute diff_col = wfna - wfna_old
diff_col_ref.setData(
wfna_ref.getData().subtract(wfna_old_ref.getData()));
}
}
/** native method declarations, to Fortran via C */
private native void re_read_1_c(int i, float[] data_b);
private native void goesrte_2_c(float gzen, float tskin, float[] t,
float[] w, float[] c, float[] p,
float[] wfn, float[] tbcx);
private native void get_profil_c(float rlat, int imon, float[] tpro,
float[] wpro, float[] opro,
float[] pref);
}