Skip to content

Commit

Permalink
Added IGRA2 integration. Added GUI, CLI, and API interfaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
a-urq committed Sep 15, 2023
1 parent 3cbf672 commit 8653cb8
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 57 deletions.
Binary file not shown.
Binary file not shown.
Binary file modified bin/com/ameliaWx/soundingViewer/SoundingFrame.class
Binary file not shown.
12 changes: 6 additions & 6 deletions bin/com/ameliaWx/soundingViewer/res/controls.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html>
<head>
<meta charset='utf-8'>
<title>RadarView Help Page</title>
<title>Sounding Viewer Controls Page</title>
<style>
html{
font-family: sans-serif;
Expand Down Expand Up @@ -58,15 +58,15 @@ <h2>Parcel Path Options</h2>
<h3>Surface Based</h3>
<p><b>When to use:</b> Surface based storms. May be useful in assessing tornado potential in surface based supercells.</p>
<p><b>How it's calculated:</b> Sets the pressure, temperature, and dewpoint of the starting point to that of the environmental air at the surface.</p>
<h3>Mixed Layer (50 mb)</h3>
<p><b>When to use:</b> Surface based storms. May be most useful in storms with shallow inflow layers.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the lowest 50 mb of the atmosphere. Sets the pressure of the starting point to that of the surface air. Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and surface pressure.</p>
<h3>Mixed Layer (100 mb)</h3>
<p><b>When to use:</b> Surface based storms. May be most useful in storms with deep inflow layers.</p>
<h3>Mixed Layer</h3>
<p><b>When to use:</b> Surface based storms. Often used as a general-purpose indicator of storm strength.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the lowest 100 mb of the atmosphere. Sets the pressure of the starting point to that of the surface air. Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and surface pressure.</p>
<h3>Most Unstable</h3>
<p><b>When to use:</b> Elevated storms.</p>
<p><b>How it's calculated:</b> Finds the pressure level with the highest Theta-E (equivalent potential temperature). Sets the pressure, temperature, and dewpoint to the environmental air at that level.</p>
<h3>Inflow Layer</h3>
<p><b>When to use:</b> Any storm. Will display nothing if no inflow layer is found.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the effective inflow layer. Sets the pressure of the starting point to that of the inflow base (often the surface for surface-based storms). Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and inflow base pressure.</p>

<h2>Storm Motion Vector Options</h2>
<h3>Left Moving</h3>
Expand Down
Binary file not shown.
Binary file modified bin/com/ameliaWx/soundingViewer/unixTool/RadiosondeSite.class
Binary file not shown.
Binary file modified bin/com/ameliaWx/soundingViewer/unixTool/RadiosondeWrapper.class
Binary file not shown.
17 changes: 9 additions & 8 deletions src/com/ameliaWx/soundingViewer/SoundingFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import javax.swing.JComponent;
Expand Down Expand Up @@ -392,10 +393,10 @@ public SoundingFrame(String soundingSource, Sounding sounding0, DateTime time0,
ilcinh[i] = WeatherUtils.computeCinh(activeSounding.getPressureLevels(),
activeSounding.getTemperature(), activeSounding.getDewpoint(), parcelPathInflowLayer[i]);

sbLcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathSurfaceBased[i]);
ilLcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathInflowLayer[i]);
mlLcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathMixedLayer[i]);
muLcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathMostUnstable[i]);
sbLcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathSurfaceBased[i]);
ilLcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathInflowLayer[i]);
mlLcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathMixedLayer[i]);
muLcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathMostUnstable[i]);

sbCcl[i] = WeatherUtils.convectiveCondensationLevel(activeSounding.getPressureLevels(),
activeSounding.getTemperature(), activeSounding.getDewpoint(), parcelPathSurfaceBased[i]);
Expand Down Expand Up @@ -442,10 +443,10 @@ public SoundingFrame(String soundingSource, Sounding sounding0, DateTime time0,
muecinh[i] = WeatherUtils.computeCinh(activeSounding.getPressureLevels(),
activeSounding.getTemperature(), activeSounding.getDewpoint(), parcelPathMostUnstableEntr[i]);

sbELcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathSurfaceBasedEntr[i]);
ilELcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathInflowLayerEntr[i]);
mlELcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathMixedLayerEntr[i]);
muELcl[i] = WeatherUtils.liftedCondensationLevel(surfacePressure, parcelPathMostUnstableEntr[i]);
sbELcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathSurfaceBasedEntr[i]);
ilELcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathInflowLayerEntr[i]);
mlELcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathMixedLayerEntr[i]);
muELcl[i] = WeatherUtils.liftedCondensationLevel(parcelPathMostUnstableEntr[i]);

