Skip to content

Commit

Permalink
Merge pull request #7 from AdenKoperczak/add_max_data_type
Browse files Browse the repository at this point in the history
Add max data type
  • Loading branch information
AdenKoperczak authored Dec 18, 2024
2 parents 647195e + 39c95ca commit 7200d79
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 5 deletions.
28 changes: 24 additions & 4 deletions grib2pf-ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from PySide6.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, \
QLineEdit, QCheckBox, QSpinBox, QHBoxLayout, QVBoxLayout, QToolButton, \
QPushButton, QFileDialog, QTableView, QMessageBox, QInputDialog, \
QComboBox, QDialog, QTreeView
QComboBox, QDialog, QTreeView, QDoubleSpinBox
from PySide6.QtCore import Qt, Signal, QModelIndex, QAbstractTableModel, \
QMimeData, QSortFilterProxyModel, QThread
from PySide6.QtGui import QKeySequence, QClipboard, QIcon, QStandardItemModel, \
Expand Down Expand Up @@ -215,13 +215,17 @@ class PlacefileEditor(QWidget):
"regenerateTime": 60,
"pullPeriod": 10,
"gzipped": True,
"renderMode": "Average_Data"
"renderMode": "Average_Data",
"minimum": -998,
"threshold": 0,
}

RENDER_MODES = [
["Averaging", "Average_Data"],
["Nearest", "Nearest_Data"],
["Nearest", "Nearest_Fast_Data"],
["Nearest Fast", "Nearest_Fast_Data"],
["Maximum", "Max_Data"],
["Minimum", "Min_Data"],
]
MAIN_TYPES = [
["Basic", "basic"],
Expand Down Expand Up @@ -264,6 +268,8 @@ def __init__(self, *args, **kwargs):
"pullPeriod": QSpinBox(),
"gzipped": QCheckBox(),
"renderMode": QComboBox(),
"minimum": QDoubleSpinBox(),
"threshold": QDoubleSpinBox(),
}

self.dataWidgets["refresh"].setMinimum(15)
Expand All @@ -284,6 +290,14 @@ def __init__(self, *args, **kwargs):
self.dataWidgets["timeout"].setMinimum(1)
self.dataWidgets["timeout"].setMaximum(60)

self.dataWidgets["minimum"].setMinimum(-9999999)
self.dataWidgets["minimum"].setMaximum(9999999)
self.dataWidgets["minimum"].setDecimals(4)

self.dataWidgets["threshold"].setMinimum(-9999999)
self.dataWidgets["threshold"].setMaximum(9999999)
self.dataWidgets["threshold"].setDecimals(4)

self.dataWidgets["aws"].stateChanged.connect(self.change_enabled_callback)

for name, value in self.RENDER_MODES:
Expand All @@ -298,13 +312,16 @@ def __init__(self, *args, **kwargs):
view = [
("Title", "title", False, "The title to be used in Supercell-Wx for this Placefile"),
("Type of Product", "mainType", False, "The type of product to produce."),
("Render Mode", "renderMode", False, "How data is transformed into an image."),
("AWS", "aws", False, "Pull from AWS instead of a URL. Recommended."),
("Product", "product", False, "The product to pull from AWS."),
("Precipitation Flag Product", "typeProduct", False, "The product to pull from AWS."),
("Reflectivity Product", "reflProduct", False, "The product to pull from AWS."),
("URL", "url", False, "The URL to pull the GRIB/MRMS data from."),
("Image File", "imageFile", False, "The path to where the image (png) should be generated"),
("Place File", "placeFile", False, "The path to where the placefile should be generated"),
("Minimum", "minimum", True, "The minimum value which is considered valid."),
("Threshold", "threshold", True, "The threshold value for the placefile"),
("Refresh (s)", "refresh", False, "How often Supercell-Wx should refresh the placefile. Often is OK for local files."),
("Regeneration Period", "regenerateTime", False, "How often the placefile should be regenerated."),
("Pull Period", "pullPeriod", False, "How often AWS should be pulled for new data."),
Expand All @@ -318,7 +335,6 @@ def __init__(self, *args, **kwargs):
("Gzipped", "gzipped", False, "If the GRIB file is Gzip compressed. True for MRMS"),
("Verbose", "verbose", False, "If grib2pf should 'print' out information"),
("Timeout", "timeout", True, "The time grib2pf should wait for a response from the URL."),
("Render Mode", "renderMode", False, "How data is transformed into an image. Average is better for most data. Nearest is better for digital data like precipitation flags."),
]

for i, (text, name, optional, tooltip) in enumerate(view):
Expand Down Expand Up @@ -381,6 +397,8 @@ def set_settings(self, settings):
elif isinstance(widget, QComboBox):
index = widget.findData(value)
widget.setCurrentIndex(index)
elif isinstance(widget, QDoubleSpinBox):
widget.setValue(value)

if name in self.enableWidgets:
self.enableWidgets[name].setChecked(enabled)
Expand Down Expand Up @@ -408,6 +426,8 @@ def get_settings(self):
settings[name] = widget.get_product()
elif isinstance(widget, QComboBox):
settings[name] = widget.currentData()
elif isinstance(widget, QDoubleSpinBox):
settings[name] = widget.value()
return settings

class FilePicker(QWidget):
Expand Down
5 changes: 5 additions & 0 deletions grib2pf.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def __init__(
height = 1080,
verbose = False,
timeout = 30,
minimum = -998,
mode = "Nearest_Data",
threshold = 0):

Expand All @@ -73,6 +74,7 @@ def __init__(
self.height = height
self.verbose = verbose
self.timeout = timeout
self.minimum = minimum
self.mode = mode
self.threshold = threshold

Expand All @@ -93,6 +95,7 @@ def _generate(self):
"title": self.title,
"mode": self.mode,
"offset": 0,
"minimum": self.minimum,
}])
lib = Grib2PfLib()
err, lonL, lonR, latT, latB = lib.generate_image(settings)
Expand Down Expand Up @@ -161,6 +164,7 @@ def __init__(self, settings):
"typeUrl": settings.get("typeUrl", None),
"reflUrl": settings.get("reflUrl", None),
"timeout": settings.get("timeout", 30),
"minimum": settings.get("minimum", -998),
"title": settings.get("title", None),
"verbose": settings.get("verbose", False),
"gzipped": settings.get("gzipped", False),
Expand Down Expand Up @@ -260,6 +264,7 @@ async def run_setting(settings):
settings.get("imageHeight", 1080),
settings.get("verbose", False),
settings.get("timeout", 30),
settings.get("minimum", -998),
settings.get("renderMode", "Average_Data"),
settings.get("threshold", 0))

Expand Down
10 changes: 9 additions & 1 deletion grib2pflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ def _parse_color(self, text, colorType, optional):
RenderModes = {
"Average_Data": 0,
"Nearest_Data": 1,
"Nearest_Fast_Data": 2,
"Max_Data": 3,
"Min_Data": 4,
}

class MessageSettings(Structure):
Expand All @@ -175,11 +178,12 @@ class MessageSettings(Structure):
("imageHeight", c_size_t),
("title", c_char_p),
("mode", c_int),
("minimum", c_double),
("offset", c_size_t),
]

def set(self, imageFile, palette, imageWidth, imageHeight, title,
mode, offset):
mode, offset, minimum):

