From d42b2682f02af98d27869e9208c4d3e63fcb5f12 Mon Sep 17 00:00:00 2001 From: Benjamin Thomas Schwertfeger Date: Fri, 21 Oct 2022 09:16:18 +0200 Subject: [PATCH 1/2] removed some log statements --- README.md | 5 ++++- example_adjust.run.sh | 8 ++++---- src/CMethods.cxx | 16 ++++++---------- src/main.cxx | 3 +-- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0430005..bd82594 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ # Bias-Adjustment-Cpp -[![Generic badge](https://img.shields.io/badge/license-MIT-green.svg)](https://shields.io/) +
+ [![GitHub](https://badgen.net/badge/icon/github?icon=github&label)](https://github.com/btschwertfeger/Bias-Adjustment-Cpp) +[![Generic badge](https://img.shields.io/badge/license-MIT-green.svg)](https://shields.io/) +
Collection of different scale- and distribution-based bias adjustment techniques for climatic research. Many of these methods have also been implemented in Python. This can be found here: https://github.com/btschwertfeger/Bias-Adjustment-Python. ____ diff --git a/example_adjust.run.sh b/example_adjust.run.sh index c96b1a8..69f9950 100755 --- a/example_adjust.run.sh +++ b/example_adjust.run.sh @@ -45,18 +45,18 @@ declare -a quant_methods=("quantile_mapping" "quantile_delta_mapping") { setopt KSH_ARRAYS || : ; } 2> /dev/null tmp_path=${work_dir}/tmp/$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 12) -tmp_obs="${tmp_path}/obs" +tmp_ref="${tmp_path}/ref" tmp_contr="${tmp_path}/contr" tmp_scen="${tmp_path}/scen" tmp_results="${tmp_path}/results" -mkdir -p $tmp_obs +mkdir -p $tmp_ref mkdir -p $tmp_contr mkdir -p $tmp_scen mkdir -p $tmp_results declare -a datasets=("${observations}" "${control}" "${scenario}") -declare -a ds_paths=("${tmp_obs}" "${tmp_contr}" "${tmp_scen}") +declare -a ds_paths=("${tmp_ref}" "${tmp_contr}" "${tmp_scen}") # * ------------------------------------------------------------------- # * Computation @@ -82,7 +82,7 @@ for method in "${month_methods[@]}"; do # ? Apply scaling-based bias adjustment per month for (( month=1; month<13; month++ )); do $exec_file \ - --ref "${tmp_obs}/${month}.nc" \ + --ref "${tmp_ref}/${month}.nc" \ --contr "${tmp_contr}/${month}.nc" \ --scen "${tmp_scen}/${month}.nc" \ -v $variable \ diff --git a/src/CMethods.cxx b/src/CMethods.cxx index d7a0571..4e2df52 100644 --- a/src/CMethods.cxx +++ b/src/CMethods.cxx @@ -268,12 +268,11 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, if (kind == "add" || kind == "+") { std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "regular"); - // ? create CDF - std::vector + std::vector // ? create CDF vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time); - std::vector + std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), contr_cdf(vi_contr_cdf.begin(), vi_contr_cdf.end()); @@ -289,12 +288,11 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, } else if (kind == "mult" || kind == "*") { std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "bounded"); - // ? create CDF - std::vector + std::vector // ? create CDF vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time); - std::vector + std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), contr_cdf(vi_contr_cdf.begin(), vi_contr_cdf.end()); @@ -310,7 +308,6 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, float y = (float)MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], true); output[ts] = (y >= 0) ? y : 0; } - } else std::runtime_error("Adjustment kind " + kind + " unknown for Quantile Mapping!"); } @@ -345,13 +342,12 @@ void CMethods::Quantile_Delta_Mapping(float* output, float* reference, float* co if (kind == "add" || kind == "+") { std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "regular"); - // ? create CDF - std::vector + std::vector // ? create CDF vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time), vi_scen_cdf = MyMath::get_cdf(scenario, v_xbins, n_time); - std::vector + std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), contr_cdf(vi_contr_cdf.begin(), vi_contr_cdf.end()), scen_cdf(vi_scen_cdf.begin(), vi_scen_cdf.end()); diff --git a/src/main.cxx b/src/main.cxx index 66caa12..70fd47e 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -255,7 +255,6 @@ static void do_simple_adjustment(float*** data_out) { } static void do_quantile_adjustment(float*** data_out) { - Log.info("INFIDIFBLSK"); CM_Func_ptr_quantile apply_adjustment = CMethods::get_cmethod_quantile(adjustment_method_name); for (unsigned lat = 0; lat < ds_reference.n_lat; lat++) { @@ -273,7 +272,7 @@ static void do_quantile_adjustment(float*** data_out) { ds_reference.fill_lon_timeseries_for_lat(reference_lon_data, lat); ds_control.fill_lon_timeseries_for_lat(control_lon_data, lat); ds_scenario.fill_lon_timeseries_for_lat(scenario_lon_data, lat); - Log.info("INFIDIFBLSK"); + for (unsigned lon = 0; lon < ds_reference.n_lon; lon++) { apply_adjustment( data_out[lat][lon], From 8ed10028e80cb825f33082e10d36bd374c68a715 Mon Sep 17 00:00:00 2001 From: Benjamin Thomas Schwertfeger Date: Fri, 21 Oct 2022 15:10:47 +0200 Subject: [PATCH 2/2] switched from regular arrays to vectors --- .vscode/c_cpp_properties.json | 2 +- cmake/modules/FindNetCDFCxx.cmake | 1 + examples.ipynb | 83 +++++++-------- include/CMethods.hxx | 20 ++-- include/MyMath.hxx | 25 ++--- include/NcFileHandler.hxx | 6 +- src/CMethods.cxx | 162 ++++++++++++++-------------- src/MyMath.cxx | 64 ++++++----- src/NcFileHandler.cxx | 113 +++++++++++++++++++- src/main.cxx | 171 ++++++++++++++---------------- 10 files changed, 367 insertions(+), 280 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 8ebb37c..3f8c153 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,7 +9,7 @@ "defines": [], "compilerPath": "/usr/bin/g++", "cStandard": "c11", - "cppStandard": "c++17", + "cppStandard": "c++11", "intelliSenseMode": "macos-gcc-x64" } ], diff --git a/cmake/modules/FindNetCDFCxx.cmake b/cmake/modules/FindNetCDFCxx.cmake index 3da6166..1522c1a 100644 --- a/cmake/modules/FindNetCDFCxx.cmake +++ b/cmake/modules/FindNetCDFCxx.cmake @@ -11,6 +11,7 @@ # netCDFCxx_INCLUDE_DIRS - path of netCDFCxx includes # netCDFCxx_LIBRARIES - netCDFCxx libraries +message (STATUS "searching netCDFCxx...") find_package(netCDF REQUIRED) find_program(NCXX4_CONFIG "ncxx4-config") diff --git a/examples.ipynb b/examples.ipynb index 4c79635..4d705c4 100644 --- a/examples.ipynb +++ b/examples.ipynb @@ -103,16 +103,16 @@ { "cell_type": "code", "execution_count": 7, - "id": "8527dadf-3928-4cc1-8ac2-b7ca30afb7ad", + "id": "9dc582c9-acc7-40c9-9cbc-90467b6bd5c9", "metadata": {}, "outputs": [], "source": [ - "float* obs_one_loc = new float[ds_obs.n_time]; \n", - "float* simh_one_loc = new float[ds_simh.n_time];\n", - "float* simp_one_loc = new float[ds_simp.n_time];\n", + "std::vector v_obs_one_loc(ds_obs.n_time); // observations (control period)\n", + "std::vector v_simh_one_loc(ds_obs.n_time); // simulated (control period)\n", + "std::vector v_simp_one_loc(ds_obs.n_time); // simulated (scenario period)\n", "\n", - "float* ls_result = new float[ds_simp.n_time];\n", - "float* qdm_result = new float[ds_simp.n_time];" + "std::vector v_ls_result(ds_obs.n_time); // Lienar Scaling result\n", + "std::vector v_qdm_result(ds_obs.n_time); // Quantile Delta Mapping result" ] }, { @@ -132,9 +132,9 @@ "outputs": [], "source": [ "// select time series\n", - "ds_obs.fill_timeseries_for_location(obs_one_loc, 0, 0);\n", - "ds_simh.fill_timeseries_for_location(simh_one_loc, 0, 0);\n", - "ds_simp.fill_timeseries_for_location(simp_one_loc, 0, 0);" + "ds_obs.fill_timeseries_for_location(v_obs_one_loc, 0, 0);\n", + "ds_simh.fill_timeseries_for_location(v_simh_one_loc, 0, 0);\n", + "ds_simp.fill_timeseries_for_location(v_simp_one_loc, 0, 0);" ] }, { @@ -153,7 +153,7 @@ "outputs": [], "source": [ "// select metotds \n", - "CM_Func_ptr_simple apply_adjustment_ls = CMethods::get_cmethod_simple(\"linear_scaling\");\n", + "CM_Func_ptr_scaling apply_adjustment_ls = CMethods::get_cmethod_scaling(\"linear_scaling\");\n", "CM_Func_ptr_quantile apply_adjustment_qdm = CMethods::get_cmethod_quantile(\"quantile_delta_mapping\");" ] }, @@ -174,11 +174,10 @@ "source": [ "// apply linear scaling\n", "apply_adjustment_ls(\n", - " ls_result, \n", - " obs_one_loc, \n", - " simh_one_loc, \n", - " simp_one_loc, \n", - " ds_simp.n_time,\n", + " v_ls_result, \n", + " v_obs_one_loc, \n", + " v_simh_one_loc, \n", + " v_simp_one_loc, \n", " \"+\"\n", ")" ] @@ -192,11 +191,10 @@ "source": [ "// apply quantile delta mapping\n", "apply_adjustment_qdm(\n", - " qdm_result, \n", - " obs_one_loc, \n", - " simh_one_loc, \n", - " simp_one_loc, \n", - " ds_simp.n_time,\n", + " v_qdm_result, \n", + " v_obs_one_loc, \n", + " v_simh_one_loc, \n", + " v_simp_one_loc, \n", " \"+\",\n", " 100\n", ")" @@ -235,7 +233,7 @@ } ], "source": [ - "for(unsigned ts = start; ts < end; ts++) std::cout << obs_one_loc[ts] << \" \";" + "for(unsigned ts = start; ts < end; ts++) std::cout << v_obs_one_loc[ts] << \" \";" ] }, { @@ -253,7 +251,7 @@ } ], "source": [ - "std::cout << MyMath::mean(obs_one_loc, ds_obs.n_time);" + "std::cout << MyMath::mean(v_obs_one_loc);" ] }, { @@ -279,7 +277,7 @@ } ], "source": [ - "for(unsigned ts = start; ts < end; ts++) std::cout << simh_one_loc[ts] << \" \";" + "for(unsigned ts = start; ts < end; ts++) std::cout << v_simh_one_loc[ts] << \" \";" ] }, { @@ -297,7 +295,7 @@ } ], "source": [ - "std::cout << MyMath::mean(simh_one_loc, ds_simh.n_time);" + "std::cout << MyMath::mean(v_simh_one_loc);" ] }, { @@ -323,7 +321,7 @@ } ], "source": [ - "for(unsigned ts = start; ts < end; ts++) std::cout << simp_one_loc[ts] << \" \";" + "for(unsigned ts = start; ts < end; ts++) std::cout << v_simp_one_loc[ts] << \" \";" ] }, { @@ -341,7 +339,7 @@ } ], "source": [ - "std::cout << MyMath::mean(simp_one_loc, ds_simp.n_time);" + "std::cout << MyMath::mean(v_simp_one_loc);" ] }, { @@ -368,7 +366,7 @@ } ], "source": [ - "for(unsigned ts = 0; ts < 10; ts++) std::cout << ls_result[ts] << \" \";" + "for(unsigned ts = 0; ts < 10; ts++) std::cout << v_ls_result[ts] << \" \";" ] }, { @@ -386,7 +384,7 @@ } ], "source": [ - "std::cout << MyMath::mean(ls_result, ds_simp.n_time);" + "std::cout << MyMath::mean(v_ls_result);" ] }, { @@ -412,7 +410,7 @@ } ], "source": [ - "for(unsigned ts = 0; ts < 10; ts++) std::cout << qdm_result[ts] << \" \";" + "for(unsigned ts = 0; ts < 10; ts++) std::cout << v_qdm_result[ts] << \" \";" ] }, { @@ -430,7 +428,7 @@ } ], "source": [ - "std::cout << MyMath::mean(qdm_result, ds_simp.n_time);" + "std::cout << MyMath::mean(v_qdm_result);" ] }, { @@ -454,18 +452,18 @@ "* All time attributes are missing here, so one have to set them using some other variable.\n", "*/\n", "NcFileHandler ncSaver;\n", - "ncSaver.to_netcdf(\"qdm_result.nc\", variable_name, qdm_result, ds_simp.n_time) // n_time should be length of qdm_result" + "ncSaver.to_netcdf(\"qdm_result.nc\", variable_name, v_qdm_result) // n_time should be length of qdm_result" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "id": "101f92fa-29a6-42fc-86f6-a4614c73e780", "metadata": {}, "outputs": [], "source": [ "// Saving can also be done by using the ds_simp instance to copy all time attributes and values to the full adjusted time series \n", - "ds_simp.to_netcdf(\"qdm_result.nc\", variable_name, qdm_result)" + "ds_simp.to_netcdf(\"qdm_result.nc\", variable_name, v_qdm_result)" ] }, { @@ -473,12 +471,13 @@ "id": "9e53e2b8-d7fc-4cc8-b52b-14ca4e5b7cda", "metadata": {}, "source": [ - "# 4. More usage examples" + "# 4. More usage examples based on Unidata Program Center's NetCDF data strucutres \n", + "References: http://doi.org/10.5065/D6H70CW6" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "id": "c6563442-e2be-4f64-bc0e-494e79eb4646", "metadata": {}, "outputs": [ @@ -496,7 +495,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "id": "73227a54-95c6-40d5-bc22-5537e0cfe60b", "metadata": {}, "outputs": [ @@ -514,7 +513,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "id": "7f449f18-9bbb-4e0e-8e8f-fb78e6fc9bb8", "metadata": {}, "outputs": [ @@ -532,7 +531,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "id": "d1bdcab5-edb7-41d7-b038-b14b260d7c2b", "metadata": {}, "outputs": [ @@ -568,17 +567,17 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "id": "67e00d69-81a9-4a1f-8001-4ec1ddd43ee0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{ \"calendar\" => @0x6000020ec9d8, \"units\" => @0x6000020ec7a8 }" + "{ \"calendar\" => @0x60000089f1a8, \"units\" => @0x60000089f138 }" ] }, - "execution_count": 29, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -589,7 +588,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "id": "093c24e1-3e99-4c56-a450-207ffa00e4b7", "metadata": {}, "outputs": [ diff --git a/include/CMethods.hxx b/include/CMethods.hxx index 859e9d0..11ceb44 100644 --- a/include/CMethods.hxx +++ b/include/CMethods.hxx @@ -14,28 +14,28 @@ #include -typedef void (*CM_Func_ptr_simple)(float* output, float* ref, float* contr, float* scen, unsigned n_time, std::string kind); -typedef void (*CM_Func_ptr_quantile)(float* output, float* ref, float* contr, float* scen, unsigned n_time, std::string kind, unsigned n_quantiles); +typedef void (*CM_Func_ptr_scaling)(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind); +typedef void (*CM_Func_ptr_quantile)(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind, unsigned n_quantiles); class CMethods { public: CMethods(); ~CMethods(); - static CM_Func_ptr_simple get_cmethod_simple(std::string method_name); + static CM_Func_ptr_scaling get_cmethod_scaling(std::string method_name); static CM_Func_ptr_quantile get_cmethod_quantile(std::string method_name); - static std::vector simple_method_names; + static std::vector scaling_method_names; static std::vector quantile_method_names; static std::vector all_method_names; - static void Linear_Scaling(float* output, float* reference, float* control, float* scenario, unsigned, std::string n_time); - static void Variance_Scaling(float* output, float* reference, float* control, float* scenario, unsigned, std::string n_time); - static void Delta_Method(float* output, float* reference, float* control, float* scenario, unsigned, std::string n_time); + static void Linear_Scaling(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind); + static void Variance_Scaling(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind); + static void Delta_Method(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind); - static std::vector get_xbins(float* a, float* b, unsigned n_quantiles, unsigned length, std::string kind); - static void Quantile_Mapping(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind, unsigned n_quantiles); - static void Quantile_Delta_Mapping(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind, unsigned n_quantiles); + static std::vector get_xbins(std::vector& a, std::vector& b, unsigned n_quantiles, std::string kind); + static void Quantile_Mapping(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind, unsigned n_quantiles); + static void Quantile_Delta_Mapping(std::vector& v_output, std::vector& v_reference, std::vector& v_control, std::vector& v_scenario, std::string kind, unsigned n_quantiles); }; #endif diff --git a/include/MyMath.hxx b/include/MyMath.hxx index 2015e9c..6c42d64 100644 --- a/include/MyMath.hxx +++ b/include/MyMath.hxx @@ -13,9 +13,10 @@ #define __MYMATH__ #include +#include -typedef float (*Func_one)(float* x, unsigned n); -typedef float (*Func_two)(float* x, float* y, unsigned n); +typedef float (*Func_one)(std::vector& x); +typedef float (*Func_two)(std::vector& x, std::vector& y); class MyMath { public: @@ -29,18 +30,18 @@ class MyMath { static Func_one get_method_for_1_ds(std::string name); static Func_two get_method_for_2_ds(std::string name); - static float correlation_coefficient(float* x, float* y, unsigned n); - static float rmse(float* x, float* y, unsigned n); - static float mbe(float* x, float* y, unsigned n); - static float ioa(float* x, float* y, unsigned n); - static float sd(float* x, unsigned n); - static float variance(float* x, unsigned n); - static float mean(float* a, unsigned n); + static float correlation_coefficient(std::vector& x, std::vector& y); + static float rmse(std::vector& x, std::vector& y); + static float mbe(std::vector& x, std::vector& y); + static float ioa(std::vector& x, std::vector& y); + static float sd(std::vector& x); + static float variance(std::vector& x); + static float mean(std::vector& a); static double lerp(double a, double b, double x); - static std::vector get_pdf(float* arr, std::vector bins, unsigned length); - static std::vector get_cdf(float* arr, std::vector bins, unsigned length); - static double interp(std::vector& xData, std::vector& yData, double x); + static std::vector get_pdf(std::vector& arr, std::vector& bins); + static std::vector get_cdf(std::vector& arr, std::vector& bins); + // static double interp(std::vector& xData, std::vector& yData, double x); static double interpolate(std::vector& xData, std::vector& yData, double x, bool extrapolate); }; diff --git a/include/NcFileHandler.hxx b/include/NcFileHandler.hxx index 7c46885..a2b82ed 100644 --- a/include/NcFileHandler.hxx +++ b/include/NcFileHandler.hxx @@ -20,13 +20,15 @@ class NcFileHandler { NcFileHandler(std::string filepath, std::string variable_name); ~NcFileHandler(); - void fill_lon_timeseries_for_lat(float** out_arr, unsigned lat); - void fill_timeseries_for_location(float* out_arr, unsigned lat, unsigned lon); + void fill_lon_timeseries_for_lat(std::vector>& v_out_arr, unsigned lat); + void fill_timeseries_for_location(std::vector& v_out_arr, unsigned lat, unsigned lon); void to_netcdf(std::string out_fpath, std::string variable_name, float* out_data); void to_netcdf(std::string out_fpath, std::string variable_name, float* out_data, unsigned n_time); + void to_netcdf(std::string out_fpath, std::string variable_name, std::vector& v_out_data); void to_netcdf(std::string out_fpath, std::string variable_name, float** out_data); void to_netcdf(std::string out_fpath, std::string variable_name, double** out_data); void to_netcdf(std::string out_fpath, std::string variable_name, float*** out_data); + void to_netcdf(std::string out_fpath, std::string variable_name, std::vector>>& v_out_data); void to_netcdf(std::string out_fpath, std::vector variable_names, std::vector out_data); static std::string time_name; diff --git a/src/CMethods.cxx b/src/CMethods.cxx index 4e2df52..eef037b 100644 --- a/src/CMethods.cxx +++ b/src/CMethods.cxx @@ -27,14 +27,13 @@ #include "MyMath.hxx" #include "math.h" - /** * * ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- * * Definitions * * ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */ -std::vector CMethods::simple_method_names = {"linear_scaling", "variance_scaling", "delta_method"}; +std::vector CMethods::scaling_method_names = {"linear_scaling", "variance_scaling", "delta_method"}; std::vector CMethods::quantile_method_names = {"quantile_mapping", "quantile_delta_mapping"}; /** @@ -52,7 +51,7 @@ CMethods::~CMethods() {} * * ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */ -CM_Func_ptr_simple CMethods::get_cmethod_simple(std::string method_name) { +CM_Func_ptr_scaling CMethods::get_cmethod_scaling(std::string method_name) { if (method_name == "linear_scaling") return Linear_Scaling; else if (method_name == "variance_scaling") @@ -85,7 +84,6 @@ CM_Func_ptr_quantile CMethods::get_cmethod_quantile(std::string method_name) { * @param reference observation data (control period) * @param control modeled data of the control period * @param scenario data to adjust - * @param n_time length of input and output arrays * @param kind type of adjustment; additive or multiplicative * * Add ('+'): @@ -96,17 +94,17 @@ CM_Func_ptr_quantile CMethods::get_cmethod_quantile(std::string method_name) { * (4.) $ T_{scen}^{*}(d) = \mu_{m}(T_{obs}(d))\cdot\left[\frac{T_{contr}(d)}{\mu_{m}(T_{scen}(d))}\right]$ * */ -void CMethods::Linear_Scaling(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind) { +void CMethods::Linear_Scaling(std::vector &v_output, std::vector &v_reference, std::vector &v_control, std::vector &v_scenario, std::string kind) { const float - ref_mean = MyMath::mean(reference, n_time), - contr_mean = MyMath::mean(control, n_time); + ref_mean = MyMath::mean(v_reference), + contr_mean = MyMath::mean(v_control); if (kind == "add" || kind == "+") { - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = scenario[ts] + (ref_mean - contr_mean); // Eq. 1f. + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = v_scenario[ts] + (ref_mean - contr_mean); // Eq. 1f. } else if (kind == "mult" || kind == "*") { - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = scenario[ts] * (ref_mean / contr_mean); // Eq. 3f. + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = v_scenario[ts] * (ref_mean / contr_mean); // Eq. 3f. } else std::runtime_error("Invalid adjustment kind " + kind + "!"); } @@ -121,7 +119,6 @@ void CMethods::Linear_Scaling(float* output, float* reference, float* control, f * @param reference observation data (control period) * @param control modeled data of the control period * @param scenario data to adjust - * @param n_time length of input and output arrays * @param kind type of adjustment; additive or multiplicative * * (1.) $T^{*1}_{contr}(d)=T_{contr}(d)+\mu_{m}(T_{obs}(d))-\mu_{m}(T_{contr}(d))$ @@ -136,36 +133,34 @@ void CMethods::Linear_Scaling(float* output, float* reference, float* control, f * (7.) $T^{*}_{contr}(d)=T^{*3}_{contr}(d)+\mu_{m}(T^{*1}_{contr}(d))$ * (8.) $T^{*}_{scen}(d)=T^{*3}_{scen}(d)+\mu_{m}(T^{*1}_{scen}(d))$ */ -void CMethods::Variance_Scaling(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind) { +void CMethods::Variance_Scaling(std::vector &v_output, std::vector &v_reference, std::vector &v_control, std::vector &v_scenario, std::string kind) { if (kind == "add" || kind == "+") { - float - LS_contr[n_time], - LS_scen[n_time]; + std::vector LS_contr(v_reference.size()); + std::vector LS_scen(v_reference.size()); - Linear_Scaling(LS_contr, reference, control, control, n_time, "+"); // Eq. 1 - Linear_Scaling(LS_scen, reference, control, scenario, n_time, "+"); // Eq. 2 + Linear_Scaling(LS_contr, v_reference, v_control, v_control, "+"); // Eq. 1 + Linear_Scaling(LS_scen, v_reference, v_control, v_scenario, "+"); // Eq. 2 float - LS_contr_mean = MyMath::mean(LS_contr, n_time), - LS_scen_mean = MyMath::mean(LS_scen, n_time); + LS_contr_mean = MyMath::mean(LS_contr), + LS_scen_mean = MyMath::mean(LS_scen); - float - VS1_contr[n_time], - VS1_scen[n_time]; + std::vector VS1_contr(v_reference.size()); + std::vector VS1_scen(v_reference.size()); - for (unsigned ts = 0; ts < n_time; ts++) { + for (unsigned ts = 0; ts < v_reference.size(); ts++) { VS1_contr[ts] = LS_contr[ts] - LS_contr_mean; // Eq. 3 VS1_scen[ts] = LS_scen[ts] - LS_scen_mean; // Eq. 4 } float - ref_sd = MyMath::sd(reference, n_time), - VS1_contr_sd = MyMath::sd(VS1_contr, n_time); + ref_sd = MyMath::sd(v_reference), + VS1_contr_sd = MyMath::sd(VS1_contr); - float VS2_scen[n_time]; - for (unsigned ts = 0; ts < n_time; ts++) { + std::vector VS2_scen(v_reference.size()); + for (unsigned ts = 0; ts < v_reference.size(); ts++) { VS2_scen[ts] = VS1_scen[ts] * (ref_sd / VS1_contr_sd); // Eq. 6 - output[ts] = VS2_scen[ts] + LS_scen_mean; // Eq. 7 + v_output[ts] = VS2_scen[ts] + LS_scen_mean; // Eq. 7 } } else if (kind == "mult" || kind == "*") @@ -182,7 +177,6 @@ void CMethods::Variance_Scaling(float* output, float* reference, float* control, * @param reference observation data (control period) * @param control modeled data of the control period * @param scenario data to adjust - * @param n_time length of input and output arrays * @param kind type of adjustment; additive or multiplicative * * Add (+): @@ -191,32 +185,34 @@ void CMethods::Variance_Scaling(float* output, float* reference, float* control, * (2.) $T^{*}_{contr}(d) = T_{contr}(d) \cdot \left[\frac{\mu_{m}(T_{scen}(d))}{\mu_{m}(T_{obs}(d))}\right]$ * */ -void CMethods::Delta_Method(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind) { +void CMethods::Delta_Method(std::vector &v_output, std::vector &v_reference, std::vector &v_control, std::vector &v_scenario, std::string kind) { const float - contr_mean = MyMath::mean(control, n_time), - scen_mean = MyMath::mean(scenario, n_time); + contr_mean = MyMath::mean(v_control), + scen_mean = MyMath::mean(v_scenario); if (kind == "add" || kind == "+") { - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = reference[ts] + (scen_mean - contr_mean); // Eq. 1 + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = v_reference[ts] + (scen_mean - contr_mean); // Eq. 1 } else if (kind == "mult" || kind == "*") { - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = reference[ts] * (scen_mean / contr_mean); // Eq. 2 + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = v_reference[ts] * (scen_mean / contr_mean); // Eq. 2 } else std::runtime_error("Invalid adjustment kind " + kind + "!"); } /** * + * @param a time series + * @param b time series * @param kind regular or bounded: defines if min is the real minimum or set to 0 */ -std::vector CMethods::get_xbins(float* a, float* b, unsigned n_quantiles, unsigned length, std::string kind) { +std::vector CMethods::get_xbins(std::vector &a, std::vector &b, unsigned n_quantiles, std::string kind) { if (kind == "regular") { const double - a_max = *std::max_element(a, a + length), - a_min = *std::min_element(a, a + length), - b_max = *std::max_element(b, b + length), - b_min = *std::min_element(b, b + length); + a_max = *std::max_element(std::begin(a), std::end(a)), + a_min = *std::min_element(std::begin(a), std::end(a)), + b_max = *std::max_element(std::begin(b), std::end(b)), + b_min = *std::min_element(std::begin(b), std::end(b)); const double global_max = std::max(a_max, b_max), @@ -231,8 +227,8 @@ std::vector CMethods::get_xbins(float* a, float* b, unsigned n_quantiles } else if (kind == "bounded") { const double - a_max = *std::max_element(a, a + length), - b_max = *std::max_element(b, b + length); + a_max = *std::max_element(std::begin(a), std::end(a)), + b_max = *std::max_element(std::begin(b), std::end(b)); const double global_max = std::max(a_max, b_max); const double wide = global_max / n_quantiles; @@ -255,7 +251,6 @@ std::vector CMethods::get_xbins(float* a, float* b, unsigned n_quantiles * @param reference observation data (control period) * @param control modeled data of the control period * @param scenario data to adjust - * @param n_time length of input and output arrays * @param kind type of adjustment; additive or multiplicative * @param n_quantiles number of quantiles to use * @@ -264,33 +259,39 @@ std::vector CMethods::get_xbins(float* a, float* b, unsigned n_quantiles * (mult): * same but experimental ... */ -void CMethods::Quantile_Mapping(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind, unsigned n_quantiles) { +void CMethods::Quantile_Mapping(std::vector &v_output, std::vector &v_reference, std::vector &v_control, std::vector &v_scenario, std::string kind, unsigned n_quantiles) { if (kind == "add" || kind == "+") { - std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "regular"); + for (auto i : v_reference) { + std::cout << i << " "; + } + + std::vector + v_xbins = get_xbins(v_reference, v_control, n_quantiles, "regular"); std::vector // ? create CDF - vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), - vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time); + vi_ref_cdf = MyMath::get_cdf(v_reference, v_xbins), + vi_contr_cdf = MyMath::get_cdf(v_control, v_xbins); std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), contr_cdf(vi_contr_cdf.begin(), vi_contr_cdf.end()); // ? Interpolate - std::vector cdf_values; - for (unsigned ts = 0; ts < n_time; ts++) - cdf_values.push_back(MyMath::interpolate(v_xbins, contr_cdf, (double)scenario[ts], false)); + std::vector + cdf_values; + for (unsigned ts = 0; ts < v_reference.size(); ts++) + cdf_values.push_back(MyMath::interpolate(v_xbins, contr_cdf, (double)v_scenario[ts], false)); // ? Invert in inversed CDF and return - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = (float)MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false); + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = (float)MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false); } else if (kind == "mult" || kind == "*") { - std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "bounded"); + std::vector v_xbins = get_xbins(v_reference, v_control, n_quantiles, "bounded"); std::vector // ? create CDF - vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), - vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time); + vi_ref_cdf = MyMath::get_cdf(v_reference, v_xbins), + vi_contr_cdf = MyMath::get_cdf(v_control, v_xbins); std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), @@ -298,15 +299,15 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, // ? Interpolate std::vector cdf_values; - for (unsigned ts = 0; ts < n_time; ts++) { - double y = MyMath::interpolate(v_xbins, contr_cdf, (double)scenario[ts], true); + for (unsigned ts = 0; ts < v_reference.size(); ts++) { + double y = MyMath::interpolate(v_xbins, contr_cdf, (double)v_scenario[ts], true); cdf_values.push_back((y >= 0) ? y : 0); } // ? Invert in inversed CDF and return - for (unsigned ts = 0; ts < n_time; ts++) { + for (unsigned ts = 0; ts < v_reference.size(); ts++) { float y = (float)MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], true); - output[ts] = (y >= 0) ? y : 0; + v_output[ts] = (y >= 0) ? y : 0; } } else std::runtime_error("Adjustment kind " + kind + " unknown for Quantile Mapping!"); @@ -321,7 +322,6 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, * @param reference observation data (control period) * @param control modeled data of the control period * @param scenario data to adjust - * @param n_time length of input and output arrays * @param kind type of adjustment; additive or multiplicative (absolute or relative change) * @param n_quantiles number of quantiles to use * @@ -338,14 +338,14 @@ void CMethods::Quantile_Mapping(float* output, float* reference, float* control, * & = \frac{ X_{sim,p}(i) }{ F^{-1}_{sim,h}\left\{F^{}_{sim,p}\left[X_{sim,p}(i)\right]\right\} } * (2.4) X^{*QDM}_{sim,p}(i) = X^{QDM(1)}_{sim,p}(i) \cdot \Delta(i) */ -void CMethods::Quantile_Delta_Mapping(float* output, float* reference, float* control, float* scenario, unsigned n_time, std::string kind, unsigned n_quantiles) { +void CMethods::Quantile_Delta_Mapping(std::vector &v_output, std::vector &v_reference, std::vector &v_control, std::vector &v_scenario, std::string kind, unsigned n_quantiles) { if (kind == "add" || kind == "+") { - std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "regular"); + std::vector v_xbins = get_xbins(v_reference, v_control, n_quantiles, "regular"); std::vector // ? create CDF - vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), - vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time), - vi_scen_cdf = MyMath::get_cdf(scenario, v_xbins, n_time); + vi_ref_cdf = MyMath::get_cdf(v_reference, v_xbins), + vi_contr_cdf = MyMath::get_cdf(v_control, v_xbins), + vi_scen_cdf = MyMath::get_cdf(v_scenario, v_xbins); std::vector // ? change to double ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), @@ -353,24 +353,24 @@ void CMethods::Quantile_Delta_Mapping(float* output, float* reference, float* co scen_cdf(vi_scen_cdf.begin(), vi_scen_cdf.end()); std::vector cdf_values; - for (unsigned ts = 0; ts < n_time; ts++) - cdf_values.push_back(MyMath::interpolate(v_xbins, scen_cdf, scenario[ts], false)); + for (unsigned ts = 0; ts < v_reference.size(); ts++) + cdf_values.push_back(MyMath::interpolate(v_xbins, scen_cdf, v_scenario[ts], false)); std::vector QDM1; // insert simulated values into inverse cdf of observed - for (unsigned ts = 0; ts < n_time; ts++) QDM1.push_back(MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false)); + for (unsigned ts = 0; ts < v_reference.size(); ts++) QDM1.push_back(MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false)); // ? Invert, insert in inversed CDF and return - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = (float)(QDM1[ts] + scenario[ts] - MyMath::interpolate(contr_cdf, v_xbins, cdf_values[ts], false)); // Eq. 2f. + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = (float)(QDM1[ts] + v_scenario[ts] - MyMath::interpolate(contr_cdf, v_xbins, cdf_values[ts], false)); // Eq. 2f. } else if (kind == "mult" || kind == "*") { - std::vector v_xbins = get_xbins(reference, control, n_quantiles, n_time, "bounded"); + std::vector v_xbins = get_xbins(v_reference, v_control, n_quantiles, "bounded"); // ? create CDF std::vector - vi_ref_cdf = MyMath::get_cdf(reference, v_xbins, n_time), - vi_contr_cdf = MyMath::get_cdf(control, v_xbins, n_time), - vi_scen_cdf = MyMath::get_cdf(scenario, v_xbins, n_time); + vi_ref_cdf = MyMath::get_cdf(v_reference, v_xbins), + vi_contr_cdf = MyMath::get_cdf(v_control, v_xbins), + vi_scen_cdf = MyMath::get_cdf(v_scenario, v_xbins); std::vector ref_cdf(vi_ref_cdf.begin(), vi_ref_cdf.end()), @@ -378,15 +378,15 @@ void CMethods::Quantile_Delta_Mapping(float* output, float* reference, float* co scen_cdf(vi_scen_cdf.begin(), vi_scen_cdf.end()); std::vector cdf_values; - for (unsigned ts = 0; ts < n_time; ts++) - cdf_values.push_back(MyMath::interpolate(v_xbins, scen_cdf, scenario[ts], false)); + for (unsigned ts = 0; ts < v_reference.size(); ts++) + cdf_values.push_back(MyMath::interpolate(v_xbins, scen_cdf, v_scenario[ts], false)); std::vector QDM1; // insert simulated values into inverse cdf of observed - for (unsigned ts = 0; ts < n_time; ts++) QDM1.push_back(MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false)); + for (unsigned ts = 0; ts < v_reference.size(); ts++) QDM1.push_back(MyMath::interpolate(ref_cdf, v_xbins, cdf_values[ts], false)); // ? Invert, insert in inversed CDF and return - for (unsigned ts = 0; ts < n_time; ts++) - output[ts] = (float)(QDM1[ts] * (scenario[ts] / MyMath::interpolate(contr_cdf, v_xbins, cdf_values[ts], false))); // Eq. 2.3f. + for (unsigned ts = 0; ts < v_reference.size(); ts++) + v_output[ts] = (float)(QDM1[ts] * (v_scenario[ts] / MyMath::interpolate(contr_cdf, v_xbins, cdf_values[ts], false))); // Eq. 2.3f. } else std::runtime_error("Adjustment kind " + kind + " unknown for Quantile Delta Mapping!"); } diff --git a/src/MyMath.cxx b/src/MyMath.cxx index bb2abb3..12c4724 100644 --- a/src/MyMath.cxx +++ b/src/MyMath.cxx @@ -20,7 +20,6 @@ #include #include #include - /** * * ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- * * Attributes @@ -80,16 +79,16 @@ Func_two MyMath::get_method_for_2_ds(std::string name) { * * @param x reference * @param y prediction - * @param n length */ -float MyMath::correlation_coefficient(float* x, float* y, unsigned n) { +float MyMath::correlation_coefficient(std::vector& x, std::vector& y) { float sum_X = 0, sum_Y = 0, sum_XY = 0, - squareSum_X = 0, squareSum_Y = 0; + squareSum_X = 0, + squareSum_Y = 0; - for (unsigned ts = 0; ts < n; ts++) { + for (unsigned ts = 0; ts < x.size(); ts++) { sum_X = sum_X + x[ts]; // sum of elements of array x. sum_Y = sum_Y + y[ts]; // sum of elements of array y. sum_XY = sum_XY + x[ts] * y[ts]; // sum of x[i] * y[i]. @@ -97,7 +96,7 @@ float MyMath::correlation_coefficient(float* x, float* y, unsigned n) { squareSum_X = squareSum_X + x[ts] * x[ts]; squareSum_Y = squareSum_Y + y[ts] * y[ts]; } - return (n * sum_XY - sum_X * sum_Y) / sqrt((n * squareSum_X - sum_X * sum_X) * (n * squareSum_Y - sum_Y * sum_Y)); + return (x.size() * sum_XY - sum_X * sum_Y) / sqrt((x.size() * squareSum_X - sum_X * sum_X) * (x.size() * squareSum_Y - sum_Y * sum_Y)); } /** Returns the Root Mean Square Error @@ -107,9 +106,9 @@ float MyMath::correlation_coefficient(float* x, float* y, unsigned n) { * @param y prediction * @param n length */ -float MyMath::rmse(float* x, float* y, unsigned n) { +float MyMath::rmse(std::vector& x, std::vector& y) { float result = 0; - for (unsigned ts = 0; ts < n; ts++) result += pow(y[ts] - x[ts], 2) / (float)n; + for (unsigned ts = 0; ts < x.size(); ts++) result += pow(y[ts] - x[ts], 2) / (float)x.size(); return sqrt(result); } @@ -118,12 +117,11 @@ float MyMath::rmse(float* x, float* y, unsigned n) { * * @param x reference * @param y prediction - * @param n length */ -float MyMath::mbe(float* x, float* y, unsigned n) { +float MyMath::mbe(std::vector& x, std::vector& y) { float result = 0; - for (unsigned ts = 0; ts < n; ts++) result += y[ts] - x[ts]; - return result * (float(1.0) / n); + for (unsigned ts = 0; ts < x.size(); ts++) result += y[ts] - x[ts]; + return result * (float(1.0) / x.size()); } /** Returns the index of agreement * $d = 1 - \frac{ @@ -135,12 +133,11 @@ float MyMath::mbe(float* x, float* y, unsigned n) { * * @param x reference * @param y prediction - * @param n length */ -float MyMath::ioa(float* x, float* y, unsigned n) { +float MyMath::ioa(std::vector& x, std::vector& y) { float upper = 0, lower = 0; - const double m = mean(x, n); - for (unsigned i = 0; i < n; i++) { + const double m = mean(x); + for (unsigned i = 0; i < x.size(); i++) { upper += pow(x[i] - y[i], 2); lower += pow(abs(y[i] - m) + abs(x[i] - m), 2); } @@ -151,43 +148,40 @@ float MyMath::ioa(float* x, float* y, unsigned n) { * $\sigma^{2}(x) = \frac{\sum_{i=1}^{n}(x_{i}-\mu(x)^{2}}{n-1}$ * * @param x reference - * @param n length */ -float MyMath::variance(float* x, unsigned n) { - float* v = new float[n]; - const float m = mean(x, n); - for (unsigned i = 0; i < n; i++) v[i] = pow(x[i] - m, 2); - return mean(v, n); +float MyMath::variance(std::vector& x) { + std::vector v(x.size()); + const float m = mean(x); + for (unsigned i = 0; i < x.size(); i++) v[i] = pow(x[i] - m, 2); + return mean(v); } /** Returns the standard deviation * $\sigma(x) = \sqrt{\frac{\sum_{i=1}^{n}(x_{i}-\mu(x)^{2}}{n-1}}$ * * @param x reference - * @param n length */ -float MyMath::sd(float* x, unsigned n) { - return sqrt(variance(x, n)); +float MyMath::sd(std::vector& x) { + return sqrt(variance(x)); } /** Mean * * @param a 1D array of floats to get the mean from - * @param n length of a */ -float MyMath::mean(float* a, unsigned n) { +float MyMath::mean(std::vector& a) { float sum = 0; - for (unsigned i = 0; i < n; i++) sum += a[i]; - return sum / n; + for (unsigned i = 0; i < a.size(); i++) sum += a[i]; + return sum / a.size(); } /** * Probabillity density function * */ -std::vector MyMath::get_pdf(float* arr, std::vector bins, unsigned length) { +std::vector MyMath::get_pdf(std::vector& arr, std::vector& bins) { std::vector v_pdf(bins.size() - 1); - for (unsigned ts = 0; ts < length; ts++) { + for (unsigned ts = 0; ts < arr.size(); ts++) { for (unsigned i = 0; i < v_pdf.size() - 1; i++) { if (i == 0 && arr[ts] <= bins[i]) { ++v_pdf[i]; @@ -207,9 +201,11 @@ std::vector MyMath::get_pdf(float* arr, std::vector bins, unsigned /** * Cumulative distribution function */ -std::vector MyMath::get_cdf(float* arr, std::vector bins, unsigned length) { - std::vector v_pdf = MyMath::get_pdf(arr, bins, length); - std::vector v_cdf(v_pdf.size() + 1); +std::vector MyMath::get_cdf(std::vector& arr, std::vector& bins) { + std::vector + v_pdf = MyMath::get_pdf(arr, bins); + std::vector + v_cdf(v_pdf.size() + 1); v_cdf[0] = 0; for (unsigned i = 0; i < v_pdf.size(); i++) v_cdf[i + 1] = v_cdf[i] + v_pdf[i]; diff --git a/src/NcFileHandler.cxx b/src/NcFileHandler.cxx index 2ef193e..a645a31 100644 --- a/src/NcFileHandler.cxx +++ b/src/NcFileHandler.cxx @@ -96,7 +96,7 @@ NcFileHandler::~NcFileHandler() {} * @param out_arr output array * @param lat latitude of desired locations */ -void NcFileHandler::fill_lon_timeseries_for_lat(float** out_arr, unsigned lat) { +void NcFileHandler::fill_lon_timeseries_for_lat(std::vector>& v_out_arr, unsigned lat) { std::vector startp, countp; startp.push_back(0); startp.push_back(lat); @@ -110,7 +110,7 @@ void NcFileHandler::fill_lon_timeseries_for_lat(float** out_arr, unsigned lat) { data.getVar(startp, countp, *tmp); for (unsigned ts = 0; ts < n_time; ts++) for (unsigned lon = 0; lon < n_lon; lon++) - out_arr[lon][ts] = tmp[ts][lon]; + v_out_arr[lon][ts] = tmp[ts][lon]; } /** Filles out_arr with all timesteps of one location @@ -119,7 +119,7 @@ void NcFileHandler::fill_lon_timeseries_for_lat(float** out_arr, unsigned lat) { * @param lat latitude of desired location * @param lon longitude of desired location */ -void NcFileHandler::fill_timeseries_for_location(float* out_arr, unsigned lat, unsigned lon) { +void NcFileHandler::fill_timeseries_for_location(std::vector& v_out_arr, unsigned lat, unsigned lon) { std::vector startp, // start point countp; // end point @@ -135,7 +135,7 @@ void NcFileHandler::fill_timeseries_for_location(float* out_arr, unsigned lat, u for (unsigned day = 0; day < n_time; day++) { startp[0] = day; data.getVar(startp, countp, *tmp); - out_arr[day] = tmp[lat][lon]; + v_out_arr[day] = tmp[lat][lon]; } } @@ -211,6 +211,31 @@ void NcFileHandler::to_netcdf(std::string out_fpath, std::string variable_name, output_var.putVar(startp, countp, out_data); } +/** Saves a dataset with one variable for one time dimension (1d vector) + * -> else no time attributes and values will be saved (empty) + * + * @param out_fpath output file path + * @param variable_name name of the output variable + * @param out_data 1d array of data + * @param n_time custom length of the array + */ +void NcFileHandler::to_netcdf(std::string out_fpath, std::string variable_name, std::vector& v_out_data) { + netCDF::NcFile output_file(out_fpath, netCDF::NcFile::replace); + + // ? Save vector as new file without any time attributes and values + netCDF::NcDim out_time_dim = output_file.addDim("time", n_time); + netCDF::NcVar out_time_var = output_file.addVar("time", netCDF::ncDouble, out_time_dim); + + std::vector dim_vector; + dim_vector.push_back(out_time_dim); + netCDF::NcVar output_var = output_file.addVar(variable_name, netCDF::ncFloat, dim_vector); + + std::vector startp, countp; + startp.push_back(0); + countp.push_back(n_time); + output_var.putVar(startp, countp, &v_out_data[0]); +} + /** Saves a dataset with one variable for one lat and one lon and only one timestep to file * * @param out_fpath output file path @@ -344,6 +369,86 @@ void NcFileHandler::to_netcdf(std::string out_fpath, std::string variable_name, output_var.putVar(startp, countp, tmp); } } +/** Saves a dataset to file (3 dimensions: time x lat x lon ) + * + * @param out_fpath output file path + * @param variable_name name of the output variable + * @param out_data 3d vector of data + */ +void NcFileHandler::to_netcdf(std::string out_fpath, std::string variable_name, std::vector>>& v_out_data) { + netCDF::NcFile output_file(out_fpath, netCDF::NcFile::replace); + + netCDF::NcDim + out_time_dim = output_file.addDim(time_name, n_time), + out_lat_dim = output_file.addDim(lat_name, n_lat), + out_lon_dim = output_file.addDim(lon_name, n_lon); + + netCDF::NcVar + out_time_var = output_file.addVar(time_name, netCDF::ncDouble, out_time_dim), + out_lat_var = output_file.addVar(lat_name, netCDF::ncFloat, out_lat_dim), + out_lon_var = output_file.addVar(lon_name, netCDF::ncFloat, out_lon_dim); + + // Set attributes + for (std::pair att : time_var.getAtts()) { + if (att.second.getType().getName() == "char") { + char value[att.second.getAttLength()]; + att.second.getValues(value); + out_time_var.putAtt(att.first, att.second.getType(), att.second.getAttLength(), value); + } else if (att.second.getType().getName() == "double") { + double value[att.second.getAttLength()]; + att.second.getValues(value); + out_time_var.putAtt(att.first, att.second.getType(), att.second.getAttLength(), value); + } + } + + for (std::pair att : lon_var.getAtts()) { + if (att.second.getType().getName() == "char") { + char value[att.second.getAttLength()]; + att.second.getValues(value); + out_lon_var.putAtt(att.first, att.second.getType(), att.second.getAttLength(), value); + } + } + + for (std::pair att : lat_var.getAtts()) { + if (att.second.getType().getName() == "char") { + char value[att.second.getAttLength()]; + att.second.getValues(value); + out_lat_var.putAtt(att.first, att.second.getType(), att.second.getAttLength(), value); + } + } + + std::vector dim_vector; + dim_vector.push_back(out_time_dim); + dim_vector.push_back(out_lat_dim); + dim_vector.push_back(out_lon_dim); + + netCDF::NcVar + output_var = output_file.addVar(variable_name, netCDF::ncFloat, dim_vector); + + out_time_var.putVar(time_values); + out_lat_var.putVar(lat_values); + out_lon_var.putVar(lon_values); + + std::vector startp, countp; + startp.push_back(0); + startp.push_back(0); + startp.push_back(0); + countp.push_back(1); + countp.push_back(n_lat); + countp.push_back(n_lon); + + // ? workaround, because putVar does not work with pointer + // ? -> it works but creates random incostances and destroys the result + for (size_t time = 0; time < n_time; time++) { + startp[0] = time; + float tmp[n_lat][n_lon]; + for (unsigned lat = 0; lat < n_lat; lat++) { + for (unsigned lon = 0; lon < n_lon; lon++) + tmp[lat][lon] = v_out_data[time][lat][lon]; + } + output_var.putVar(startp, countp, tmp); + } +} /** Saves a dataset containing multiple variables for only one timestep to file * diff --git a/src/main.cxx b/src/main.cxx index 70fd47e..8686936 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -33,10 +33,13 @@ #include +#include + #include "CMethods.hxx" #include "NcFileHandler.hxx" #include "Utils.hxx" #include "colors.h" + /* * ----- ----- ----- D E F I N I T I O N S ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */ @@ -95,8 +98,8 @@ static void show_usage(std::string name) { std::cerr << BOLDBLUE << "Available methods: " << RESET << "\n-> "; std::vector all_methods; - all_methods.reserve(CMethods::simple_method_names.size() + CMethods::quantile_method_names.size()); // preallocate memory - all_methods.insert(all_methods.end(), CMethods::simple_method_names.begin(), CMethods::simple_method_names.end()); + all_methods.reserve(CMethods::scaling_method_names.size() + CMethods::quantile_method_names.size()); // preallocate memory + all_methods.insert(all_methods.end(), CMethods::scaling_method_names.begin(), CMethods::scaling_method_names.end()); all_methods.insert(all_methods.end(), CMethods::quantile_method_names.begin(), CMethods::quantile_method_names.end()); for (size_t i = 0; i < all_methods.size(); i++) std::cerr << all_methods[i] << " "; @@ -205,109 +208,84 @@ static int parse_args(int argc, char** argv) { std::runtime_error("Longitude dimension of input files does not have the same length!"); else if (ds_reference.n_time != ds_control.n_time || ds_reference.n_time != ds_scenario.n_time) std::runtime_error("Time dimension input files does not have the same length!"); - return 0; } /* * ----- ----- ----- C O M P U T A T I O N ----- ----- ----- ----- ----- ----- ----- ----- ----- */ -static void do_simple_adjustment(float*** data_out) { - CM_Func_ptr_simple apply_adjustment = CMethods::get_cmethod_simple(adjustment_method_name); - - for (unsigned lat = 0; lat < ds_reference.n_lat; lat++) { - // ? Fill whole row of data for each dataset - float** reference_lon_data = new float*[ds_reference.n_lon]; - float** control_lon_data = new float*[ds_control.n_lon]; - float** scenario_lon_data = new float*[ds_scenario.n_lon]; - - for (unsigned i = 0; i < ds_reference.n_lon; i++) { - reference_lon_data[i] = new float[ds_reference.n_time]; - control_lon_data[i] = new float[ds_control.n_time]; - scenario_lon_data[i] = new float[ds_scenario.n_time]; - } - - ds_reference.fill_lon_timeseries_for_lat(reference_lon_data, lat); - ds_control.fill_lon_timeseries_for_lat(control_lon_data, lat); - ds_scenario.fill_lon_timeseries_for_lat(scenario_lon_data, lat); - - for (unsigned lon = 0; lon < ds_reference.n_lon; lon++) +static void do_scaling_adjustment(std::vector>>& v_data_out) { + CM_Func_ptr_scaling apply_adjustment = CMethods::get_cmethod_scaling(adjustment_method_name); + + for (unsigned lat = 0; lat < v_data_out.size(); lat++) { + std::vector> v_reference_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + std::vector> v_control_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + std::vector> v_scenario_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + + ds_reference.fill_lon_timeseries_for_lat(v_reference_lon_data, lat); + ds_control.fill_lon_timeseries_for_lat(v_control_lon_data, lat); + ds_scenario.fill_lon_timeseries_for_lat(v_scenario_lon_data, lat); + + for (unsigned lon = 0; lon < v_data_out.at(0).size(); lon++) apply_adjustment( - data_out[lat][lon], - reference_lon_data[lon], - control_lon_data[lon], - scenario_lon_data[lon], - ds_reference.n_time, + v_data_out[lat][lon], + v_reference_lon_data[lon], + v_control_lon_data[lon], + v_scenario_lon_data[lon], adjustment_kind); - for (unsigned xlon = 0; xlon < ds_reference.n_lon; xlon++) { - delete reference_lon_data[xlon]; - delete control_lon_data[xlon]; - delete scenario_lon_data[xlon]; - } - delete[] reference_lon_data; - delete[] control_lon_data; - delete[] scenario_lon_data; - - utils::progress_bar((float)lat, (float)ds_reference.n_lat); + utils::progress_bar((float)lat, (float)(v_data_out.size())); } - utils::progress_bar((float)ds_reference.n_lat, (float)ds_reference.n_lat); + utils::progress_bar((float)(v_data_out.size()), (float)(v_data_out.size())); } -static void do_quantile_adjustment(float*** data_out) { +static void do_quantile_adjustment(std::vector>>& v_data_out) { CM_Func_ptr_quantile apply_adjustment = CMethods::get_cmethod_quantile(adjustment_method_name); - for (unsigned lat = 0; lat < ds_reference.n_lat; lat++) { - float** reference_lon_data = new float*[ds_reference.n_lon]; - float** control_lon_data = new float*[ds_control.n_lon]; - float** scenario_lon_data = new float*[ds_scenario.n_lon]; - - for (unsigned i = 0; i < ds_reference.n_lon; i++) { - reference_lon_data[i] = new float[ds_reference.n_time]; - control_lon_data[i] = new float[ds_control.n_time]; - scenario_lon_data[i] = new float[ds_scenario.n_time]; - } - - // ? Fill whole row of data for each dataset - ds_reference.fill_lon_timeseries_for_lat(reference_lon_data, lat); - ds_control.fill_lon_timeseries_for_lat(control_lon_data, lat); - ds_scenario.fill_lon_timeseries_for_lat(scenario_lon_data, lat); - - for (unsigned lon = 0; lon < ds_reference.n_lon; lon++) { + for (unsigned lat = 0; lat < v_data_out.size(); lat++) { + std::vector> v_reference_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + std::vector> v_control_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + std::vector> v_scenario_lon_data( + v_data_out.at(lat).size(), + std::vector(v_data_out.at(0).at(0).size())); + + ds_reference.fill_lon_timeseries_for_lat(v_reference_lon_data, lat); + ds_control.fill_lon_timeseries_for_lat(v_control_lon_data, lat); + ds_scenario.fill_lon_timeseries_for_lat(v_scenario_lon_data, lat); + + for (unsigned lon = 0; lon < v_data_out.at(0).size(); lon++) { apply_adjustment( - data_out[lat][lon], - reference_lon_data[lon], - control_lon_data[lon], - scenario_lon_data[lon], - ds_reference.n_time, + v_data_out[lat][lon], + v_reference_lon_data[lon], + v_control_lon_data[lon], + v_scenario_lon_data[lon], adjustment_kind, n_quantiles); } - - for (unsigned xlon = 0; xlon < ds_reference.n_lon; xlon++) { - delete reference_lon_data[xlon]; - delete control_lon_data[xlon]; - delete scenario_lon_data[xlon]; - } - delete[] reference_lon_data; - delete[] control_lon_data; - delete[] scenario_lon_data; - - utils::progress_bar((float)lat, (float)(ds_reference.n_lat)); + utils::progress_bar((float)lat, (float)(v_data_out.size())); } - utils::progress_bar((float)ds_reference.n_lat, (float)(ds_reference.n_lat)); + utils::progress_bar((float)(v_data_out.size()), (float)(v_data_out.size())); } -static void do_adjustment(float*** data_out) { - if (isInStrV(CMethods::simple_method_names, adjustment_method_name)) - do_simple_adjustment(data_out); +static void do_adjustment(std::vector>>& v_data_out) { + if (isInStrV(CMethods::scaling_method_names, adjustment_method_name)) + do_scaling_adjustment(v_data_out); if (isInStrV(CMethods::quantile_method_names, adjustment_method_name)) - do_quantile_adjustment(data_out); + do_quantile_adjustment(v_data_out); else std::runtime_error("Unknown adjustment method " + adjustment_method_name + "!"); std::cout << std::endl; } - /* * ----- ----- ----- M A I N ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */ @@ -318,29 +296,34 @@ int main(int argc, char** argv) { if (args_result != 0) return args_result; // ? prepare memory lat x lon x time - float*** data_out = new float**[(int)ds_reference.n_lat]; - for (unsigned lat = 0; lat < (int)ds_reference.n_lat; lat++) { - data_out[lat] = new float*[(int)ds_reference.n_lon]; - for (unsigned lon = 0; lon < (int)ds_reference.n_lon; lon++) - data_out[lat][lon] = new float[(int)ds_reference.n_time]; - } + std::vector>> v_data_out( + (int)ds_reference.n_lat, + std::vector>( + (int)ds_reference.n_lon, + std::vector( + (int)ds_reference.n_time))); // ? apply adjustment - do_adjustment(data_out); + do_adjustment(v_data_out); + + std::vector>> v_data_to_save( + (int)ds_reference.n_time, + std::vector>( + (int)ds_reference.n_lat, + std::vector( + (int)ds_reference.n_lon))); // ? reshape to lat x lon x time - float*** data_to_save = new float**[ds_scenario.n_time]; - for (unsigned time = 0; time < ds_scenario.n_time; time++) { - data_to_save[time] = new float*[ds_scenario.n_lat]; - for (unsigned lat = 0; lat < ds_scenario.n_lat; lat++) { - data_to_save[time][lat] = new float[ds_scenario.n_lon]; - for (unsigned lon = 0; lon < ds_scenario.n_lon; lon++) - data_to_save[time][lat][lon] = data_out[lat][lon][time]; + for (unsigned lat = 0; lat < v_data_out.size(); lat++) { + for (unsigned lon = 0; lon < v_data_out.at(lat).size(); lon++) { + for (unsigned time = 0; time < v_data_out.at(lat).at(lon).size(); time++) { + v_data_to_save.at(time).at(lat).at(lon) = v_data_out.at(lat).at(lon).at(time); + } } } Log.info("Saving " + output_filepath); - ds_scenario.to_netcdf(output_filepath, variable_name, data_to_save); + ds_scenario.to_netcdf(output_filepath, variable_name, v_data_to_save); Log.info("SUCCESS!"); return 0;