sbECcl[i] = WeatherUtils.convectiveCondensationLevel(activeSounding.getPressureLevels(),
activeSounding.getTemperature(), activeSounding.getDewpoint(), parcelPathSurfaceBasedEntr[i]);
Expand Down
12 changes: 6 additions & 6 deletions src/com/ameliaWx/soundingViewer/res/controls.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html>
<head>
<meta charset='utf-8'>
<title>RadarView Help Page</title>
<title>Sounding Viewer Controls Page</title>
<style>
html{
font-family: sans-serif;
Expand Down Expand Up @@ -58,15 +58,15 @@ <h2>Parcel Path Options</h2>
<h3>Surface Based</h3>
<p><b>When to use:</b> Surface based storms. May be useful in assessing tornado potential in surface based supercells.</p>
<p><b>How it's calculated:</b> Sets the pressure, temperature, and dewpoint of the starting point to that of the environmental air at the surface.</p>
<h3>Mixed Layer (50 mb)</h3>
<p><b>When to use:</b> Surface based storms. May be most useful in storms with shallow inflow layers.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the lowest 50 mb of the atmosphere. Sets the pressure of the starting point to that of the surface air. Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and surface pressure.</p>
<h3>Mixed Layer (100 mb)</h3>
<p><b>When to use:</b> Surface based storms. May be most useful in storms with deep inflow layers.</p>
<h3>Mixed Layer</h3>
<p><b>When to use:</b> Surface based storms. Often used as a general-purpose indicator of storm strength.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the lowest 100 mb of the atmosphere. Sets the pressure of the starting point to that of the surface air. Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and surface pressure.</p>
<h3>Most Unstable</h3>
<p><b>When to use:</b> Elevated storms.</p>
<p><b>How it's calculated:</b> Finds the pressure level with the highest Theta-E (equivalent potential temperature). Sets the pressure, temperature, and dewpoint to the environmental air at that level.</p>
<h3>Inflow Layer</h3>
<p><b>When to use:</b> Any storm. Will display nothing if no inflow layer is found.</p>
<p><b>How it's calculated:</b> Computes the average potential temperature and mixing ratio in the effective inflow layer. Sets the pressure of the starting point to that of the inflow base (often the surface for surface-based storms). Computes the parcel temperature using the average potential temperature and surface pressure and the parcel dewpoint using the average mixing ratio and inflow base pressure.</p>

<h2>Storm Motion Vector Options</h2>
<h3>Left Moving</h3>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ameliaWx.soundingViewer.unixTool;

public class RadiosondeNotFoundException extends Exception {
private static final long serialVersionUID = -6787054422626219881L;

public RadiosondeNotFoundException(String errorMessage) {
super(errorMessage);
}
}
73 changes: 71 additions & 2 deletions src/com/ameliaWx/soundingViewer/unixTool/RadiosondeSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import java.util.Scanner;

import org.apache.commons.io.FileUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class RadiosondeSite implements Comparable<RadiosondeSite> {
public static String dataFolder = System.getProperty("user.home") + "/Documents/SoundingViewer/data/";
Expand Down Expand Up @@ -52,6 +54,10 @@ public RadiosondeSite(String internationalCode, String fourLetterCode, double la
static {
initializeSites();
}

public static void init() {
initializeSites();
}

public static void main(String[] args) {
// for(int i = 0; i < sites.size(); i++) {
Expand All @@ -63,6 +69,9 @@ public static void main(String[] args) {
System.out.println(findSite("KOUN"));
}

private static String[][] countryListArr = null;
private static String[][] usStatesArr = null;

private static void initializeSites() {
try {
File stationList = downloadFile(
Expand All @@ -79,16 +88,19 @@ private static void initializeSites() {
File fourLetterCodes = loadResourceAsFile("res/fourLetterCodes.txt");

String[][] stationListArr = parseFixedWidth(stationList, 11, 9, 10, 7, 4, 30, 5, 6, 5);
String[][] usStatesArr = parseFixedWidth(usStatesList, 2, 40);
String[][] countryListArr = parseFixedWidth(countryList, 2, 40);
usStatesArr = parseFixedWidth(usStatesList, 2, 40);
countryListArr = parseFixedWidth(countryList, 2, 40);
String[][] fourLetterCodesArr = parseFixedWidth(fourLetterCodes, 11, 40);

HashMap<String, String> usStatesMap = arrToHashMap(usStatesArr);
HashMap<String, String> countryListMap = arrToHashMap(countryListArr);
HashMap<String, String> fourLetterCodesMap = arrToHashMap(fourLetterCodesArr);

sites = new ArrayList<>();

for (String[] line : stationListArr) {
// System.out.println(Arrays.toString(line));
// System.out.println(sites.size());

String internationalCode = line[0];
double latitude = Double.valueOf(line[1]);
Expand Down Expand Up @@ -258,6 +270,63 @@ public int getEndYear() {
public int getNumRecords() {
return numRecords;
}

public static String[] getCountries() {
String[] countries = new String[countryListArr.length];

countries[0] = "United States";

boolean detectedUS = false;

for(int i = 0; i < countries.length; i++) {
if(detectedUS) {
countries[i] = countryListArr[i][1];
} else {
if("United States".equals(countryListArr[i][1])) {
detectedUS = true;
continue;
}

countries[i + 1] = countryListArr[i][1];
}
}

return countries;
}

public static String[] getUsStates() {
String[] states = new String[usStatesArr.length];

for(int i = 0; i < states.length; i++) {
states[i] = usStatesArr[i][1];
}

return states;
}

public static RadiosondeSite[] getSitesInRegion(String country, String state, boolean current) {
ArrayList<RadiosondeSite> sitesList = new ArrayList<>();

DateTime nowMinus7 = DateTime.now(DateTimeZone.UTC).minusDays(7);

for(int i = 0; i < sites.size(); i++) {
// System.out.println(sites.get(i));
if(country.equals(sites.get(i).getCountry()) && state.equals(sites.get(i).getState())) {
if(!current || sites.get(i).getEndYear() >= nowMinus7.getYear()) {
sitesList.add(sites.get(i));
}
}

// System.out.println(sitesList.size());
}

RadiosondeSite[] sites = new RadiosondeSite[sitesList.size()];
for(int i = 0; i < sitesList.size(); i++) {
sites[i] = sitesList.get(i);
}

return sites;
}

public static File loadResourceAsFile(String urlStr) {
// System.out.println(urlStr);
Expand Down
Loading

0 comments on commit 8653cb8

Please sign in to comment.