if isinstance(mode, str):
mode = RenderModes[mode]
Expand All @@ -196,6 +200,7 @@ def set(self, imageFile, palette, imageWidth, imageHeight, title,
self.title = c_char_p(title.encode("utf-8"))
self.mode = c_int(mode)
self.offset = c_size_t(offset)
self.minimum = c_double(minimum)

class Settings(Structure):
_fields_ = [
Expand Down Expand Up @@ -237,6 +242,7 @@ class MRMSTypedReflSettings(Structure):
("rainPalette", POINTER(ColorTable)),
("snowPalette", POINTER(ColorTable)),
("hailPalette", POINTER(ColorTable)),
("minimum", c_double),
("imageWidth", c_size_t),
("imageHeight", c_size_t),
("mode", c_int),
Expand All @@ -246,6 +252,7 @@ def __init__(self,
typeUrl,
reflUrl,
timeout,
minimum,
title,
verbose,
gzipped,
Expand Down Expand Up @@ -287,6 +294,7 @@ def __init__(self,
self.rainPalette = pointer(self.rainPalette_)
self.snowPalette = pointer(self.snowPalette_)
self.hailPalette = pointer(self.hailPalette_)
self.minimum = c_double(minimum)
self.imageWidth = c_size_t(imageWidth)
self.imageHeight = c_size_t(imageHeight)
self.mode = c_int(mode)
Expand Down
4 changes: 4 additions & 0 deletions include/grib2pf.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ typedef enum RenderMode {
Average_Data = 0,
Nearest_Data = 1,
Nearest_Fast_Data = 2,
Max_Data = 3,
Min_Data = 4,
} RenderMode;

typedef struct {
Expand All @@ -21,6 +23,7 @@ typedef struct {
size_t imageHeight;
const char* title;
/*RenderMode*/int mode;
double minimum;

size_t offset;
} MessageSettings;
Expand Down Expand Up @@ -48,6 +51,7 @@ typedef struct {
const ColorTable* rainPalette;
const ColorTable* snowPalette;
const ColorTable* hailPalette;
double minimum;
size_t imageWidth;
size_t imageHeight;
/*RenderMode*/int mode;
Expand Down
80 changes: 80 additions & 0 deletions source/grib2pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ ImageData generate_image_data(MessageSettings* message, uint8_t* d, size_t size,
double lon = latLonValues[i + 1];
double value = latLonValues[i + 2];

if (value < message->minimum) {
continue;
}

double x = (lon - lonL) * xM;
double y;
if (lat == lastLat) {
Expand Down Expand Up @@ -438,6 +442,10 @@ ImageData generate_image_data(MessageSettings* message, uint8_t* d, size_t size,
double lon = latLonValues[i + 1];
double value = latLonValues[i + 2];

if (value < message->minimum) {
continue;
}

double x = (lon - lonL) * xM;
double y;
if (lat == lastLat) {
Expand Down Expand Up @@ -467,6 +475,76 @@ ImageData generate_image_data(MessageSettings* message, uint8_t* d, size_t size,
}
}
free(nearestDist);
break; }
case Max_Data: {
for (size_t i = 0; i < latLonValuesSize; i += 3) {
double lat = latLonValues[i + 0];
double lon = latLonValues[i + 1];
double value = latLonValues[i + 2];

if (value < message->minimum) {
continue;
}

double x = (lon - lonL) * xM;
double y;
if (lat == lastLat) {
y = lastY;
} else {
y = (PROJECT_LAT_Y(lat) - yB) * yM;
lastLat = lat;
lastY = y;
}

if (x < 0 || y < 0 ||
x >= message->imageWidth || y >= message->imageHeight) {
continue;
}
size_t iX = (size_t) x;
size_t iY = (size_t) y;
size_t index = iX + iY * message->imageWidth;

if (imageData[index] < value || counts[index] == 0) {
imageData[index] = value;
counts[index] = 1;
}
}

break; }
case Min_Data: {
for (size_t i = 0; i < latLonValuesSize; i += 3) {
double lat = latLonValues[i + 0];
double lon = latLonValues[i + 1];
double value = latLonValues[i + 2];

if (value < message->minimum) {
continue;
}

double x = (lon - lonL) * xM;
double y;
if (lat == lastLat) {
y = lastY;
} else {
y = (PROJECT_LAT_Y(lat) - yB) * yM;
lastLat = lat;
lastY = y;
}

if (x < 0 || y < 0 ||
x >= message->imageWidth || y >= message->imageHeight) {
continue;
}
size_t iX = (size_t) x;
size_t iY = (size_t) y;
size_t index = iX + iY * message->imageWidth;

if (imageData[index] > value || counts[index] == 0) {
imageData[index] = value;
counts[index] = 1;
}
}

break; }
}
free(latLonValues);
Expand Down Expand Up @@ -582,6 +660,7 @@ int generate_mrms_typed_refl(const MRMSTypedReflSettings* settings,
.title = settings->title,
.mode = settings->mode,
.offset = 0,
.minimum = settings->minimum,
};
ImageData reflData = generate_image_data(&message1, data1.gribStart,
data1.totalSize, settings->verbose);
Expand All @@ -605,6 +684,7 @@ int generate_mrms_typed_refl(const MRMSTypedReflSettings* settings,
.title = settings->title,
.mode = Nearest_Fast_Data,
.offset = 0,
.minimum = -1,
};
DownloadedData data2 = download_data(&downloadS2);
if (data2.error) {
Expand Down

0 comments on commit 7200d79

Please sign in to comment.