diff --git a/README.md b/README.md
index 91c38610..62e84e19 100644
--- a/README.md
+++ b/README.md
@@ -36,19 +36,21 @@ Documentation is provided via the included examples folders as well as [online d
## Engaging on GitHub
-FLORIS leverages the following GitHub features to coordinate support and development efforts:
+FLASC leverages the following GitHub features to coordinate support and development efforts:
- [Discussions](https://github.com/NREL/flasc/discussions): Collaborate to develop ideas for new use cases, features, and software designs, and get support for usage questions
- [Issues](https://github.com/NREL/flasc/issues): Report potential bugs and well-developed feature requests
- [Projects](https://github.com/orgs/NREL/projects/39): Include current and future work on a timeline and assign a person to "own" it
+Your feedback is crucial in this environment, as it helps identify areas for enhancement, resolve issues, and ensure the project meets the needs of its users. By sharing your insights and suggestions, you contribute to the project's evolution and success.
+
Generally, the first entry point for the community will be within one of the
categories in Discussions.
[Ideas](https://github.com/NREL/flasc/discussions/categories/ideas) is a great spot to develop the
details for a feature request. [Q&A](https://github.com/NREL/flasc/discussions/categories/q-a)
is where to get usage support.
[Show and tell](https://github.com/NREL/flasc/discussions/categories/show-and-tell) is a free-form
-space to show off the things you are doing with FLORIS.
+space to show off the things you are doing with FLASC.
# License
diff --git a/examples_smarteole/09_wake_steering_uplift_analysis.ipynb b/examples_smarteole/09_wake_steering_uplift_analysis.ipynb
new file mode 100644
index 00000000..e761eeca
--- /dev/null
+++ b/examples_smarteole/09_wake_steering_uplift_analysis.ipynb
@@ -0,0 +1,3546 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Analyze Wake Steering Uplift\n",
+ "\n",
+ "In this notebook we will calculate the energy uplift and uncertainty of wake steering."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:31.952395Z",
+ "start_time": "2024-08-12T18:41:31.948228Z"
+ }
+ },
+ "source": [
+ "from pathlib import Path\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd"
+ ],
+ "outputs": [],
+ "execution_count": 26
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:31.972433Z",
+ "start_time": "2024-08-12T18:41:31.953492Z"
+ }
+ },
+ "source": [
+ "# Suppress warnings\n",
+ "import warnings\n",
+ "\n",
+ "warnings.filterwarnings(\"ignore\")"
+ ],
+ "outputs": [],
+ "execution_count": 27
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Step 0: Load processed data\n",
+ "\n",
+ "Load the processed SCADA data with power curve filtering and northing calibration applied and inspect"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.005763Z",
+ "start_time": "2024-08-12T18:41:31.972433Z"
+ }
+ },
+ "source": [
+ "timebase_s = 60\n",
+ "\n",
+ "\n",
+ "def load_data(timebase_s: int = 60):\n",
+ " root_path = Path.cwd()\n",
+ " f = root_path / \"postprocessed\" / \"df_scada_data_60s_filtered_and_northing_calibrated.ftr\"\n",
+ " df_scada = pd.read_feather(f)\n",
+ "\n",
+ " if timebase_s != 60:\n",
+ " import flasc.data_processing.time_operations as fto\n",
+ "\n",
+ " cols_angular = [c for c in df_scada if ((\"wd_\" in c) or (\"yaw_\" in c))]\n",
+ " df_scada = fto.df_downsample(\n",
+ " df_scada,\n",
+ " cols_angular=cols_angular,\n",
+ " window_width=pd.Timedelta(seconds=timebase_s),\n",
+ " )\n",
+ "\n",
+ " return df_scada\n",
+ "\n",
+ "\n",
+ "df_scada = load_data(timebase_s)"
+ ],
+ "outputs": [],
+ "execution_count": 28
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.024932Z",
+ "start_time": "2024-08-12T18:41:32.005763Z"
+ }
+ },
+ "source": [
+ "df_scada.head()"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " time pow_000 pow_001 pow_002 pow_003 \\\n",
+ "0 2020-02-17 16:30:00 2023.746948 2045.376953 2031.724976 NaN \n",
+ "1 2020-02-17 16:31:00 1959.036011 2050.572998 2034.890991 NaN \n",
+ "2 2020-02-17 16:32:00 2053.658936 2032.191040 2011.870972 NaN \n",
+ "3 2020-02-17 16:33:00 2044.296997 2060.478027 1995.057983 NaN \n",
+ "4 2020-02-17 16:34:00 2058.281006 2042.703003 2031.723999 NaN \n",
+ "\n",
+ " pow_004 pow_005 pow_006 ws_000 ws_001 ... \\\n",
+ "0 2028.063965 2032.461060 1983.390991 13.066 12.337 ... \n",
+ "1 2017.777954 1943.764038 2046.568970 12.091 13.057 ... \n",
+ "2 NaN 2052.092041 2039.948975 13.381 12.213 ... \n",
+ "3 NaN 2008.868042 2058.000000 14.345 13.141 ... \n",
+ "4 NaN 1819.896973 2059.760010 14.338 12.723 ... \n",
+ "\n",
+ " is_operation_normal_005 is_operation_normal_006 wind_vane_005 \\\n",
+ "0 True True 3.299 \n",
+ "1 True True 1.825 \n",
+ "2 True True 8.314 \n",
+ "3 True True 2.384 \n",
+ "4 True True 17.271 \n",
+ "\n",
+ " target_yaw_offset_005 control_mode wd_smarteole ws_smarteole \\\n",
+ "0 -0.0 baseline 251.041669 12.582482 \n",
+ "1 -0.0 baseline 251.282677 12.823891 \n",
+ "2 -0.0 baseline 252.874153 12.859400 \n",
+ "3 -0.0 baseline 251.341539 13.426766 \n",
+ "4 -0.0 baseline 253.343030 13.225105 \n",
+ "\n",
+ " pow_ref_smarteole ti wd \n",
+ "0 2021.060059 0.11 251.377068 \n",
+ "1 2022.767212 0.11 251.485048 \n",
+ "2 2034.417480 0.11 253.473037 \n",
+ "3 2039.458252 0.11 251.104001 \n",
+ "4 2048.116943 0.11 255.679234 \n",
+ "\n",
+ "[5 rows x 37 columns]"
+ ],
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " time | \n",
+ " pow_000 | \n",
+ " pow_001 | \n",
+ " pow_002 | \n",
+ " pow_003 | \n",
+ " pow_004 | \n",
+ " pow_005 | \n",
+ " pow_006 | \n",
+ " ws_000 | \n",
+ " ws_001 | \n",
+ " ... | \n",
+ " is_operation_normal_005 | \n",
+ " is_operation_normal_006 | \n",
+ " wind_vane_005 | \n",
+ " target_yaw_offset_005 | \n",
+ " control_mode | \n",
+ " wd_smarteole | \n",
+ " ws_smarteole | \n",
+ " pow_ref_smarteole | \n",
+ " ti | \n",
+ " wd | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 2020-02-17 16:30:00 | \n",
+ " 2023.746948 | \n",
+ " 2045.376953 | \n",
+ " 2031.724976 | \n",
+ " NaN | \n",
+ " 2028.063965 | \n",
+ " 2032.461060 | \n",
+ " 1983.390991 | \n",
+ " 13.066 | \n",
+ " 12.337 | \n",
+ " ... | \n",
+ " True | \n",
+ " True | \n",
+ " 3.299 | \n",
+ " -0.0 | \n",
+ " baseline | \n",
+ " 251.041669 | \n",
+ " 12.582482 | \n",
+ " 2021.060059 | \n",
+ " 0.11 | \n",
+ " 251.377068 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 2020-02-17 16:31:00 | \n",
+ " 1959.036011 | \n",
+ " 2050.572998 | \n",
+ " 2034.890991 | \n",
+ " NaN | \n",
+ " 2017.777954 | \n",
+ " 1943.764038 | \n",
+ " 2046.568970 | \n",
+ " 12.091 | \n",
+ " 13.057 | \n",
+ " ... | \n",
+ " True | \n",
+ " True | \n",
+ " 1.825 | \n",
+ " -0.0 | \n",
+ " baseline | \n",
+ " 251.282677 | \n",
+ " 12.823891 | \n",
+ " 2022.767212 | \n",
+ " 0.11 | \n",
+ " 251.485048 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 2020-02-17 16:32:00 | \n",
+ " 2053.658936 | \n",
+ " 2032.191040 | \n",
+ " 2011.870972 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2052.092041 | \n",
+ " 2039.948975 | \n",
+ " 13.381 | \n",
+ " 12.213 | \n",
+ " ... | \n",
+ " True | \n",
+ " True | \n",
+ " 8.314 | \n",
+ " -0.0 | \n",
+ " baseline | \n",
+ " 252.874153 | \n",
+ " 12.859400 | \n",
+ " 2034.417480 | \n",
+ " 0.11 | \n",
+ " 253.473037 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 2020-02-17 16:33:00 | \n",
+ " 2044.296997 | \n",
+ " 2060.478027 | \n",
+ " 1995.057983 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2008.868042 | \n",
+ " 2058.000000 | \n",
+ " 14.345 | \n",
+ " 13.141 | \n",
+ " ... | \n",
+ " True | \n",
+ " True | \n",
+ " 2.384 | \n",
+ " -0.0 | \n",
+ " baseline | \n",
+ " 251.341539 | \n",
+ " 13.426766 | \n",
+ " 2039.458252 | \n",
+ " 0.11 | \n",
+ " 251.104001 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 2020-02-17 16:34:00 | \n",
+ " 2058.281006 | \n",
+ " 2042.703003 | \n",
+ " 2031.723999 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1819.896973 | \n",
+ " 2059.760010 | \n",
+ " 14.338 | \n",
+ " 12.723 | \n",
+ " ... | \n",
+ " True | \n",
+ " True | \n",
+ " 17.271 | \n",
+ " -0.0 | \n",
+ " baseline | \n",
+ " 253.343030 | \n",
+ " 13.225105 | \n",
+ " 2048.116943 | \n",
+ " 0.11 | \n",
+ " 255.679234 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
5 rows × 37 columns
\n",
+ "
"
+ ]
+ },
+ "execution_count": 29,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 29
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.031870Z",
+ "start_time": "2024-08-12T18:41:32.024932Z"
+ }
+ },
+ "source": [
+ "df_scada.columns"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Index(['time', 'pow_000', 'pow_001', 'pow_002', 'pow_003', 'pow_004',\n",
+ " 'pow_005', 'pow_006', 'ws_000', 'ws_001', 'ws_002', 'ws_003', 'ws_004',\n",
+ " 'ws_005', 'ws_006', 'wd_000', 'wd_001', 'wd_002', 'wd_003', 'wd_004',\n",
+ " 'wd_005', 'wd_006', 'is_operation_normal_000',\n",
+ " 'is_operation_normal_001', 'is_operation_normal_002',\n",
+ " 'is_operation_normal_003', 'is_operation_normal_004',\n",
+ " 'is_operation_normal_005', 'is_operation_normal_006', 'wind_vane_005',\n",
+ " 'target_yaw_offset_005', 'control_mode', 'wd_smarteole', 'ws_smarteole',\n",
+ " 'pow_ref_smarteole', 'ti', 'wd'],\n",
+ " dtype='object')"
+ ]
+ },
+ "execution_count": 30,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 30
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Step 1: Run wind-up analysis\n",
+ "\n",
+ "Use wind-up analysis to determine the uplift and uncertainty."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.046216Z",
+ "start_time": "2024-08-12T18:41:32.033859Z"
+ }
+ },
+ "source": [
+ "# configure logger so wind-up log messages are displayed in this notebook\n",
+ "import logging\n",
+ "import re\n",
+ "\n",
+ "from IPython.display import display, Markdown\n",
+ "\n",
+ "logging.basicConfig(format=\"%(message)s\", level=logging.INFO)\n",
+ "\n",
+ "\n",
+ "class NotebookHandler(logging.Handler):\n",
+ " def emit(self, record):\n",
+ " message = self.format(record)\n",
+ " # Replace newline characters with
tags\n",
+ " message = re.sub(r\"\\n\", \"
\", message)\n",
+ " display(Markdown(message))\n",
+ "\n",
+ "\n",
+ "logger = logging.getLogger()\n",
+ "logger.handlers = [] # Clear existing handlers to avoid duplication\n",
+ "logger.addHandler(NotebookHandler())"
+ ],
+ "outputs": [],
+ "execution_count": 31
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.067639Z",
+ "start_time": "2024-08-12T18:41:32.046216Z"
+ }
+ },
+ "source": [
+ "# create the wind-up meadata_df\n",
+ "import zipfile\n",
+ "\n",
+ "\n",
+ "def unpack_smarteole_metadata(timebase_s: int) -> pd.DataFrame:\n",
+ " md_fpath = \"SMARTEOLE-WFC-open-dataset/SMARTEOLE_WakeSteering_Coordinates_staticData.csv\"\n",
+ " with zipfile.ZipFile(\"data/SMARTEOLE-WFC-open-dataset.zip\") as zf:\n",
+ " return (\n",
+ " pd.read_csv(zf.open(md_fpath), index_col=0)\n",
+ " .reset_index()\n",
+ " .rename(columns={\"Turbine\": \"Name\"})\n",
+ " .query(\"Name.str.startswith('SMV')\") # is a turbine\n",
+ " .loc[:, [\"Name\", \"Latitude\", \"Longitude\"]]\n",
+ " .assign(TimeZone=\"UTC\", TimeSpanMinutes=timebase_s / 60, TimeFormat=\"Start\")\n",
+ " )\n",
+ "\n",
+ "\n",
+ "metadata_df = unpack_smarteole_metadata(timebase_s)\n",
+ "metadata_df.head()"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " Name Latitude Longitude TimeZone TimeSpanMinutes TimeFormat\n",
+ "0 SMV1 49.84975 2.80194 UTC 1.0 Start\n",
+ "1 SMV2 49.84661 2.80150 UTC 1.0 Start\n",
+ "2 SMV3 49.84347 2.80162 UTC 1.0 Start\n",
+ "3 SMV4 49.84033 2.80122 UTC 1.0 Start\n",
+ "4 SMV5 49.83719 2.80080 UTC 1.0 Start"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Name | \n",
+ " Latitude | \n",
+ " Longitude | \n",
+ " TimeZone | \n",
+ " TimeSpanMinutes | \n",
+ " TimeFormat | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " SMV1 | \n",
+ " 49.84975 | \n",
+ " 2.80194 | \n",
+ " UTC | \n",
+ " 1.0 | \n",
+ " Start | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " SMV2 | \n",
+ " 49.84661 | \n",
+ " 2.80150 | \n",
+ " UTC | \n",
+ " 1.0 | \n",
+ " Start | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " SMV3 | \n",
+ " 49.84347 | \n",
+ " 2.80162 | \n",
+ " UTC | \n",
+ " 1.0 | \n",
+ " Start | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " SMV4 | \n",
+ " 49.84033 | \n",
+ " 2.80122 | \n",
+ " UTC | \n",
+ " 1.0 | \n",
+ " Start | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " SMV5 | \n",
+ " 49.83719 | \n",
+ " 2.80080 | \n",
+ " UTC | \n",
+ " 1.0 | \n",
+ " Start | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 32,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 32
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.246920Z",
+ "start_time": "2024-08-12T18:41:32.067639Z"
+ }
+ },
+ "source": [
+ "from flasc.utilities.wind_up_tools import df_scada_to_wind_up\n",
+ "\n",
+ "# format flasc turbine data as wind-up scada_df\n",
+ "scada_df = df_scada_to_wind_up(df_scada, turbine_names=[f\"SMV{x}\" for x in range(1, 8)])\n",
+ "scada_df[scada_df[\"target_yaw_offset\"] > 15].head()"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ActivePowerMean WindSpeedMean YawAngleMean \\\n",
+ "TimeStamp_StartFormat \n",
+ "2020-02-18 07:49:00 1259.180054 8.423 215.961761 \n",
+ "2020-02-18 07:50:00 1353.114014 9.020 218.049759 \n",
+ "2020-02-18 07:51:00 1208.845947 8.994 207.330750 \n",
+ "2020-02-18 07:52:00 1198.353027 8.550 216.020752 \n",
+ "2020-02-18 07:53:00 1144.171021 8.049 210.955750 \n",
+ "\n",
+ " is_operation_normal TurbineName wind_vane \\\n",
+ "TimeStamp_StartFormat \n",
+ "2020-02-18 07:49:00 True SMV6 9.646 \n",
+ "2020-02-18 07:50:00 True SMV6 12.696 \n",
+ "2020-02-18 07:51:00 True SMV6 0.864 \n",
+ "2020-02-18 07:52:00 True SMV6 9.665 \n",
+ "2020-02-18 07:53:00 True SMV6 4.673 \n",
+ "\n",
+ " target_yaw_offset PitchAngleMean GenRpmMean \\\n",
+ "TimeStamp_StartFormat \n",
+ "2020-02-18 07:49:00 15.736000 0 1000 \n",
+ "2020-02-18 07:50:00 17.041000 0 1000 \n",
+ "2020-02-18 07:51:00 18.132000 0 1000 \n",
+ "2020-02-18 07:52:00 19.334999 0 1000 \n",
+ "2020-02-18 07:53:00 19.913000 0 1000 \n",
+ "\n",
+ " ShutdownDuration \n",
+ "TimeStamp_StartFormat \n",
+ "2020-02-18 07:49:00 0 \n",
+ "2020-02-18 07:50:00 0 \n",
+ "2020-02-18 07:51:00 0 \n",
+ "2020-02-18 07:52:00 0 \n",
+ "2020-02-18 07:53:00 0 "
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " ActivePowerMean | \n",
+ " WindSpeedMean | \n",
+ " YawAngleMean | \n",
+ " is_operation_normal | \n",
+ " TurbineName | \n",
+ " wind_vane | \n",
+ " target_yaw_offset | \n",
+ " PitchAngleMean | \n",
+ " GenRpmMean | \n",
+ " ShutdownDuration | \n",
+ "
\n",
+ " \n",
+ " TimeStamp_StartFormat | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2020-02-18 07:49:00 | \n",
+ " 1259.180054 | \n",
+ " 8.423 | \n",
+ " 215.961761 | \n",
+ " True | \n",
+ " SMV6 | \n",
+ " 9.646 | \n",
+ " 15.736000 | \n",
+ " 0 | \n",
+ " 1000 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2020-02-18 07:50:00 | \n",
+ " 1353.114014 | \n",
+ " 9.020 | \n",
+ " 218.049759 | \n",
+ " True | \n",
+ " SMV6 | \n",
+ " 12.696 | \n",
+ " 17.041000 | \n",
+ " 0 | \n",
+ " 1000 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2020-02-18 07:51:00 | \n",
+ " 1208.845947 | \n",
+ " 8.994 | \n",
+ " 207.330750 | \n",
+ " True | \n",
+ " SMV6 | \n",
+ " 0.864 | \n",
+ " 18.132000 | \n",
+ " 0 | \n",
+ " 1000 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2020-02-18 07:52:00 | \n",
+ " 1198.353027 | \n",
+ " 8.550 | \n",
+ " 216.020752 | \n",
+ " True | \n",
+ " SMV6 | \n",
+ " 9.665 | \n",
+ " 19.334999 | \n",
+ " 0 | \n",
+ " 1000 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2020-02-18 07:53:00 | \n",
+ " 1144.171021 | \n",
+ " 8.049 | \n",
+ " 210.955750 | \n",
+ " True | \n",
+ " SMV6 | \n",
+ " 4.673 | \n",
+ " 19.913000 | \n",
+ " 0 | \n",
+ " 1000 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 33,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 33
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.282737Z",
+ "start_time": "2024-08-12T18:41:32.246920Z"
+ }
+ },
+ "source": [
+ "from wind_up.constants import TIMESTAMP_COL\n",
+ "\n",
+ "toggle_df = df_scada[[\"time\", \"control_mode\"]].dropna().copy()\n",
+ "toggle_df[\"toggle_on\"] = toggle_df.control_mode == \"controlled\"\n",
+ "toggle_df[\"toggle_off\"] = toggle_df.control_mode == \"baseline\"\n",
+ "toggle_df = toggle_df.set_index(\"time\")\n",
+ "toggle_df.index.name = TIMESTAMP_COL\n",
+ "toggle_df.index = toggle_df.index.tz_localize(\"UTC\")\n",
+ "toggle_df.head()"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " control_mode toggle_on toggle_off\n",
+ "TimeStamp_StartFormat \n",
+ "2020-02-17 16:30:00+00:00 baseline False True\n",
+ "2020-02-17 16:31:00+00:00 baseline False True\n",
+ "2020-02-17 16:32:00+00:00 baseline False True\n",
+ "2020-02-17 16:33:00+00:00 baseline False True\n",
+ "2020-02-17 16:34:00+00:00 baseline False True"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " control_mode | \n",
+ " toggle_on | \n",
+ " toggle_off | \n",
+ "
\n",
+ " \n",
+ " TimeStamp_StartFormat | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2020-02-17 16:30:00+00:00 | \n",
+ " baseline | \n",
+ " False | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 2020-02-17 16:31:00+00:00 | \n",
+ " baseline | \n",
+ " False | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 2020-02-17 16:32:00+00:00 | \n",
+ " baseline | \n",
+ " False | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 2020-02-17 16:33:00+00:00 | \n",
+ " baseline | \n",
+ " False | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " 2020-02-17 16:34:00+00:00 | \n",
+ " baseline | \n",
+ " False | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 34
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.296802Z",
+ "start_time": "2024-08-12T18:41:32.284001Z"
+ }
+ },
+ "source": [
+ "from wind_up.reanalysis_data import ReanalysisDataset\n",
+ "\n",
+ "rng = np.random.default_rng(0)\n",
+ "rows = 100\n",
+ "reanalysis_dataset = ReanalysisDataset(\n",
+ " id=\"dummy_reanalysis_data\",\n",
+ " data=pd.DataFrame(\n",
+ " data={\n",
+ " \"100_m_hws_mean_mps\": rng.uniform(5, 10, rows),\n",
+ " \"100_m_hwd_mean_deg-n_true\": rng.uniform(0, 360, rows),\n",
+ " },\n",
+ " index=pd.DatetimeIndex(\n",
+ " pd.date_range(start=\"2020-03-01 00:00:00\", periods=rows, freq=\"H\", tz=\"UTC\")\n",
+ " ),\n",
+ " ),\n",
+ ")\n",
+ "reanalysis_dataset.data.head()"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 100_m_hws_mean_mps 100_m_hwd_mean_deg-n_true\n",
+ "2020-03-01 00:00:00+00:00 8.184808 172.795653\n",
+ "2020-03-01 01:00:00+00:00 6.348934 83.654251\n",
+ "2020-03-01 02:00:00+00:00 5.204868 288.677008\n",
+ "2020-03-01 03:00:00+00:00 5.082638 332.470858\n",
+ "2020-03-01 04:00:00+00:00 9.066351 95.806898"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " 100_m_hws_mean_mps | \n",
+ " 100_m_hwd_mean_deg-n_true | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2020-03-01 00:00:00+00:00 | \n",
+ " 8.184808 | \n",
+ " 172.795653 | \n",
+ "
\n",
+ " \n",
+ " 2020-03-01 01:00:00+00:00 | \n",
+ " 6.348934 | \n",
+ " 83.654251 | \n",
+ "
\n",
+ " \n",
+ " 2020-03-01 02:00:00+00:00 | \n",
+ " 5.204868 | \n",
+ " 288.677008 | \n",
+ "
\n",
+ " \n",
+ " 2020-03-01 03:00:00+00:00 | \n",
+ " 5.082638 | \n",
+ " 332.470858 | \n",
+ "
\n",
+ " \n",
+ " 2020-03-01 04:00:00+00:00 | \n",
+ " 9.066351 | \n",
+ " 95.806898 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ]
+ },
+ "execution_count": 35,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 35
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:41:32.320111Z",
+ "start_time": "2024-08-12T18:41:32.296802Z"
+ }
+ },
+ "source": [
+ "from wind_up.models import PlotConfig, WindUpConfig\n",
+ "\n",
+ "\n",
+ "def define_smarteole_example_config(timebase_s: int, out_dir: Path) -> WindUpConfig:\n",
+ " wtg_map = {\n",
+ " f\"SMV{i}\": {\n",
+ " \"name\": f\"SMV{i}\",\n",
+ " \"turbine_type\": {\n",
+ " \"turbine_type\": \"Senvion-MM82-2050\",\n",
+ " \"rotor_diameter_m\": 82.0,\n",
+ " \"rated_power_kw\": 2050.0,\n",
+ " \"cutout_ws_mps\": 25,\n",
+ " \"normal_operation_pitch_range\": (-10.0, 35.0),\n",
+ " \"normal_operation_genrpm_range\": (250.0, 2000.0),\n",
+ " \"rpm_v_pw_margin_factor\": 0.05,\n",
+ " \"pitch_to_stall\": False,\n",
+ " },\n",
+ " }\n",
+ " for i in range(1, 7 + 1)\n",
+ " }\n",
+ " northing_corrections_utc = [ # data is already northed by FLASC\n",
+ " # (\"SMV1\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 5.750994540354649),\n",
+ " # (\"SMV2\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 5.690999999999994),\n",
+ " # (\"SMV3\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 5.558000000000042),\n",
+ " # (\"SMV4\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 5.936999999999996),\n",
+ " # (\"SMV5\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 6.797253350869262),\n",
+ " # (\"SMV6\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 5.030130916842758),\n",
+ " # (\"SMV7\", pd.Timestamp(\"2020-02-17 16:30:00+0000\"), 4.605999999999972),\n",
+ " ]\n",
+ "\n",
+ " wd_filter_margin = 3 + 7 * timebase_s / 600\n",
+ " return WindUpConfig(\n",
+ " assessment_name=\"smarteole_example\",\n",
+ " timebase_s=timebase_s,\n",
+ " require_ref_wake_free=True,\n",
+ " detrend_min_hours=12,\n",
+ " ref_wd_filter=[207 - wd_filter_margin, 236 + wd_filter_margin], # steer is from 207-236\n",
+ " filter_all_test_wtgs_together=True,\n",
+ " use_lt_distribution=False,\n",
+ " out_dir=out_dir,\n",
+ " test_wtgs=[wtg_map[\"SMV6\"], wtg_map[\"SMV5\"]],\n",
+ " ref_wtgs=[wtg_map[\"SMV7\"]],\n",
+ " ref_super_wtgs=[],\n",
+ " non_wtg_ref_names=[],\n",
+ " analysis_first_dt_utc_start=pd.Timestamp(\"2020-02-17 16:30:00+0000\"),\n",
+ " upgrade_first_dt_utc_start=pd.Timestamp(\"2020-02-17 16:30:00+0000\"),\n",
+ " analysis_last_dt_utc_start=pd.Timestamp(\"2020-05-25 00:00:00+0000\")\n",
+ " - pd.Timedelta(seconds=timebase_s),\n",
+ " lt_first_dt_utc_start=pd.Timestamp(\"2020-02-17 16:30:00+0000\"),\n",
+ " lt_last_dt_utc_start=pd.Timestamp(\"2020-05-25 00:00:00+0000\")\n",
+ " - pd.Timedelta(seconds=timebase_s),\n",
+ " detrend_first_dt_utc_start=pd.Timestamp(\"2020-02-17 16:30:00+0000\"),\n",
+ " detrend_last_dt_utc_start=pd.Timestamp(\"2020-05-25 00:00:00+0000\")\n",
+ " - pd.Timedelta(seconds=timebase_s),\n",
+ " years_for_lt_distribution=0,\n",
+ " years_for_detrend=0,\n",
+ " ws_bin_width=1.0,\n",
+ " asset={\n",
+ " \"name\": \"Sole du Moulin Vieux\",\n",
+ " \"wtgs\": list(wtg_map.values()),\n",
+ " \"masts_and_lidars\": [],\n",
+ " },\n",
+ " northing_corrections_utc=northing_corrections_utc,\n",
+ " toggle={\n",
+ " \"name\": \"wake steering\",\n",
+ " \"toggle_file_per_turbine\": False,\n",
+ " \"toggle_filename\": \"SMV_offset_active_toggle_df.parquet\",\n",
+ " \"detrend_data_selection\": \"use_toggle_off_data\",\n",
+ " \"pairing_filter_method\": \"any_within_timedelta\",\n",
+ " \"pairing_filter_timedelta_seconds\": 3600,\n",
+ " \"toggle_change_settling_filter_seconds\": 120,\n",
+ " },\n",
+ " )\n",
+ "\n",
+ "\n",
+ "out_dir = Path.cwd() / \"wind_up_output\"\n",
+ "out_dir.mkdir(exist_ok=True)\n",
+ "cfg = define_smarteole_example_config(timebase_s=timebase_s, out_dir=out_dir)\n",
+ "plot_cfg = PlotConfig(\n",
+ " show_plots=True, save_plots=False, skip_per_turbine_plots=True, plots_dir=cfg.out_dir / \"plots\"\n",
+ ")"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "loaded WindUpConfig assessment_name: smarteole_example"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "toggle analysis period (UTC): 2020-02-17 16:30 to 2020-05-25 00:00"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "long term period (UTC): 2020-02-17 16:30 to 2020-05-25 00:00"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "detrend period (UTC): 2020-02-17 16:30 to 2020-05-25 00:00"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "execution_count": 36
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2024-08-12T18:44:07.592530Z",
+ "start_time": "2024-08-12T18:41:32.320111Z"
+ }
+ },
+ "source": [
+ "from wind_up.interface import AssessmentInputs\n",
+ "\n",
+ "assessment_inputs = AssessmentInputs.from_cfg(\n",
+ " cfg=cfg,\n",
+ " plot_cfg=plot_cfg,\n",
+ " toggle_df=toggle_df,\n",
+ " scada_df=scada_df,\n",
+ " metadata_df=metadata_df,\n",
+ " reanalysis_datasets=[reanalysis_dataset],\n",
+ " cache_dir=None,\n",
+ ")"
+ ],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "running wind_up analysis for smarteole_example"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "running load_smart_scada_and_md_from_file for 2020-02-17 16:30:00+00:00 to 2020-05-24 23:59:00+00:00"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "loaded 7 turbines, 0.3 years per turbine"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/markdown": "finished load_smart_scada_and_md for 2020-02-17 16:30:00+00:00 to 2020-05-24 23:59:00+00:00"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "