Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added config reader data source #6

Open
wants to merge 4 commits into
base: feature/nwp-emulator
Choose a base branch
from

Conversation

cducher
Copy link

@cducher cducher commented Feb 21, 2025

This data reader uses a configuration to provide data to the emulator. It supports five generation methods (see configuration on README for examples)
These are examples of fields it can generate (grid is N80):
example_1
example_2

@cducher cducher self-assigned this Feb 21, 2025
@codecov-commenter
Copy link

codecov-commenter commented Feb 21, 2025

Codecov Report

Attention: Patch coverage is 0% with 433 lines in your changes missing coverage. Please review.

Project coverage is 24.21%. Comparing base (42b7ea9) to head (32be034).

Files with missing lines Patch % Lines
src/nwp_emulator/config_reader.cc 0.00% 237 Missing ⚠️
src/nwp_emulator/config_reader_funcs.cc 0.00% 170 Missing ⚠️
src/nwp_emulator/config_reader.h 0.00% 16 Missing ⚠️
src/nwp_emulator/nwp_data_provider.cc 0.00% 8 Missing ⚠️
src/nwp_emulator/base_data_reader.h 0.00% 2 Missing ⚠️
Additional details and impacted files
@@                   Coverage Diff                    @@
##           feature/nwp-emulator       #6      +/-   ##
========================================================
- Coverage                 29.46%   24.21%   -5.25%     
========================================================
  Files                        49       52       +3     
  Lines                      1972     2399     +427     
  Branches                    138      249     +111     
========================================================
  Hits                        581      581              
- Misses                     1391     1818     +427     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cducher cducher force-pushed the feature/nwp-emulator-config-source branch from fac6af7 to 576cb67 Compare March 6, 2025 11:42
@cducher cducher force-pushed the feature/nwp-emulator-config-source branch from 576cb67 to 68ec7a8 Compare March 6, 2025 11:45
@cducher cducher changed the title WIP Added config reader data source Added config reader data source Mar 6, 2025
@cducher cducher marked this pull request as ready for review March 6, 2025 11:53
Copy link
Collaborator

@antons-it antons-it left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, nice work! this will make the development/testing of plugins much easier


Here is an example of YAML configuration file you can use to generate model data, which demonstrate the options that each generation function accept:

```yaml
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice and useful configuration example! we could consider having a separate entry for "functions" (at the same level of "fields") where named functions are defined. Then these named functions could be recalled within the fields/levels - to avoid duplications. But this can definitely be another PR

apply:
vortex_rollup:
time_variation: 1.1
u: # no specified levtype means not surface
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is getting u,v from model-level grib output supported?

*
* @return The rectangular area of the map or a null pointer if the whole globe should be considered.
*/
FocusArea* setFocusArea(const eckit::LocalConfiguration& options);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return std::unique_ptr<FocusArea> instead of a raw pointer.

}
}

ConfigReader::~ConfigReader() {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this completely.

ConfigReader(const eckit::PathName& inputPath, size_t rank, size_t root, int stepCountLimit = 100);

/// Makes sure that dynamically allocated memory is freed.
~ConfigReader();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this completely.

fieldConfigStr += ".levels." + levelKey;
}
readerConfig_.get(fieldConfigStr, fieldConfig);
for (const std::string& func : fieldConfig.keys()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An elegant way of doing this would be to create a lookup table of std::string -> std::function .

std::map<std::string, std::function<>> myLookUpTable

translation[1] *= step_;
}
std::vector<double> areaCoords;
FocusArea* focusArea = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you don't have to do this.

}
focusArea = new FocusArea{west, east, south, north};
}
return focusArea;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you can do just focusArea = std::make_unique<FocusArea>(west, east, south, north).


for (size_t i_pt = 0; i_pt < values.size(); i_pt++) {
atlas::PointLonLat p{lonlat(i_pt, atlas::LON), lonlat(i_pt, atlas::LAT)};
if (focusArea != nullptr && !focusArea->contains(p)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (focusArea && ...)

@@ -22,7 +22,9 @@ NWPDataProvider::NWPDataProvider(const DataSourceType& sourceType, const eckit::
dataReader = new GRIBFileReader(inputPath, rank, root);
break;
case DataSourceType::CONFIG:
eckit::Log::info() << "Config source type has not been implemented yet" << std::endl;
eckit::Log::info() << "Emulator will use config as source type from" << inputPath << std::endl;
dataReader = new ConfigReader(inputPath, rank, root);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here too.

@@ -71,6 +73,9 @@ NWPDataProvider::NWPDataProvider(const DataSourceType& sourceType, const eckit::
atlas::grid::Distribution distribution(grid, atlas::util::Config("type", grid.partitioner().getString("type")) |
atlas::util::Config("bands", nprocs_));
fs_ = atlas::functionspace::StructuredColumns(grid, distribution, atlas::util::Config("levels", nlevels));
if (sourceType_ == DataSourceType::CONFIG) {
dynamic_cast<ConfigReader*>(dataReader)->setReaderArea(fs_.lonlat());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps move this to the base class if that is what conceptually makes sense.

@cducher cducher requested a review from dsarmany March 18, 2025 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants