diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3decb62690..90c5447de5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ ci: autoupdate_schedule: quarterly repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.15" + rev: "v0.2.0" hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/htdocs/agclimate/smts.php b/htdocs/agclimate/smts.php index 53b0836a67..c1ea048ad5 100644 --- a/htdocs/agclimate/smts.php +++ b/htdocs/agclimate/smts.php @@ -42,21 +42,17 @@ $d2 = daySelect2($day2, "day2"); $h2 = hourSelect($hour2, "hour2"); -$ar = array( - "1" => "3 Panel Plot", - "2" => "Just Soil Temps", - "sm" => "Just Soil Moisture", - "3" => "Daily Max/Min 4 Inch Soil Temps", - "4" => "Daily Solar Radiation", - "5" => "Daily Potential Evapotranspiration", - "encrh" => "Enclosure Relative Humidity", - "6" => "Histogram of Volumetric Soil Moisture", - "7" => "Daily Soil Water + Change", - "8" => "Battery Voltage", - "9" => "Daily Rainfall, 4 inch Soil Temp, and RH", - "10" => "Inversion Diagnostic Plot (BOOI4, CAMI4, CRFI4)", - "11" => "Inversion Timing (BOOI4, CAMI4, CRFI4)", -); +// Retreive the autoplot description JSON +$content = file_get_contents("http://iem.local/plotting/auto/meta/177.json"); +$meta = json_decode($content, $assoc=TRUE); + +foreach ($meta["arguments"] as $arg) { + if ($arg["name"] == "opt") { + $ar = $arg["options"]; + break; + } +} + $dd = "This plot is a time series graph of observations from a time period and ISU Soil Moisture station of your choice."; $desc = array( @@ -70,6 +66,12 @@ "7" => $dd, "8" => $dd ); +$desc["m"] = << datetime.timedelta(days=5): + table = "sm_hourly" + barwidth = 1 / 24.0 + with get_sqlalchemy_conn("isuag") as conn: + df = pd.read_sql( + f"SELECT * from {table} WHERE " + "station = %s and valid BETWEEN %s and %s ORDER by valid ASC", + conn, + params=(ctx["station"], ctx["sts"], ctx["ets"]), + index_col="valid", + ) + if df.empty: + raise NoDataFound("No Data Found for This Plot.") + fig = figure( + title=f"ISUSM Station: {ctx['_sname']} Timeseries", + apctx=ctx, + ) + axes = fig.subplots(2, 1, sharex=True) + ax = axes[0] + ax.plot(df.index.values, c2f(df["tair_c_avg_qc"]), color="r", label="Air") + dwpf = ( + dewpoint_from_relative_humidity( + units("degC") * df["tair_c_avg_qc"].values, + units("percent") * df["rh_avg_qc"].values, + ) + .to(units("degF")) + .m + ) + ax.plot(df.index.values, dwpf, color="g", label="Dew Point") + ax.grid(True) + ax.set_ylabel(r"Temperature $^\circ$F") + ax.legend(loc="best", ncol=2) + + # ---------------- + ax = axes[1] + ax.bar(df.index.values, df["ws_mph_max_qc"], width=barwidth, color="r") + ax.bar(df.index.values, df["ws_mph_qc"], width=barwidth, color="b") + ax.grid(True) + ax.set_ylabel("Wind Speed [MPH]") + + ax2 = ax.twinx() + ax2.scatter(df.index.values, df["winddir_d1_wvt_qc"], color="g") + ax2.set_ylabel("Wind Direction [deg]") + ax2.set_ylim(-1, 361) + ax2.set_yticks(range(0, 361, 45)) + ax2.set_yticklabels(["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"]) + + handles = [ + Line2D([0], [0], color="r", lw=2, label="Max Gust"), + Line2D([0], [0], color="b", lw=2, label="Avg Wind"), + Line2D([0], [0], color="g", lw=2, label="Wind Dir"), + ] + ax.legend( + handles=handles, + loc=(0.5, 1.04), + ncol=3, + fontsize=10, + ) + + xaxis_magic(ctx, ax) + return fig, df + + def plot1(ctx): """Do main plotting logic""" with get_sqlalchemy_conn("isuag") as conn: @@ -983,10 +1052,11 @@ def xaxis_magic(ctx, ax): def plotter(fdict): """Go""" ctx = get_autoplot_context(fdict, get_description()) - ctx["pgconn"] = get_dbconn("isuag") if ctx["opt"] == "1": fig, df = plot1(ctx) + if ctx["opt"] == "m": + fig, df = plot_meteogram(ctx) elif ctx["opt"] == "2": fig, df = plot2(ctx) elif ctx["opt"] == "at": @@ -1038,10 +1108,4 @@ def plotter(fdict): if __name__ == "__main__": - plotter( - { - "station": "BOOI4", - "opt": "11", - "sts": "2012-01-01 0000", - } - ) + plotter({}) diff --git a/pyproject.toml b/pyproject.toml index 498127e649..835ff2ded5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,5 +3,5 @@ filterwarnings = ["ignore:numpy.ndarray size changed:RuntimeWarning"] [tool.ruff] line-length = 79 -select = ["E", "F", "I"] +lint.select = ["E", "F", "I"] target-version = "py39" diff --git a/scripts/ingestors/asos_1minute/parse_ncdc_asos1minute.py b/scripts/ingestors/asos_1minute/parse_ncdc_asos1minute.py index 0485e3ad96..4accfdc56b 100644 --- a/scripts/ingestors/asos_1minute/parse_ncdc_asos1minute.py +++ b/scripts/ingestors/asos_1minute/parse_ncdc_asos1minute.py @@ -31,6 +31,7 @@ from tqdm import tqdm LOG = logger() +pd.set_option("future.no_silent_downcasting", True) HIDDENURL = "https://www.ncei.noaa.gov/pub/download/hidden/onemin" BASEDIR = "/mesonet/ARCHIVE/raw/asos/data" TMPDIR = "/mesonet/tmp/asos1min" @@ -360,7 +361,7 @@ def merge_archive_end(df, dt): ) LOG.info("found %s stations in the archive", len(df2.index)) df["archive_end"] = df2["max"] - df["archive_end"] = df["archive_end"].fillna(DT1980) + df["archive_end"] = df["archive_end"].fillna(DT1980).infer_objects() def dl_realtime(df, dt, mdt, page):