├── .github
└── workflows
│ ├── main.yml
│ └── package.yml
├── .gitignore
├── CMakeLists.txt
├── COPYING
├── LICENSE
├── README.md
├── cmake
├── FindNetCDF.cmake
├── FindR.cmake
└── Testing.cmake
├── docs
├── DoxygenLayout.xml
├── config.in
└── image.jpg
├── include
└── gridpp.h
├── src
├── api
│ ├── .calc_gradient.cpp.swo
│ ├── .gitignore
│ ├── bilinear.cpp
│ ├── calc_gradient.cpp
│ ├── corr_points.cpp
│ ├── count.cpp
│ ├── curve.cpp
│ ├── distance.cpp
│ ├── distribution.cpp
│ ├── doping.cpp
│ ├── downscale_probability.cpp
│ ├── downscaling.cpp
│ ├── fill.cpp
│ ├── gradient.cpp
│ ├── grid.cpp
│ ├── gridding.cpp
│ ├── gridpp.cpp
│ ├── humidity.cpp
│ ├── kdtree.cpp
│ ├── local_distribution_correction.cpp
│ ├── mask_threshold_downscale_consensus.cpp
│ ├── metric_optimizer.cpp
│ ├── nearest.cpp
│ ├── neighbourhood.cpp
│ ├── neighbourhood_score.cpp
│ ├── neighbourhood_search.cpp
│ ├── oi.cpp
│ ├── oi_ensi.cpp
│ ├── oi_ensi_multi.cpp
│ ├── point.cpp
│ ├── points.cpp
│ ├── pressure.cpp
│ ├── qnh.cpp
│ ├── quantile_mapping.cpp
│ ├── simple_gradient.cpp
│ ├── smart.cpp
│ ├── structure.cpp
│ ├── swig.cpp
│ ├── transform.cpp
│ ├── util.cpp
│ ├── wind.cpp
│ └── window.cpp
└── client
│ ├── CMakeLists.txt
│ ├── Calibrator
│ ├── Accumulate.cpp
│ ├── Accumulate.h
│ ├── Altitude.cpp
│ ├── Altitude.h
│ ├── Bct.cpp
│ ├── Bct.h
│ ├── Calibrator.cpp
│ ├── Calibrator.h
│ ├── Cloud.cpp
│ ├── Cloud.h
│ ├── Coastal.cpp
│ ├── Coastal.h
│ ├── Deaccumulate.cpp
│ ├── Deaccumulate.h
│ ├── DiagnoseHumidity.cpp
│ ├── DiagnoseHumidity.h
│ ├── DiagnoseWind.cpp
│ ├── DiagnoseWind.h
│ ├── Gaussian.cpp
│ ├── Gaussian.h
│ ├── Kriging.cpp
│ ├── Kriging.h
│ ├── Mask.cpp
│ ├── Mask.h
│ ├── Neighbourhood.cpp
│ ├── Neighbourhood.h
│ ├── Oi.cpp
│ ├── Oi.h
│ ├── Override.cpp
│ ├── Override.h
│ ├── Phase.cpp
│ ├── Phase.h
│ ├── Qc.cpp
│ ├── Qc.h
│ ├── Qnh.cpp
│ ├── Qnh.h
│ ├── Qq.cpp
│ ├── Qq.h
│ ├── Regression.cpp
│ ├── Regression.h
│ ├── Sort.cpp
│ ├── Sort.h
│ ├── Temperature.cpp
│ ├── Temperature.h
│ ├── Threshold.cpp
│ ├── Threshold.h
│ ├── WindDirection.cpp
│ ├── WindDirection.h
│ ├── Window.cpp
│ ├── Window.h
│ ├── Zaga.cpp
│ ├── Zaga.h
│ └── devel
│ │ ├── Wind.cpp
│ │ └── Wind.h
│ ├── Downscaler
│ ├── Bilinear.cpp
│ ├── Bilinear.h
│ ├── Bypass.cpp
│ ├── Bypass.h
│ ├── Coastal.h
│ ├── Downscaler.cpp
│ ├── Downscaler.h
│ ├── Gradient.cpp
│ ├── Gradient.h
│ ├── NearestNeighbour.cpp
│ ├── NearestNeighbour.h
│ ├── Pressure.cpp
│ ├── Pressure.h
│ ├── Smart.cpp
│ ├── Smart.h
│ ├── Upscale.cpp
│ └── Upscale.h
│ ├── Driver
│ ├── .vimrc
│ ├── Custom.cpp
│ └── Gridpp.cpp
│ ├── Field.cpp
│ ├── Field.h
│ ├── File
│ ├── Fake.cpp
│ ├── Fake.h
│ ├── File.cpp
│ ├── File.h
│ ├── Netcdf.cpp
│ ├── Netcdf.h
│ ├── NorcomQnh.cpp
│ ├── NorcomQnh.h
│ ├── Point.cpp
│ ├── Point.h
│ ├── Text.cpp
│ └── Text.h
│ ├── Grid.cpp
│ ├── Grid.h
│ ├── KDTree.cpp
│ ├── KDTree.h
│ ├── Location.cpp
│ ├── Location.h
│ ├── NetcdfUtil.cpp
│ ├── NetcdfUtil.h
│ ├── Options.cpp
│ ├── Options.h
│ ├── ParameterFile
│ ├── .vimrc
│ ├── Netcdf.cpp
│ ├── Netcdf.h
│ ├── ParameterFile.cpp
│ ├── ParameterFile.h
│ ├── Simple.cpp
│ ├── Simple.h
│ ├── Text.cpp
│ └── Text.h
│ ├── Parameters.cpp
│ ├── Parameters.h
│ ├── Scheme.cpp
│ ├── Scheme.h
│ ├── Setup.cpp
│ ├── Setup.h
│ ├── Testing
│ ├── .vimrc
│ ├── Calibrator.cpp
│ ├── CalibratorAccumulate.cpp
│ ├── CalibratorAltitude.cpp
│ ├── CalibratorBct.cpp
│ ├── CalibratorDeaccumulate.cpp
│ ├── CalibratorDiagnoseHumidity.cpp
│ ├── CalibratorDiagnoseWind.cpp
│ ├── CalibratorKriging.cpp
│ ├── CalibratorMask.cpp
│ ├── CalibratorNeighbourhood.cpp
│ ├── CalibratorPhase.cpp
│ ├── CalibratorQc.cpp
│ ├── CalibratorQnh.cpp
│ ├── CalibratorQq.cpp
│ ├── CalibratorRegression.cpp
│ ├── CalibratorSort.cpp
│ ├── CalibratorThreshold.cpp
│ ├── CalibratorWindDirection.cpp
│ ├── CalibratorWindow.cpp
│ ├── CalibratorZaga.cpp
│ ├── Downscaler.cpp
│ ├── DownscalerBilinear.cpp
│ ├── DownscalerGradient.cpp
│ ├── DownscalerNearestNeighbour.cpp
│ ├── DownscalerPressure.cpp
│ ├── DownscalerSmart.cpp
│ ├── Field.cpp
│ ├── File.cpp
│ ├── FileFake.cpp
│ ├── FileNetcdf.cpp
│ ├── FileNorcomQnh.cpp
│ ├── FilePoint.cpp
│ ├── FileText.cpp
│ ├── KDTree.cpp
│ ├── Location.cpp
│ ├── NetcdfUtil.cpp
│ ├── Options.cpp
│ ├── ParameterFile.cpp
│ ├── ParameterFileNetcdf.cpp
│ ├── ParameterFileSimple.cpp
│ ├── ParameterFileText.cpp
│ ├── Parameters.cpp
│ ├── Setup.cpp
│ ├── Template
│ ├── Util.cpp
│ ├── Variable.cpp
│ └── devel
│ │ └── OperationalStatkraft.cpp
│ ├── Util.cpp
│ ├── Util.h
│ ├── Uuid.h
│ ├── Variable.cpp
│ ├── Variable.h
│ ├── Version.h
│ └── run_all_tests.sh
├── swig
├── CMakeLists.txt
├── R
│ └── CMakeLists.txt
├── gridpp.i
├── numpy.i
├── python-packaging
│ ├── CMakeLists.txt
│ ├── MANIFEST.in
│ ├── pyproject.toml
│ ├── setup.in.py
│ └── setup.sh
├── python
│ ├── CMakeLists.txt
│ └── setup.in.py
└── vector.i
└── tests
├── .gitignore
├── __init__.py
├── benchmark.py
├── check_installation.py
├── files
├── .gitignore
├── 10x10.nc
├── 10x10.txt
├── 10x10_copy.nc
├── 10x10_ec.nc
├── 10x10_noPrecip.nc
├── 10x10_param.nc
├── 10x10_param_xy.nc
├── 10x10_param_zero_altitude.nc
├── 1x1.nc
├── 3x3.nc
├── invalidText1.txt
├── kalmanEmpty.txt
├── kalmanInvalid1.txt
├── kalmanInvalid2.txt
├── kalmanInvalid3.txt
├── kalmanInvalid4.txt
├── kalmanOutput.txt
├── kalmanOutputWithMissing.txt
├── mask0.txt
├── parameters.txt
├── parametersCycling.txt
├── parametersEmpty.txt
├── parametersInvalidEntries.txt
├── parametersInvalidTime.txt
├── parametersKriging.txt
├── parametersMultipleTime.txt
├── parametersNoTime.txt
├── parametersPhase.txt
├── parametersQq.txt
├── parametersSingleTime.txt
├── parametersUnevenRows.txt
├── parametersWindDirection.txt
├── regression0order.txt
├── regression1order.txt
├── regression2order.txt
├── regressionInvalid1.txt
├── regressionMissing.txt
├── sampleObsFcst.txt
├── training.txt
├── trainingDataFcst.txt
├── trainingDataObs.txt
├── trainingDataTemperature.txt
├── validArome1.nc
├── validArome2.nc
├── validEc1.nc
├── validEc2.nc
├── validEc3.nc
├── validEc_gph.nc
├── validEc_gph_no_x.nc
├── validEc_multidim_altitude.nc
├── validNetcdf1.nc
├── validNetcdf2.nc
├── validNetcdf3.nc
├── validNetcdf4.nc
├── validNetcdfAnalysis.nc
├── validNetcdfAnalysis2.nc
├── validNetcdfDimNames.nc
├── validNetcdfGeopotential.nc
├── validPoint1.txt
├── validPoint2.txt
├── validText1.txt
└── validText2.txt
├── test_apply_curve.py
├── test_barnes_structure.py
├── test_bilinear.py
├── test_calc_gradient.py
├── test_count.py
├── test_distance.py
├── test_distribution.py
├── test_doping.py
├── test_downscale_probability.py
├── test_downscaling.py
├── test_fill.py
├── test_fill_missing.py
├── test_full_gradient.py
├── test_get_neighbourhood_thresholds.py
├── test_gradient.py
├── test_grid.py
├── test_gridding.py
├── test_humidity.py
├── test_init_vec.py
├── test_interpolate.py
├── test_kdtree.py
├── test_local_distribution_correction.py
├── test_mask_threshold_downscale_consensus.py
├── test_memory.py
├── test_metric_optimizer.py
├── test_monotonize.py
├── test_nearest.py
├── test_neighbourhood.py
├── test_neighbourhood_quantile.py
├── test_neighbourhood_quantile_fast.py
├── test_neighbourhood_search.py
├── test_optimal_interpolation.py
├── test_optimal_interpolation_ens.py
├── test_point.py
├── test_point_in_rectangle.py
├── test_points.py
├── test_pressure.py
├── test_qnh.py
├── test_quantile_mapping.py
├── test_sea_level_pressure.py
├── test_simple_gradient.py
├── test_structure.py
├── test_swig.py
├── test_transform.py
├── test_util.py
├── test_wind.py
└── test_window.py
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: C/C++ CI
2 |
3 | on: [push, pull_request]
4 |
5 | # push:
6 | # branches: [ master ]
7 | # pull_request:
8 | # branches: [ master ]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-20.04
13 |
14 | steps:
15 | - uses: actions/checkout@v4
16 | - uses: actions/setup-python@v5
17 | with:
18 | python-version: '3.10'
19 | - name: dependencies
20 | run: |
21 | sudo apt update -qq
22 | sudo apt install swig libboost-dev libarmadillo9 libarmadillo-dev cmake python3-setuptools python3-numpy python3-pip lcov
23 | - name: configure
24 | run: mkdir build && cd build && cmake -DBUILD_R=no -DCMAKE_BUILD_TYPE=DEBUG -DENABLE_TESTS=ON ..
25 | - name: build
26 | run: cd build && VERBOSE=1 make develop-python-user
27 | - name: test
28 | run: |
29 | cd build
30 | /usr/bin/python3 -m pip install coverage nose
31 | make tests
32 | lcov --directory CMakeFiles/gridpp.dir/src/api --capture --output-file coverage.info
33 | lcov --remove coverage.info '/usr/*' --output-file coverage.info
34 | lcov --list coverage.info
35 | # - name: test
36 | # run: |
37 | # /usr/bin/python3 -c "import gridpp; print(gridpp.version())"
38 | # /usr/bin/python3 -m pip install --upgrade pip
39 | # /usr/bin/python3 -m pip install coverage nose
40 | # coverage run --omit */*-packages/*,*tests* -m nose
41 | # coverage report
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | *.o
3 | gridpp
4 | gridpp_debug
5 | gridpp_train
6 | gridpp_train_debug
7 | gridpp_kf
8 | gridpp_kf_debug
9 | *.nc
10 | gmon.out
11 | tags
12 | temp/
13 | */devel/
14 | devel/
15 | .*.swp
16 | data
17 | coverage.*
18 | debian/gridpp*
19 | build*
20 | env/
21 | .vscode
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | Copyright 2014-2024 Norwegian Meteorological Institute
2 | All rights reserved.
3 |
4 | This program is free software: you can redistribute it and/or modify it under the terms of
5 | the GNU Lesser General Public License as published by the Free Software Foundation, either
6 | version 3 of the License, or (at your option) any later version.
7 |
8 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 | See the GNU Lesser General Public License for more details.
11 |
12 | You should have received a copy of the GNU Lesser General Public License along with this
13 | program. If not, see .
14 |
--------------------------------------------------------------------------------
/docs/image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/metno/gridpp/7f357ccbfec56f7d59482fecb5b51cb4dd46fa59/docs/image.jpg
--------------------------------------------------------------------------------
/src/api/.calc_gradient.cpp.swo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/metno/gridpp/7f357ccbfec56f7d59482fecb5b51cb4dd46fa59/src/api/.calc_gradient.cpp.swo
--------------------------------------------------------------------------------
/src/api/.gitignore:
--------------------------------------------------------------------------------
1 | convert.sh
2 |
--------------------------------------------------------------------------------
/src/api/count.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 |
4 | using namespace gridpp;
5 |
6 | vec gridpp::count(const Grid& grid, const Points& points, float radius) {
7 | int size = points.size();
8 | vec output(size);
9 | vec olats = points.get_lats();
10 | vec olons = points.get_lons();
11 | #pragma omp parallel for
12 | for(int i = 0; i < size; i++) {
13 | int num = grid.get_num_neighbours(olats[i], olons[i], radius);
14 | output[i] = num;
15 | }
16 | return output;
17 | }
18 |
19 | vec2 gridpp::count(const Grid& igrid, const Grid& ogrid, float radius) {
20 | ivec size = ogrid.size();
21 | vec2 output(size[0]);
22 | vec2 olats = ogrid.get_lats();
23 | vec2 olons = ogrid.get_lons();
24 | for(int i = 0; i < size[0]; i++) {
25 | output[i].resize(size[1], 0);
26 | }
27 | #pragma omp parallel for collapse(2)
28 | for(int i = 0; i < size[0]; i++) {
29 | for(int j = 0; j < size[1]; j++) {
30 | int num = igrid.get_num_neighbours(olats[i][j], olons[i][j], radius);
31 | output[i][j] = num;
32 | }
33 | }
34 | return output;
35 | }
36 |
37 | vec2 gridpp::count(const Points& points, const Grid& grid, float radius) {
38 | ivec size = grid.size();
39 | vec2 output(size[0]);
40 | vec2 olats = grid.get_lats();
41 | vec2 olons = grid.get_lons();
42 | for(int i = 0; i < size[0]; i++) {
43 | output[i].resize(size[1], 0);
44 | }
45 | #pragma omp parallel for collapse(2)
46 | for(int i = 0; i < size[0]; i++) {
47 | for(int j = 0; j < size[1]; j++) {
48 | int num = points.get_num_neighbours(olats[i][j], olons[i][j], radius);
49 | output[i][j] = num;
50 | }
51 | }
52 | return output;
53 | }
54 |
55 | vec gridpp::count(const Points& ipoints, const Points& opoints, float radius) {
56 | int size = opoints.size();
57 | vec output(size);
58 | vec olats = opoints.get_lats();
59 | vec olons = opoints.get_lons();
60 | #pragma omp parallel for
61 | for(int i = 0; i < size; i++) {
62 | int num = ipoints.get_num_neighbours(olats[i], olons[i], radius);
63 | output[i] = num;
64 | }
65 | return output;
66 | }
67 |
--------------------------------------------------------------------------------
/src/api/distribution.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 |
3 | using namespace gridpp;
4 |
5 | vec gridpp::gamma_inv(const vec& levels, const vec& shape, const vec& scale) {
6 | int N = shape.size();
7 | for(int i = 0; i < N; i++) {
8 | if(levels[i] < 0 || levels[i] > 1 || !gridpp::is_valid(levels[i])) {
9 | std::stringstream ss;
10 | ss << "Invalid level '" << levels[i] << "'. Levels must be on the interval [0, 1].";
11 | throw std::invalid_argument(ss.str());
12 | }
13 | if(shape[i] <= 0 || !gridpp::is_valid(shape[i])) {
14 | std::stringstream ss;
15 | ss << "Invalid shape '" << shape[i] << "'. Shapes must be > 0.";
16 | throw std::invalid_argument(ss.str());
17 | }
18 | if(scale[i] <= 0 || !gridpp::is_valid(scale[i])) {
19 | std::stringstream ss;
20 | ss << "Invalid scale '" << scale[i] << "'. Scale must be > 0.";
21 | throw std::invalid_argument(ss.str());
22 | }
23 | }
24 | vec results(N);
25 |
26 | #pragma omp parallel for
27 | for(int i = 0; i < N; i++) {
28 | boost::math::gamma_distribution<> m_gamma_dist(shape[i], scale[i]);
29 | float value = boost::math::quantile(m_gamma_dist, levels[i]);
30 | results[i] = value;
31 | }
32 | return results;
33 | }
34 |
--------------------------------------------------------------------------------
/src/api/downscale_probability.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 | #include
4 |
5 | using namespace gridpp;
6 |
7 | vec2 gridpp::downscale_probability(const Grid& igrid, const Grid& ogrid, const vec3& ivalues, const vec2& threshold, const ComparisonOperator& comparison_operator) {
8 | vec2 iOutputLats = ogrid.get_lats();
9 | vec2 iOutputLons = ogrid.get_lons();
10 |
11 | int nLat = iOutputLats.size();
12 | int nLon = iOutputLats[0].size();
13 | int nEns = ivalues[0][0].size();
14 |
15 | vec2 output(nLat);
16 | for(int i = 0; i < nLat; i++)
17 | output[i].resize(nLon);
18 |
19 | #pragma omp parallel for collapse(2)
20 | for(int i = 0; i < nLat; i++) {
21 | for(int j = 0; j < nLon; j++) {
22 | ivec indices = igrid.get_nearest_neighbour(iOutputLats[i][j], iOutputLons[i][j]);
23 | int I = indices[0];
24 | int J = indices[1];
25 | int count = 0;
26 | int total = 0;
27 | for(int k = 0; k < nEns; k++){
28 | if (gridpp::is_valid(ivalues[I][J][k])) {
29 | count = count + 1;
30 | if (comparison_operator == gridpp::Leq) {
31 | if (ivalues[I][J][k] <= threshold[i][j]) {
32 | total = total + 1;
33 | }
34 | } else if (comparison_operator == gridpp::Lt) {
35 | if (ivalues[I][J][k] < threshold[i][j]) {
36 | total = total + 1;
37 | }
38 | } else if (comparison_operator == gridpp::Geq) {
39 | if (ivalues[I][J][k] >= threshold[i][j]) {
40 | total = total + 1;
41 | }
42 | } else if (comparison_operator == gridpp::Gt) {
43 | if (ivalues[I][J][k] > threshold[i][j]) {
44 | total = total + 1;
45 | }
46 | }
47 | }
48 | }
49 | // std::cout << "total[" << i <<"][" << j << "]:" << total << std::endl;
50 | // std::cout << "count[" << i <<"][" << j << "]:" << count << std::endl;
51 |
52 | float prob;
53 | if (count == 0) {
54 | prob = gridpp::MV;
55 | }
56 | else {
57 | prob = (float)total / (float)count;
58 | // std::cout << "prob[" << i <<"][" << j << "]:" << prob << std::endl;
59 | }
60 |
61 | output[i][j] = prob;
62 | }
63 | }
64 | return output;
65 | }
--------------------------------------------------------------------------------
/src/api/downscaling.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 | #include
4 |
5 | using namespace gridpp;
6 |
7 | vec gridpp::downscaling(const Grid& igrid, const Points& opoints, const vec2& ivalues, Downscaler downscaler) {
8 | if(!gridpp::compatible_size(igrid, ivalues))
9 | throw std::invalid_argument("Grid size is not the same as values");
10 |
11 | vec output;
12 | if(downscaler == gridpp::Nearest)
13 | output = gridpp::nearest(igrid, opoints, ivalues);
14 | else if(downscaler == gridpp::Bilinear)
15 | output = gridpp::bilinear(igrid, opoints, ivalues);
16 | else
17 | throw std::invalid_argument("Invalid downscaler");
18 | return output;
19 | }
20 |
21 | vec2 gridpp::downscaling(const Grid& igrid, const Grid& ogrid, const vec2& ivalues, Downscaler downscaler) {
22 | if(!gridpp::compatible_size(igrid, ivalues))
23 | throw std::invalid_argument("Grid size is not the same as values");
24 |
25 | vec2 output;
26 | if(downscaler == gridpp::Nearest)
27 | output = gridpp::nearest(igrid, ogrid, ivalues);
28 | else if(downscaler == gridpp::Bilinear)
29 | output = gridpp::bilinear(igrid, ogrid, ivalues);
30 | else
31 | throw std::invalid_argument("Invalid downscaler");
32 | return output;
33 | }
34 |
35 | vec2 gridpp::downscaling(const Grid& igrid, const Points& opoints, const vec3& ivalues, Downscaler downscaler) {
36 | if(!gridpp::compatible_size(igrid, ivalues))
37 | throw std::invalid_argument("Grid size is not the same as values");
38 |
39 | vec2 output;
40 | if(downscaler == gridpp::Nearest)
41 | output = gridpp::nearest(igrid, opoints, ivalues);
42 | else if(downscaler == gridpp::Bilinear)
43 | output = gridpp::bilinear(igrid, opoints, ivalues);
44 | else
45 | throw std::invalid_argument("Invalid downscaler");
46 | return output;
47 | }
48 |
49 | vec3 gridpp::downscaling(const Grid& igrid, const Grid& ogrid, const vec3& ivalues, Downscaler downscaler) {
50 | if(!gridpp::compatible_size(igrid, ivalues))
51 | throw std::invalid_argument("Grid size is not the same as values");
52 |
53 | vec3 output;
54 | if(downscaler == gridpp::Nearest)
55 | output = gridpp::nearest(igrid, ogrid, ivalues);
56 | else if(downscaler == gridpp::Bilinear)
57 | output = gridpp::bilinear(igrid, ogrid, ivalues);
58 | else
59 | throw std::invalid_argument("Invalid downscaler");
60 | return output;
61 | }
62 |
--------------------------------------------------------------------------------
/src/api/gridpp.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 | #include
4 | #include
5 |
6 | using namespace gridpp;
7 |
8 | std::string gridpp::version() {
9 | return __version__;
10 | }
11 | gridpp::Statistic gridpp::get_statistic(std::string name) {
12 | gridpp::Statistic type;
13 | if(name == "mean") {
14 | type = gridpp::Mean;
15 | }
16 | else if(name == "min") {
17 | type = gridpp::Min;
18 | }
19 | else if(name == "max") {
20 | type = gridpp::Max;
21 | }
22 | else if(name == "median") {
23 | type = gridpp::Median;
24 | }
25 | else if(name == "quantile") {
26 | type = gridpp::Quantile;
27 | }
28 | else if(name == "std") {
29 | type = gridpp::Std;
30 | }
31 | else if(name == "sum") {
32 | type = gridpp::Sum;
33 | }
34 | else if(name == "count") {
35 | type = gridpp::Count;
36 | }
37 | else if(name == "randomchoice") {
38 | type = gridpp::RandomChoice;
39 | }
40 | else {
41 | type = gridpp::Unknown;
42 | }
43 | return type;
44 | }
45 | void gridpp::initialize_omp() {
46 | #ifdef _OPENMP
47 | int num_threads = 1;
48 | const char* num_threads_char = std::getenv("OMP_NUM_THREADS");
49 | if(num_threads_char != NULL) {
50 | std::istringstream(std::string(num_threads_char)) >> num_threads;
51 | if(num_threads <= 0)
52 | num_threads = 1;
53 | }
54 | gridpp::set_omp_threads(num_threads);
55 | #endif
56 | }
57 | void gridpp::set_omp_threads(int num) {
58 | #ifdef _OPENMP
59 | // omp_set_dynamic(0);
60 | omp_set_num_threads(num);
61 | #endif
62 | }
63 | int gridpp::get_omp_threads() {
64 | #ifdef _OPENMP
65 | return omp_get_max_threads();
66 | #endif
67 | return 0;
68 | }
69 |
70 | void gridpp::set_debug_level(int level) {
71 | gridpp::debug_level = level;
72 | }
73 |
74 | int gridpp::get_debug_level() {
75 | return gridpp::debug_level;
76 | }
77 | gridpp::not_implemented_exception::not_implemented_exception() :
78 | std::logic_error("Function not yet implemented") {
79 | };
80 |
--------------------------------------------------------------------------------
/src/api/neighbourhood_score.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 |
4 | using namespace gridpp;
5 |
6 | vec2 gridpp::neighbourhood_score(const Grid& grid, const Points& points, const vec2& fcst, const vec& ref, int half_width, gridpp::Metric metric, float threshold) {
7 |
8 | if(!gridpp::compatible_size(grid, fcst)) {
9 | throw std::invalid_argument("Grid size is not the same as forecast values");
10 | }
11 |
12 | if(half_width <= 0) {
13 | throw std::invalid_argument("half_width must be greater than 0");
14 | }
15 |
16 | int nY = fcst.size();
17 | int nX = fcst[0].size();
18 |
19 | vec2 a = gridpp::init_vec2(nY, nX, 0);
20 | vec2 b = gridpp::init_vec2(nY, nX, 0);
21 | vec2 c = gridpp::init_vec2(nY, nX, 0);
22 | vec2 d = gridpp::init_vec2(nY, nX, 0);
23 |
24 | // Gridding of observations on the the forecast grid
25 | vec2 ref_grid = gridpp::gridding_nearest(grid, points, ref, 1, gridpp::Mean);
26 |
27 | // Compute the 4 contingency values
28 | #pragma omp parallel for collapse(2)
29 | for(int y = 0; y < nY; y++) {
30 | for(int x = 0; x < nX; x++) {
31 | if(gridpp::is_valid(ref_grid[y][x]) && gridpp::is_valid(fcst[y][x])) {
32 | if(fcst[y][x] > threshold) {
33 | a[y][x] = ref_grid[y][x] > threshold;
34 | b[y][x] = ref_grid[y][x] <= threshold;
35 | }
36 | else {
37 | c[y][x] = ref_grid[y][x] > threshold;
38 | d[y][x] = ref_grid[y][x] <= threshold;
39 | }
40 | }
41 | }
42 | }
43 |
44 | // Apply neighbourhood method on contingency values
45 | vec2 a_hood = gridpp::neighbourhood(a, half_width, gridpp::Mean);
46 | vec2 b_hood = gridpp::neighbourhood(b, half_width, gridpp::Mean);
47 | vec2 c_hood = gridpp::neighbourhood(c, half_width, gridpp::Mean);
48 | vec2 d_hood = gridpp::neighbourhood(d, half_width, gridpp::Mean);
49 |
50 | // Compute score in neighbourhood
51 | vec2 output = gridpp::init_vec2(nY, nX, gridpp::Mean);
52 | #pragma omp parallel for collapse(2)
53 | for(int y = 0; y < nY; y++) {
54 | for(int x = 0; x < nX; x++) {
55 | output[y][x] = gridpp::calc_score(a_hood[y][x], b_hood[y][x], c_hood[y][x], d_hood[y][x], metric);
56 | // std::cout << y << " " << x << " " << a_hood[y][x] << std::endl;
57 | }
58 | }
59 | return output;
60 | }
61 |
--------------------------------------------------------------------------------
/src/api/point.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 |
3 | using namespace gridpp;
4 |
5 | gridpp::Point::Point(float lat, float lon, float elev, float laf, CoordinateType type) {
6 | this->lat = lat;
7 | this->lon = lon;
8 | this->elev = elev;
9 | this->laf = laf;
10 | this->type = type;
11 |
12 | if(type == gridpp::Geodetic) {
13 | float new_x = 0;
14 | float new_y = 0;
15 | float new_z = 0;
16 | gridpp::convert_coordinates(lat, lon, type, this->x, this->y, this->z);
17 | }
18 | else {
19 | this->x = lat;
20 | this->y = lon;
21 | this->z = 0;
22 | }
23 | }
24 |
25 | gridpp::Point::Point(float lat, float lon, float elev, float laf, CoordinateType type, float x, float y, float z) : lat(lat), lon(lon), elev(elev), laf(laf), type(type), x(x), y(y), z(z) {
26 | }
27 |
--------------------------------------------------------------------------------
/src/api/qnh.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 |
4 | using namespace gridpp;
5 |
6 | float gridpp::qnh(float pressure, float altitude) {
7 | if(pressure == 0)
8 | return 0;
9 | else if(gridpp::is_valid(altitude) && gridpp::is_valid(pressure)) {
10 | float g = 9.80665; // m/s2
11 | float T0 = 288.15; // K
12 | float L = 0.0065; // K/m
13 | // Method 1:
14 | // float dElev = 0 - altitude;
15 | // float M = 0.0289644; // kg/mol
16 | // float R = 8.31447; // J/(mol•K)
17 | // float cp = 1007; // J/(kg•K)
18 | // float constant = -g*M/R/T0;
19 | // float qnh = pressure * pow(1 - L*dElev/T0, g*M/R/L);
20 |
21 | // Method 2: http://www.hochwarth.com/misc/AviationCalculator.html
22 | float CRGas = 287.053; // [m^2/(s^2*K)] = [J/(kg*K)]
23 | float p0 = 101325; // pa
24 | float qnh = p0*pow(pow((pressure/p0), (CRGas*L)/g) + (altitude*L)/T0, g/(CRGas*L));
25 | return qnh;
26 | }
27 | else {
28 | return MV;
29 | }
30 | }
31 | vec gridpp::qnh(const vec& pressure, const vec& altitude) {
32 | if(pressure.size() != altitude.size())
33 | throw std::invalid_argument("Pressure and altitude vectors are not the same size");
34 |
35 | vec ret(pressure.size());
36 | #pragma omp parallel for
37 | for(int y = 0; y < pressure.size(); y++) {
38 | ret[y] = gridpp::qnh(pressure[y], altitude[y]);
39 | }
40 | return ret;
41 | }
42 |
--------------------------------------------------------------------------------
/src/api/quantile_mapping.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 |
3 | using namespace gridpp;
4 |
5 | vec gridpp::quantile_mapping_curve(const vec& ref, const vec& fcst, vec& output_fcst, vec quantiles) {
6 | if(ref.size() != fcst.size())
7 | throw std::invalid_argument("ref and fcst must be of the same size");
8 |
9 | if(quantiles.size() > 0) {
10 | for(int i = 0; i < quantiles.size(); i++) {
11 | float curr = quantiles[i];
12 | if(!gridpp::is_valid(curr) || curr > 1 || curr < 0)
13 | throw std::invalid_argument("Quantiles must be >= 0 and <= 1");
14 | }
15 | }
16 | output_fcst.clear();
17 | if(ref.size() == 0) {
18 | output_fcst = fcst;
19 | return ref;
20 | }
21 | else if(ref.size() == 1) {
22 | output_fcst = fcst;
23 | return ref;
24 | }
25 |
26 | vec ref_sort = ref;
27 | std::sort(ref_sort.begin(), ref_sort.end());
28 | vec fcst_sort = fcst;
29 | std::sort(fcst_sort.begin(), fcst_sort.end());
30 | int N = quantiles.size();
31 | int S = fcst_sort.size();
32 | if(N == 0) {
33 | output_fcst = fcst_sort;
34 | return ref_sort;
35 | }
36 | else {
37 | output_fcst.resize(N);
38 | vec output_ref(N);
39 | for(int i = 0; i < N; i++) {
40 | int index = quantiles[i] * (S - 1);
41 | output_fcst[i] = fcst[index];
42 | output_ref[i] = ref[index];
43 | }
44 | return output_ref;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/api/wind.cpp:
--------------------------------------------------------------------------------
1 | #include "gridpp.h"
2 | #include
3 |
4 | using namespace gridpp;
5 |
6 | float gridpp::wind_speed(float xwind, float ywind) {
7 | return sqrt(xwind * xwind + ywind * ywind);
8 | }
9 | vec gridpp::wind_speed(const vec& xwind, const vec& ywind) {
10 | if(xwind.size() != ywind.size())
11 | throw std::invalid_argument("xwind and ywind must be of the same size");
12 | int N = xwind.size();
13 | vec values(N, gridpp::MV);
14 | #pragma omp parallel for
15 | for(int n = 0; n < N; n++) {
16 | values[n] = wind_speed(xwind[n], ywind[n]);
17 | }
18 | return values;
19 | }
20 | float gridpp::wind_direction(float xwind, float ywind) {
21 | float dir = std::atan2(-xwind, -ywind) * 180 / gridpp::pi;
22 | if(dir < 0)
23 | dir += 360;
24 |
25 | return dir;
26 | }
27 | vec gridpp::wind_direction(const vec& xwind, const vec& ywind) {
28 | if(xwind.size() != ywind.size())
29 | throw std::invalid_argument("xwind and ywind must be of the same size");
30 | int N = xwind.size();
31 | vec values(N, gridpp::MV);
32 | #pragma omp parallel for
33 | for(int n = 0; n < N; n++) {
34 | values[n] = wind_direction(xwind[n], ywind[n]);
35 | }
36 | return values;
37 | }
38 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Accumulate.cpp:
--------------------------------------------------------------------------------
1 | #include "Accumulate.h"
2 | #include "../Util.h"
3 | #include "../File/File.h"
4 | CalibratorAccumulate::CalibratorAccumulate(const Variable& iVariable, const Options& iOptions) :
5 | Calibrator(iVariable, iOptions) {
6 | iOptions.check();
7 | }
8 | bool CalibratorAccumulate::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
9 | int nY = iFile.getNumY();
10 | int nX = iFile.getNumX();
11 | int nEns = iFile.getNumEns();
12 | int nTime = iFile.getNumTime();
13 |
14 | // Get all fields
15 | std::vector fields(nTime);
16 | std::vector fieldsAcc(nTime);
17 | for(int t = 0; t < nTime; t++) {
18 | fields[t] = iFile.getField(mVariable, t);
19 | fieldsAcc[t] = iFile.getEmptyField();
20 | }
21 |
22 | for(int t = 0; t < nTime; t++) {
23 | #pragma omp parallel for
24 | for(int y = 0; y < nY; y++) {
25 | for(int x = 0; x < nX; x++) {
26 | for(int e = 0; e < nEns; e++) {
27 | if(t == 0) {
28 | (*fieldsAcc[t])(y, x, e) = 0;
29 | }
30 | else {
31 | float previous = (*fieldsAcc[t - 1])(y, x, e);
32 | float current = (*fields[t])(y, x, e);
33 | if(Util::isValid(current) && Util::isValid(previous)) {
34 | (*fieldsAcc[t])(y, x, e) = current + previous;
35 | }
36 | else {
37 | (*fieldsAcc[t])(y, x, e) = Util::MV;
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
44 | iFile.addField(fieldsAcc[t], mVariable, t);
45 | }
46 | return true;
47 | }
48 | std::string CalibratorAccumulate::description(bool full) {
49 | std::stringstream ss;
50 | ss << Util::formatDescription("-c accumulate","Accumlates a variable over time") << std::endl;
51 | return ss.str();
52 | }
53 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Accumulate.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_ACCUMULATE_H
2 | #define CALIBRATOR_ACCUMULATE_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | // Accumlates a certain variable
7 | class CalibratorAccumulate : public Calibrator {
8 | public:
9 | CalibratorAccumulate(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "accumulate";};
12 | bool requiresParameterFile() const { return false;};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | };
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Altitude.cpp:
--------------------------------------------------------------------------------
1 | #include "Altitude.h"
2 | #include
3 | #include "../Util.h"
4 | #include "../File/File.h"
5 | #include "../ParameterFile/ParameterFile.h"
6 | CalibratorAltitude::CalibratorAltitude(const Variable& iVariable, const Options& iOptions) :
7 | Calibrator(iVariable, iOptions) {
8 | iOptions.check();
9 | }
10 | bool CalibratorAltitude::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
11 | if(!iParameterFile->isLocationDependent()) {
12 | Util::error("Cannot use a location independent parameter file to update the altitudes");
13 | }
14 | int nLat = iFile.getNumY();
15 | int nLon = iFile.getNumX();
16 | vec2 lats = iFile.getLats();
17 | vec2 lons = iFile.getLons();
18 | vec2 elevs = iFile.getElevs();
19 |
20 | #pragma omp parallel for
21 | for(int i = 0; i < nLat; i++) {
22 | for(int j = 0; j < nLon; j++) {
23 | Location loc(Util::MV, Util::MV, Util::MV);
24 | iParameterFile->getNearestLocation(0, Location(lats[i][j], lons[i][j], elevs[i][j]), loc);
25 | elevs[i][j] = loc.elev();
26 | }
27 | }
28 | iFile.setElevs(elevs);
29 | return true;
30 | }
31 |
32 | std::string CalibratorAltitude::description(bool full) {
33 | std::stringstream ss;
34 | if(full)
35 | ss << Util::formatDescription("-c altitude", "Changes the altitudes to the altitudes in the parameter file. If the file does not have an altitude field, then a new one is not created.") << std::endl;
36 | else
37 | ss << Util::formatDescription("-c altitude", "Changes the altitudes to the altitudes in the parameter file") << std::endl;
38 | return ss.str();
39 | }
40 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Altitude.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_ALTITUDE_H
2 | #define CALIBRATOR_ALTITUDE_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Changes the altitudes in iFile to the altitudes in the parameter file
8 | class CalibratorAltitude : public Calibrator {
9 | public:
10 | CalibratorAltitude(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "altitude";};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | };
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Bct.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_BCT_H
2 | #define CALIBRATOR_BCT_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | class ParameterFile;
7 | class Parameters;
8 |
9 | //! Ensemble calibration using a Box-Cox t-distribution. Its predictors are:
10 | //! - ensemble mean
11 | //! - ensemble standard deviation
12 | //! Designed for windspeed
13 | class CalibratorBct : public Calibrator {
14 | public:
15 | CalibratorBct(const Variable& iMainPredictor, const Options& iOptions);
16 | static float getInvCdf(float iQuantile, float iEnsMean, float iEnsStd, const Parameters& iParameters);
17 |
18 | static std::string description(bool full=true);
19 | std::string name() const {return "bct";};
20 | private:
21 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
22 | float mMaxEnsMean;
23 | };
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Calibrator.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_H
2 | #define CALIBRATOR_H
3 | #include
4 | #include
5 | #include "../Scheme.h"
6 | #include "../Parameters.h"
7 | #include "../Field.h"
8 | #include "../Variable.h"
9 |
10 | typedef std::vector Ens;
11 | typedef std::pair ObsEns;
12 | typedef std::pair ObsEnsField;
13 | class File;
14 | class Options;
15 | class ParameterFile;
16 | class Grid;
17 |
18 | //! Abstract calibration class
19 | class Calibrator : public Scheme {
20 | public:
21 | //! The calibrator does not free the memory of iParameterFile
22 | Calibrator(const Variable& iVariable, const Options& iOptions);
23 | virtual ~Calibrator() {};
24 | //! \brief Calibrate one or more fields in iFile
25 | //! @return true if calibration was successful, false otherwise
26 | bool calibrate(File& iFile, const ParameterFile* iParameterFile=NULL) const;
27 |
28 | //! Instantiates a calibrator with name iName
29 | static Calibrator* getScheme(std::string iName, Variable iVariable, const Options& iOptions);
30 |
31 | //! \brief Ensure that values in iAfter are in the same order as in iBefore.
32 | //! If missing values are encountered in iBefore or iAfter, then iAfter is left unchanged.
33 | //! If the sizes are different, then iAfter is left unchanged.
34 | static void shuffle(const std::vector& iBefore, std::vector& iAfter);
35 |
36 | //! Returns the name of this calibrator
37 | virtual std::string name() const = 0;
38 |
39 | static std::string getDescriptions(bool full=true);
40 |
41 | virtual Parameters train(const std::vector& iData) const;
42 | // Defaults to using the regular train method
43 | virtual Parameters train(const std::vector& iData, const Grid& iObsGrid, const Grid& iEnsGrid, int iIobs, int iJobs, int iIEns, int iJEns) const;
44 |
45 | // Does this calibrator require a parameter file?
46 | virtual bool requiresParameterFile() const { return true;};
47 | Options getOptions() const;
48 | protected:
49 | virtual bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const = 0;
50 | Variable mVariable;
51 | private:
52 | Options mOptions;
53 | };
54 | // #include "Wind.h"
55 | #include "Accumulate.h"
56 | #include "Altitude.h"
57 | #include "Bct.h"
58 | #include "Cloud.h"
59 | #include "Coastal.h"
60 | #include "Deaccumulate.h"
61 | #include "DiagnoseHumidity.h"
62 | #include "DiagnoseWind.h"
63 | #include "Gaussian.h"
64 | #include "Kriging.h"
65 | #include "Mask.h"
66 | #include "Neighbourhood.h"
67 | #include "Oi.h"
68 | #include "Override.h"
69 | #include "Phase.h"
70 | #include "Qc.h"
71 | #include "Qnh.h"
72 | #include "Qq.h"
73 | #include "Regression.h"
74 | #include "Sort.h"
75 | #include "Temperature.h"
76 | #include "Threshold.h"
77 | #include "WindDirection.h"
78 | #include "Window.h"
79 | #include "Zaga.h"
80 | #endif
81 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Cloud.cpp:
--------------------------------------------------------------------------------
1 | #include "Cloud.h"
2 | #include "../Util.h"
3 | #include "../File/File.h"
4 | CalibratorCloud::CalibratorCloud(const Variable& iVariable, const Options& iOptions) :
5 | Calibrator(iVariable, iOptions),
6 | mValue(1),
7 | mPrecipVariable("") {
8 | iOptions.getRequiredValue("precipVariable", mPrecipVariable);
9 | iOptions.getValue("value", mValue);
10 | iOptions.check();
11 | }
12 | bool CalibratorCloud::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
13 | int nLat = iFile.getNumY();
14 | int nLon = iFile.getNumX();
15 | int nEns = iFile.getNumEns();
16 | int nTime = iFile.getNumTime();
17 |
18 | // Loop over offsets
19 | for(int t = 0; t < nTime; t++) {
20 | const Field& precip = *iFile.getField(mPrecipVariable, t);
21 | Field& cloud = *iFile.getField(mVariable, t);
22 |
23 | // TODO: Figure out which cloudless members to use. Ideally, if more members
24 | // need precip, we should pick members that already have clouds, so that we minimize
25 | // our effect on the cloud cover field.
26 |
27 | #pragma omp parallel for
28 | for(int i = 0; i < nLat; i++) {
29 | for(int j = 0; j < nLon; j++) {
30 | // Turn on clouds if needed, i.e don't allow a member to
31 | // have precip without cloud cover.
32 | for(int e = 0; e < nEns; e++) {
33 | float currPrecip = precip(i,j,e);
34 | float currCloud = cloud(i,j,e);
35 | if(Util::isValid(currPrecip) && Util::isValid(currCloud)) {
36 | cloud(i,j,e) = currCloud;
37 | if(currPrecip > 0 && currCloud < mValue) {
38 | cloud(i,j,e) = mValue;
39 | }
40 | }
41 | }
42 | }
43 | }
44 | }
45 | return true;
46 | }
47 | std::string CalibratorCloud::description(bool full) {
48 | std::stringstream ss;
49 | if(full) {
50 | ss << Util::formatDescription("-c cloud", "Ensure a minimum cloud cover value precipitation is present") << std::endl;
51 | ss << Util::formatDescription(" precipVariable=undef", "Name of precipitation variable") << std::endl;
52 | ss << Util::formatDescription(" value=1", "Minimum cloud cover value allowed") << std::endl;
53 | }
54 | else
55 | ss << Util::formatDescription("-c cloud", "Ensure clouds when precip is present") << std::endl;
56 | return ss.str();
57 | }
58 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Cloud.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_CLOUD_H
2 | #define CALIBRATOR_CLOUD_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | //! Ensures that if a member has precip it also has full cloud cover
7 | class CalibratorCloud : public Calibrator {
8 | public:
9 | CalibratorCloud(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "cloud";};
12 | bool requiresParameterFile() const { return false;};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | std::string mPrecipVariable;
16 | float mValue;
17 | };
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Coastal.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_COASTAL_H
2 | #define CALIBRATOR_COASTAL_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 | class Grid;
7 |
8 | class CalibratorCoastal : public Calibrator {
9 | public:
10 | CalibratorCoastal(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "coastal";};
13 | Parameters train(const std::vector& iData, const Grid& iObsGrid, const Grid& iEnsGrid, int iIobs, int iJobs, int iIEns, int iJEns) const;
14 | private:
15 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
16 | int mSearchRadius;
17 | float mMinLafDiff;
18 | bool mUseNN;
19 | };
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Deaccumulate.cpp:
--------------------------------------------------------------------------------
1 | #include "Deaccumulate.h"
2 | #include "../Util.h"
3 | #include "../File/File.h"
4 | CalibratorDeaccumulate::CalibratorDeaccumulate(const Variable& iVariable, const Options& iOptions) :
5 | mWindow(1),
6 | Calibrator(iVariable, iOptions) {
7 | iOptions.getValue("window", mWindow);
8 | iOptions.check();
9 | }
10 | bool CalibratorDeaccumulate::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
11 | int nY = iFile.getNumY();
12 | int nX = iFile.getNumX();
13 | int nEns = iFile.getNumEns();
14 | int nTime = iFile.getNumTime();
15 |
16 | // Get all fields
17 | std::vector fields(nTime);
18 | std::vector fieldsAcc(nTime);
19 | for(int t = 0; t < nTime; t++) {
20 | fieldsAcc[t] = iFile.getField(mVariable, t);
21 | fields[t] = iFile.getEmptyField();
22 | }
23 |
24 | for(int t = 0; t < nTime; t++) {
25 | #pragma omp parallel for
26 | for(int y = 0; y < nY; y++) {
27 | for(int x = 0; x < nX; x++) {
28 | for(int e = 0; e < nEns; e++) {
29 | if(t < mWindow) {
30 | (*fields[t])(y, x, e) = Util::MV;
31 | }
32 | else {
33 | float previous = (*fieldsAcc[t - mWindow])(y, x, e);
34 | float current = (*fieldsAcc[t])(y, x, e);
35 | if(Util::isValid(current) && Util::isValid(previous)) {
36 | (*fields[t])(y, x, e) = current - previous;
37 | }
38 | else {
39 | (*fields[t])(y, x, e) = Util::MV;
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
46 | iFile.addField(fields[t], mVariable, t);
47 | }
48 | return true;
49 | }
50 | std::string CalibratorDeaccumulate::description(bool full) {
51 | std::stringstream ss;
52 | ss << Util::formatDescription("-c deaccumulate","Deaccumlates a variable over time.") << std::endl;
53 | return ss.str();
54 | }
55 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Deaccumulate.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_DEACCUMULATE_H
2 | #define CALIBRATOR_DEACCUMULATE_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | // Deaccumlates a certain variable
7 | class CalibratorDeaccumulate : public Calibrator {
8 | public:
9 | CalibratorDeaccumulate(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "deaccumulate";};
12 | bool requiresParameterFile() const { return false;};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | int mWindow;
16 | };
17 | #endif
18 |
--------------------------------------------------------------------------------
/src/client/Calibrator/DiagnoseHumidity.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_DIAGNOSE_HUMIDITY_H
2 | #define CALIBRATOR_DIAGNOSE_HUMIDITY_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | class CalibratorDiagnoseHumidity : public Calibrator {
7 | public:
8 | CalibratorDiagnoseHumidity(const Variable& iVariable, const Options& iOptions);
9 | std::string name() const {return "diagnoseHumidity";};
10 | bool requiresParameterFile() const { return false;};
11 | static std::string description(bool full=true);
12 | // Temperature in K, RH in [0,1], Returns TD in K
13 | static float computeDewpoint(float iTemperature, float iRelativeHumidity);
14 | // Temperatures in K, Returns RH in [0,1]
15 | static float computeRh(float iTemperature, float iDewPointTemperature);
16 | //! Compute wetbulb temperature
17 | //! @param iTemperature Temperature in K
18 | //! @param iPressure Pressure in pa
19 | //! @param iRelativeHumidity Relative humidity (out of 1)
20 | //! @return Wetbulb temperature in K
21 | static float computeWetbulb(float iTemperature, float iPressure, float iRelativeHumidity);
22 | private:
23 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
24 | static float mEwt[41];
25 | std::string mTemperature;
26 | std::string mRh;
27 | std::string mDewpoint;
28 | std::string mPressure;
29 | std::string mCompute;
30 | };
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/client/Calibrator/DiagnoseWind.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_DIAGNOSE_WIND_H
2 | #define CALIBRATOR_DIAGNOSE_WIND_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | class CalibratorDiagnoseWind : public Calibrator {
7 | public:
8 | CalibratorDiagnoseWind(const Variable& iVariable, const Options& iOptions);
9 | std::string name() const {return "diagnoseWind";};
10 | bool requiresParameterFile() const { return false;};
11 | static std::string description(bool full=true);
12 | private:
13 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
14 | std::string mX;
15 | std::string mY;
16 | std::string mSpeed;
17 | std::string mDirection;
18 | std::string mCompute;
19 | };
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Gaussian.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_GAUSSIAN_H
2 | #define CALIBRATOR_GAUSSIAN_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 | #include
6 | #include
7 |
8 | class ParameterFile;
9 | class Parameters;
10 |
11 | //! Ensemble calibration using zero-adjusted gamma distribution. Its predictors are:
12 | //! - ensemble mean
13 | //! - ensemble fraction
14 | //! Designed for precip
15 | class CalibratorGaussian : public Calibrator {
16 | public:
17 | CalibratorGaussian(const Variable& iVariable, const Options& iOptions);
18 | static float getInvCdf(float iQuantile, float iEnsMean, float iEnsSpread, const Parameters& iParameters);
19 | static float getCdf(float iThreshold, float iEnsMean, float iEnsSpread, const Parameters& iParameters);
20 | static float getPdf(float iThreshold, float iEnsMean, float iEnsSpread, const Parameters& iParameters);
21 |
22 | static std::string description(bool full=true);
23 | std::string name() const {return "gaussian";};
24 | Parameters train(const std::vector& iData) const;
25 | private:
26 | static double my_f(const gsl_vector *v, void *params);
27 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
28 | int mNeighbourhoodSize;
29 | float mLogLikelihoodTolerance;
30 | static const int mNumParameters = 2;
31 | };
32 | #endif
33 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Kriging.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_KRIGING_H
2 | #define CALIBRATOR_KRIGING_H
3 | #include "Calibrator.h"
4 | #include "../ParameterFile/ParameterFile.h"
5 | class Obs;
6 | class Forecast;
7 | class Parameters;
8 |
9 | class CalibratorKriging : public Calibrator {
10 | public:
11 | CalibratorKriging(const Variable& iVariable, const Options& iOptions);
12 | static std::string description(bool full=true);
13 | float calcCovar(const Location& loc1, const Location& loc2) const;
14 | enum Type {
15 | TypeCressman = 10,
16 | TypeBarnes = 20
17 | };
18 | //! Compute the bias at the training point
19 | Parameters train(const std::vector& iData) const;
20 | private:
21 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
22 |
23 | float mRadius;
24 | float mMaxElevDiff;
25 | float mEfoldDist;
26 | std::string name() const {return "kriging";};
27 | File* mPrevious;
28 | std::string mAuxVariable;
29 | float mLowerThreshold;
30 | float mUpperThreshold;
31 | Type mKrigingType;
32 | bool mUseApproxDistance;
33 | Util::Operator mOperator;
34 | bool mCrossValidate;
35 | int mWindow;
36 | };
37 | #endif
38 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Mask.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_MASK_H
2 | #define CALIBRATOR_MASK_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Sets gridpoints that are far away from parameter points to missing
8 | class CalibratorMask : public Calibrator {
9 | public:
10 | CalibratorMask(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "mask";};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | bool mUseNearestOnly;
16 | bool mKeep;
17 | };
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Neighbourhood.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_NEIGHBOURHOOD_H
2 | #define CALIBRATOR_NEIGHBOURHOOD_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 | #include "../Util.h"
6 |
7 | class ParameterFile;
8 | class Parameters;
9 |
10 | //! Applies a statistical operator to a neighbourhood
11 | class CalibratorNeighbourhood : public Calibrator {
12 | public:
13 | CalibratorNeighbourhood(const Variable& iVariable, const Options& iOptions);
14 | static std::string description(bool full=true);
15 | std::string name() const {return "neighbourhood";};
16 | bool requiresParameterFile() const { return false;};
17 | void calibrateField(const Field& iInput, Field& iOutput, const Parameters* iParameters=NULL) const;
18 | private:
19 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
20 | int mRadius;
21 | Util::StatType mStatType;
22 | float mQuantile;
23 | bool mFast;
24 | bool mApprox;
25 | int numMissingValues(const Field& iField, int iEnsIndex) const;
26 | };
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Oi.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_OI_H
2 | #define CALIBRATOR_OI_H
3 | #include
4 | #include "Calibrator.h"
5 | #include "../ParameterFile/ParameterFile.h"
6 | class Obs;
7 | class Forecast;
8 | class Parameters;
9 |
10 | class CalibratorOi : public Calibrator {
11 | public:
12 | CalibratorOi(Variable iVariable, const Options& iOptions);
13 | // Compute rho. A rho of 0 is returned if a vertical distance is missing when the
14 | // vertical scale is defined.
15 | enum RhoType {RhoTypeGaussian, RhoTypeSoar};
16 | float calcRho(float iHdist, float iVdist, float iLdist, RhoType iType=RhoTypeGaussian) const;
17 | static std::string description(bool full=true);
18 | std::string name() const {return "oi";};
19 | private:
20 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
21 | enum Type {TypeTemperature, TypePrecipitation};
22 | enum TransformType {TransformTypeNone, TransformTypeBoxCox};
23 | float mVLength;
24 | float mHLength;
25 | float mHLengthC;
26 | float mWLength;
27 | float mMu;
28 | float mGamma;
29 | std::string mBiasVariable;
30 | int mMaxLocations;
31 | float mSigma;
32 | float mSigmaC;
33 | float mDelta;
34 | std::string mDeltaVariable;
35 | std::string mNumVariable;
36 | float mC;
37 | float mEpsilonC;
38 | float mEpsilon;
39 | int mX;
40 | int mY;
41 | float mMinRho;
42 | float mMaxBytes;
43 | int mMinValidEns;
44 | bool mSaveDiff;
45 | float mElevGradient;
46 | bool mExtrapolate;
47 | float mWMin;
48 | float mNewDeltaVar;
49 | float mMaxElevDiff;
50 | bool mDiagnose;
51 | bool mLandOnly;
52 | std::string mDiaFile;
53 | bool mUseEns;
54 | typedef arma::mat mattype;
55 | typedef arma::vec vectype;
56 | typedef arma::cx_mat cxtype;
57 | float mLambda;
58 | bool mCrossValidate;
59 | Type mType;
60 | TransformType mTransformType;
61 | float calcDelta(float iOldDelta, const vec2& iY) const;
62 | float transform(float iValue) const;
63 | float invTransform(float iValue) const;
64 | RhoType mRhoType;
65 | float mBoxCoxThreshold;
66 | };
67 | #endif
68 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Override.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_OVERRIDE_H
2 | #define CALIBRATOR_OVERRIDE_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Overrides values from parameter file into gridpoints
8 | class CalibratorOverride : public Calibrator {
9 | public:
10 | CalibratorOverride(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "override";};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | int mRadius;
16 | float mMaxElevDiff;
17 | };
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Phase.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_PHASE_H
2 | #define CALIBRATOR_PHASE_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 |
6 | //! Creates a precipitation-phase field
7 | class CalibratorPhase : public Calibrator {
8 | public:
9 | CalibratorPhase(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "phase";};
12 |
13 | //! Precipitation phase
14 | enum Phase {
15 | PhaseNone = 0,
16 | PhaseRain = 1,
17 | PhaseSleet = 2,
18 | PhaseSnow = 3
19 | };
20 | private:
21 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
22 | float mMinPrecip;
23 | float mSnowThreshold;
24 | float mRainThreshold;
25 | std::string mTemperatureVariable;
26 | std::string mPrecipitationVariable;
27 | };
28 | #endif
29 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Qc.cpp:
--------------------------------------------------------------------------------
1 | #include "Qc.h"
2 | #include
3 | #include
4 | #include
5 | #include "../Util.h"
6 | #include "../File/File.h"
7 | CalibratorQc::CalibratorQc(const Variable& iVariable, const Options& iOptions):
8 | Calibrator(iVariable, iOptions),
9 | mMin(Util::MV),
10 | mMax(Util::MV) {
11 | iOptions.getValue("min", mMin);
12 | iOptions.getValue("max", mMax);
13 | if(!Util::isValid(mMin) && !Util::isValid(mMax))
14 | Util::warning("CalibratorQc: both 'min' and 'max' are missing, therefore no correction is applied.");
15 | iOptions.check();
16 | }
17 |
18 | bool CalibratorQc::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
19 | int nLat = iFile.getNumY();
20 | int nLon = iFile.getNumX();
21 | int nEns = iFile.getNumEns();
22 | int nTime = iFile.getNumTime();
23 |
24 | // Loop over offsets
25 | for(int t = 0; t < nTime; t++) {
26 | Field& field = *iFile.getField(mVariable, t);
27 |
28 | #pragma omp parallel for
29 | for(int i = 0; i < nLat; i++) {
30 | for(int j = 0; j < nLon; j++) {
31 |
32 | for(int e = 0; e < nEns; e++) {
33 | float value = field(i,j,e);
34 | if(Util::isValid(value)) {
35 | if(Util::isValid(mMin) && value < mMin)
36 | value = mMin;
37 | else if(Util::isValid(mMax) && value > mMax)
38 | value = mMax;
39 | field(i,j,e) = value;
40 | }
41 | }
42 | }
43 | }
44 | }
45 | return true;
46 | }
47 |
48 | std::string CalibratorQc::description(bool full) {
49 | std::stringstream ss;
50 | if(full) {
51 | ss << Util::formatDescription("-c qc", "Apply quality control, ensuring the values are within the bounds of the variable. If the original value is missing, no correction is applied.") << std::endl;
52 | ss << Util::formatDescription(" min=undef", "Force the minimum allowed value. If not provided, don't force a minimum.") << std::endl;
53 | ss << Util::formatDescription(" max=undef", "Force the maximum allowed value. If not provided, don't force a maximum.") << std::endl;
54 | }
55 | else
56 | ss << Util::formatDescription("-c qc", "Ensures values are within bounds") << std::endl;
57 | return ss.str();
58 | }
59 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Qc.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_QC_H
2 | #define CALIBRATOR_QC_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 | #include "../Util.h"
6 |
7 | class ParameterFile;
8 | class Parameters;
9 |
10 | //! Applies a quality control adjustment.
11 | //! Ensures that all values are within an appropriate range.
12 | class CalibratorQc : public Calibrator {
13 | public:
14 | CalibratorQc(const Variable& iVariable, const Options& iOptions);
15 | static std::string description(bool full=true);
16 | std::string name() const {return "qc";};
17 | bool requiresParameterFile() const { return false;};
18 | private:
19 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
20 | float mMin;
21 | float mMax;
22 | };
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Qnh.cpp:
--------------------------------------------------------------------------------
1 | #include "Qnh.h"
2 | #include "../Util.h"
3 | #include "../File/File.h"
4 | #include
5 | CalibratorQnh::CalibratorQnh(const Variable& iVariable, const Options& iOptions) :
6 | Calibrator(iVariable, iOptions) {
7 | iOptions.getRequiredValue("pressureVariable", mPressureVariable);
8 | iOptions.check();
9 | }
10 | bool CalibratorQnh::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
11 | int nLat = iFile.getNumY();
12 | int nLon = iFile.getNumX();
13 | int nEns = iFile.getNumEns();
14 | int nTime = iFile.getNumTime();
15 |
16 | vec2 lats = iFile.getLats();
17 | vec2 lons = iFile.getLons();
18 | vec2 elevs = iFile.getElevs();
19 |
20 | // Loop over offsets
21 | for(int t = 0; t < nTime; t++) {
22 | const Field& input = *iFile.getField(mPressureVariable, t);
23 | Field& output = *iFile.getField(mVariable, t);
24 |
25 | #pragma omp parallel for
26 | for(int i = 0; i < nLat; i++) {
27 | for(int j = 0; j < nLon; j++) {
28 | float currElev = elevs[i][j];
29 | for(int e = 0; e < nEns; e++) {
30 | float currPressure = input(i,j,e);
31 | if(Util::isValid(currPressure) && Util::isValid(currElev)) {
32 | output(i,j,e) = calcQnh(currElev, currPressure);
33 | }
34 | }
35 | }
36 | }
37 | }
38 | return true;
39 | }
40 | std::string CalibratorQnh::description(bool full) {
41 | std::stringstream ss;
42 | if(full)
43 | ss << Util::formatDescription("-c qnh", "Adjusts the surface pressure down to sea-level based on a standard atmosphere (ICAO) producing the QNH variable.") << std::endl;
44 | else
45 | ss << Util::formatDescription("-c qnh", "Compute QNH") << std::endl;
46 | return ss.str();
47 | }
48 | float CalibratorQnh::calcQnh(float iElev, float iPressure) {
49 | if(iPressure == 0)
50 | return 0;
51 | else if(Util::isValid(iElev) && Util::isValid(iPressure)) {
52 | float g = 9.80665; // m/s2
53 | float T0 = 288.15; // K
54 | float L = 0.0065; // K/m
55 | // Method 1:
56 | // float dElev = 0 - iElev;
57 | // float M = 0.0289644; // kg/mol
58 | // float R = 8.31447; // J/(mol•K)
59 | // float cp = 1007; // J/(kg•K)
60 | // float constant = -g*M/R/T0;
61 | // float qnh = iPressure * pow(1 - L*dElev/T0, g*M/R/L);
62 |
63 | // Method 2: http://www.hochwarth.com/misc/AviationCalculator.html
64 | float CRGas = 287.053; // [m^2/(s^2*K)] = [J/(kg*K)]
65 | float p0 = 101325; // pa
66 | float qnh = p0*pow(pow((iPressure/p0), (CRGas*L)/g) + (iElev*L)/T0, g/(CRGas*L));
67 | return qnh;
68 | }
69 | else {
70 | return Util::MV;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Qnh.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_QNH_H
2 | #define CALIBRATOR_QNH_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | //! Creates the QNH field by using surface pressure
7 | class CalibratorQnh : public Calibrator {
8 | public:
9 | CalibratorQnh(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "qnh";};
12 | static float calcQnh(float iElev, float iPressure);
13 | bool requiresParameterFile() const { return false;};
14 | private:
15 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
16 | std::string mPressureVariable;
17 | };
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Qq.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_QQ_H
2 | #define CALIBRATOR_QQ_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 |
6 | //! Applies polynomial regression to forecasts
7 | class CalibratorQq : public Calibrator {
8 | public:
9 | CalibratorQq(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "qq";};
12 | Parameters train(const std::vector& iData) const;
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | float mLowerQuantile;
16 | float mUpperQuantile;
17 | std::vector mQuantiles;
18 | struct ExtrapolationPolicy {
19 | enum Policy {
20 | OneToOne = 0,
21 | MeanSlope = 10,
22 | NearestSlope = 20,
23 | Zero = 30,
24 | };
25 | };
26 | ExtrapolationPolicy::Policy mPolicy;
27 | // Separate the vector of obs,fcst,obs,fcst,... into separate vectors
28 | void separate(const Parameters& iParameters, std::vector& iObs, std::vector& iFcst) const;
29 | std::vector mExtraObs;
30 | std::vector mExtraFcst;
31 | int mX;
32 | int mY;
33 | };
34 | #endif
35 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Regression.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_REGRESSION_H
2 | #define CALIBRATOR_REGRESSION_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Applies polynomial regression to forecasts
8 | class CalibratorRegression : public Calibrator {
9 | public:
10 | CalibratorRegression(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "regression";};
13 | Parameters train(const std::vector& iData) const;
14 | private:
15 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
16 | int mOrder;
17 | bool mIntercept;
18 | std::vector mVariables;
19 | };
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Sort.cpp:
--------------------------------------------------------------------------------
1 | #include "Sort.h"
2 | #include
3 | #include "../Util.h"
4 | #include "../File/File.h"
5 | #include "../ParameterFile/ParameterFile.h"
6 | #include "../Downscaler/Pressure.h"
7 | CalibratorSort::CalibratorSort(const Variable& iVariable, const Options& iOptions) :
8 | Calibrator(iVariable, iOptions) {
9 | iOptions.check();
10 | }
11 | bool CalibratorSort::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
12 | int nLat = iFile.getNumY();
13 | int nLon = iFile.getNumX();
14 | int nEns = iFile.getNumEns();
15 | int nTime = iFile.getNumTime();
16 | vec2 lats = iFile.getLats();
17 | vec2 lons = iFile.getLons();
18 | vec2 elevs = iFile.getElevs();
19 |
20 | // Loop over offsets
21 | for(int t = 0; t < nTime; t++) {
22 | Field& field = *iFile.getField(mVariable, t);
23 |
24 | #pragma omp parallel for
25 | for(int i = 0; i < nLat; i++) {
26 | for(int j = 0; j < nLon; j++) {
27 | std::vector values = field(i,j);
28 | std::sort(values.begin(), values.end());
29 |
30 | // Create a new array with all the missing values
31 | // at the end
32 | std::vector missingLast(nEns, Util::MV);
33 | int counter = 0;
34 | for(int e = 0; e < nEns; e++) {
35 | if(Util::isValid(values[e])) {
36 | missingLast[counter] = values[e];
37 | counter++;
38 | }
39 | }
40 | for(int e = 0; e < nEns; e++) {
41 | field(i,j,e) = missingLast[e];
42 | }
43 | }
44 | }
45 | }
46 | return true;
47 | }
48 |
49 | std::string CalibratorSort::description(bool full) {
50 | std::stringstream ss;
51 | if(full)
52 | ss << Util::formatDescription("-c sort", "Sorts ensemble members from lowest to highest. Any missing members are placed last.") << std::endl;
53 | else
54 | ss << Util::formatDescription("-c sort", "Sorts ensemble members from lowest to highest") << std::endl;
55 | return ss.str();
56 | }
57 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Sort.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_SORT_H
2 | #define CALIBRATOR_SORT_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Applies polynomial regression to forecasts
8 | class CalibratorSort : public Calibrator {
9 | public:
10 | CalibratorSort(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "sort";};
13 | bool requiresParameterFile() const { return false;};
14 | private:
15 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
16 | };
17 | #endif
18 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Temperature.cpp:
--------------------------------------------------------------------------------
1 | #include "Calibrator.h"
2 | #include
3 | #include
4 | #include
5 | #include "../Util.h"
6 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Temperature.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_TEMPERATURE_H
2 | #define CALIBRATOR_TEMPERATURE_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 |
6 | class CalibratorTemperature : public Calibrator {
7 | public:
8 | CalibratorTemperature(const Variable& iVariable, const Options& iOptions);
9 | static std::string description(bool full=true);
10 | std::string name() const {return "temperature";};
11 | private:
12 | bool calibrateCore(const File& iFile, const ParameterFile* iParameterFile) const;
13 | };
14 | #endif
15 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Threshold.cpp:
--------------------------------------------------------------------------------
1 | #include "Threshold.h"
2 | #include
3 | #include "../Util.h"
4 | #include "../File/File.h"
5 | #include "../ParameterFile/ParameterFile.h"
6 | #include "../Downscaler/Pressure.h"
7 | CalibratorThreshold::CalibratorThreshold(const Variable& iVariable, const Options& iOptions) :
8 | Calibrator(iVariable, iOptions) {
9 | iOptions.getRequiredValues("thresholds", mThresholds);
10 | iOptions.getRequiredValues("values", mValues);
11 | if(!iOptions.getValues("equals", mEquals)) {
12 | mEquals.resize(mThresholds.size(), 0);
13 | }
14 | if(mValues.size() != mThresholds.size() + 1) {
15 | std::stringstream ss;
16 | ss << "Length of 'values' must be one longer than the length of 'thresholds'";
17 | Util::error(ss.str());
18 | }
19 | if(mEquals.size() != mThresholds.size()) {
20 | std::stringstream ss;
21 | ss << "Length of 'equals' must be the same as the length of 'thresholds'";
22 | Util::error(ss.str());
23 | }
24 | iOptions.check();
25 | }
26 | bool CalibratorThreshold::calibrateCore(File& iFile, const ParameterFile* iParameterFile) const {
27 | int nEns = iFile.getNumEns();
28 | int nTime = iFile.getNumTime();
29 | int nX = iFile.getNumX();
30 | int nY = iFile.getNumY();
31 | vec2 elevs = iFile.getElevs();
32 | int nThresholds = mThresholds.size();
33 |
34 | for(int t = 0; t < nTime; t++) {
35 | const FieldPtr field = iFile.getField(mVariable, t);
36 | for(int e = 0; e < nEns; e++) {
37 | for(int y = 0; y < nY; y++) {
38 | for(int x = 0; x < nX; x++) {
39 | float value = (*field)(y, x, e);
40 | if(Util::isValid(value)) {
41 | (*field)(y, x, e) = mValues[nThresholds];
42 | for(int p = 0; p < nThresholds; p++) {
43 | if(value < mThresholds[p]) {
44 | (*field)(y, x, e) = mValues[p];
45 | break;
46 | }
47 | else if(value == mThresholds[p] && mEquals[p] == 1) {
48 | (*field)(y, x, e) = mValues[p];
49 | break;
50 | }
51 | }
52 | }
53 | }
54 | }
55 | }
56 | }
57 | return true;
58 | }
59 |
60 | std::string CalibratorThreshold::description(bool full) {
61 | std::stringstream ss;
62 | ss << Util::formatDescription("-c threshold", "Apply thresholding to the field, converting ranges into specified values.") << std::endl;
63 | if(full) {
64 | ss << Util::formatDescription(" thresholds=required", "List of thresholds (x1, x2, x3, ..., xn). Must be sorted.") << std::endl;
65 | ss << Util::formatDescription(" values=required", "List of values to set the ranges to. The first value is used for field values below the first threshold. Must have length one longer than threhsolds") << std::endl;
66 | ss << Util::formatDescription(" equals=undef", "Should the intervals include the upper threshold? One number for each threshold. 1 means yes, 0 means no.") << std::endl;
67 | }
68 | return ss.str();
69 | }
70 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Threshold.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_THRESHOLD_H
2 | #define CALIBRATOR_THRESHOLD_H
3 | #include "Calibrator.h"
4 | class ParameterFile;
5 | class Parameters;
6 |
7 | //! Thresholds values from parameter file into gridpoints
8 | class CalibratorThreshold : public Calibrator {
9 | public:
10 | CalibratorThreshold(const Variable& iVariable, const Options& iOptions);
11 | static std::string description(bool full=true);
12 | std::string name() const {return "threshold";};
13 | bool requiresParameterFile() const { return false;};
14 | private:
15 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
16 | std::vector mThresholds;
17 | std::vector mValues;
18 | std::vector mEquals;
19 | };
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/client/Calibrator/WindDirection.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_WIND_DIRECTION_H
2 | #define CALIBRATOR_WIND_DIRECTION_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | class ParameterFile;
7 | class Parameters;
8 |
9 | //! Multiply a variable by a factor based on the wind-direction
10 | //! factor = a + b*sin(dir) + c*cos(dir) + d*sin(2*dir) + e*cos(2*dir)
11 | //! + f*sin(3*dir) + g*cos(3*dir) + h*sin(4*dir) + i*cos(4*dir)
12 | class CalibratorWindDirection : public Calibrator {
13 | public:
14 | CalibratorWindDirection(const Variable& iVariable, const Options& iOptions);
15 | static std::string description(bool full=true);
16 | std::string name() const {return "windDirection";};
17 | //! Get multiplication factor for given wind direction
18 | //! @param iWindDirection in degrees, meteorological wind direction (0 degrees is from North)
19 | static float getFactor(float iWindDirection, const Parameters& iPar);
20 | private:
21 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
22 | std::string mDirectionVariable;
23 | };
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Window.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_WINDOW_H
2 | #define CALIBRATOR_WINDOW_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 |
6 | // Applies a statistical operator to values within a temporal window
7 | class CalibratorWindow : public Calibrator {
8 | public:
9 | CalibratorWindow(const Variable& iVariable, const Options& iOptions);
10 | static std::string description(bool full=true);
11 | std::string name() const {return "window";};
12 | bool requiresParameterFile() const { return false;};
13 | private:
14 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
15 | int mLength;
16 | Util::StatType mStatType;
17 | float mQuantile;
18 | bool mBefore;
19 | bool mKeepMissing;
20 | std::vector mWeights;
21 | enum EdgePolicy {
22 | EdgePolicyCompute = 0,
23 | EdgePolicyMissing = 10
24 | };
25 | EdgePolicy mEdgePolicy;
26 | };
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/client/Calibrator/Zaga.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_ZAGA_H
2 | #define CALIBRATOR_ZAGA_H
3 | #include "Calibrator.h"
4 | #include "../Variable.h"
5 | #include
6 | #include
7 |
8 | class ParameterFile;
9 | class Parameters;
10 |
11 | //! Ensemble calibration using zero-adjusted gamma distribution. Its predictors are:
12 | //! - ensemble mean
13 | //! - ensemble fraction
14 | //! Designed for precip
15 | class CalibratorZaga : public Calibrator {
16 | public:
17 | CalibratorZaga(const Variable& iVariable, const Options& iOptions);
18 | //! Get probability mass at 0 mm (i.e probability of no precipitation)
19 | //! If any input has missing values, the end result is missing
20 | static float getP0(float iEnsMean, float iEnsFrac, const Parameters& iParameters);
21 | //! Get Precipitation amount corresponding to quantile
22 | //! If any input has missing values, the end result is missing
23 | static float getInvCdf(float iQuantile, float iEnsMean, float iEnsFrac, const Parameters& iParameters);
24 | //! Get Precipitation amount corresponding to quantile. If any input has missing values, or
25 | //! iEnsMean < 0 or iEnsFrac is not in [0,1], a missing value is returned.
26 | static float getCdf(float iThreshold, float iEnsMean, float iEnsFrac, const Parameters& iParameters);
27 | static float getPdf(float iThreshold, float iEnsMean, float iEnsFrac, const Parameters& iParameters);
28 |
29 | static std::string description(bool full=true);
30 | std::string name() const {return "zaga";};
31 | Parameters train(const std::vector& iData) const;
32 | private:
33 | bool calibrateCore(File& iFile, const ParameterFile* iParameterFile) const;
34 | static float logLikelihood(float obs, float iEnsMean, float iEnsFrac, const Parameters& iParameters);
35 | static double my_f(const gsl_vector *v, void *params);
36 | // static void my_df(const gsl_vector *v, void *params, gsl_vector *df);
37 | // static void my_fdf(const gsl_vector *x, void *params, double *f, gsl_vector *df);
38 | //! What precip threshold should be used to count members with no precip?
39 | float mFracThreshold;
40 | int mNeighbourhoodSize;
41 | float mPopThreshold;
42 | float mPrecipLowQuantile;
43 | float mPrecipMiddleQuantile;
44 | float mPrecipHighQuantile;
45 | float mMaxEnsMean;
46 | bool m6h;
47 | float mLogLikelihoodTolerance;
48 | std::string mPopVariable;
49 | std::string mLowVariable;
50 | std::string mMiddleVariable;
51 | std::string mHighVariable;
52 | };
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/client/Calibrator/devel/Wind.cpp:
--------------------------------------------------------------------------------
1 | #include "Wind.h"
2 | #include "../Util.h"
3 | #include "../File/File.h"
4 |
5 | CalibratorWind::CalibratorWind(const ParameterFileRegion& iParameterFile) :
6 | Calibrator(),
7 | mParameterFile(iParameterFile) {
8 | }
9 | void CalibratorWind::calibrateCore(File& iFile) const {
10 | int nLat = iFile.getNumLat();
11 | int nLon = iFile.getNumLon();
12 | int nEns = iFile.getNumEns();
13 | int nTime = iFile.getNumTime();
14 |
15 | // Initialize calibrated fields in the output file
16 | std::vector windCals(nTime);
17 | for(int t = 0; t < nTime; t++) {
18 | windCals[t] = iFile.getEmptyField();
19 | }
20 |
21 | // Loop over offsets
22 | for(int t = 0; t < nTime; t++) {
23 | FieldPtr u = iFile.getField(Variable::U, t);
24 | FieldPtr v = iFile.getField(Variable::V, t);
25 |
26 | Field& windCal = *windCals[t];
27 |
28 | // Parallelizable
29 | #pragma omp parallel for
30 | for(int i = 0; i < nLat; i++) {
31 | for(int j = 0; j < nLon; j++) {
32 | Parameters parameters = mParameterFile.getParameters(i, j, t);
33 | for(int e = 0; e < nEns; e++) {
34 | float currU = (*u)[i][j][e];
35 | float currV = (*v)[i][j][e];
36 | if(Util::isValid(currU) && Util::isValid(currV)) {
37 | float dir = getDir(currU, currV);
38 | float speed = getSpeed(currU, currV);
39 | float calSpeed = calibrateLocal(speed, dir, parameters);
40 | windCal[i][j][e] = calSpeed;
41 | }
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 | float CalibratorWind::calibrateLocal(float iSpeed, float iDir, const Parameters& iParameters) const {
49 | return 16.4;
50 | }
51 |
52 | float CalibratorWind::getDir(float iU, float iV) {
53 | return 0;
54 | }
55 | float CalibratorWind::getSpeed(float iU, float iV) {
56 | return 0;
57 | }
58 |
--------------------------------------------------------------------------------
/src/client/Calibrator/devel/Wind.h:
--------------------------------------------------------------------------------
1 | #ifndef CALIBRATOR_WIND_H
2 | #define CALIBRATOR_WIND_H
3 | #include "Calibrator.h"
4 | #include "../ParameterFile.h"
5 |
6 | class CalibratorWind : public Calibrator {
7 | public:
8 | CalibratorWind(const ParameterFileRegion& iParameterFileRegion);
9 | private:
10 | void calibrateCore(File& iFile) const;
11 | static float getDir(float iU, float iV);
12 | static float getSpeed(float iU, float iV);
13 | float calibrateLocal(float iSpeed, float iDir, const Parameters& iParameters) const;
14 | ParameterFileRegion mParameterFile;
15 | };
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/client/Downscaler/Bilinear.h:
--------------------------------------------------------------------------------
1 | #ifndef DOWNSCALER_BILINEAR_H
2 | #define DOWNSCALER_BILINEAR_H
3 | #include