-
Notifications
You must be signed in to change notification settings - Fork 13
Feature/fdb 327 fdb compare #165
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
Open
stefaniereuter
wants to merge
40
commits into
develop
Choose a base branch
from
feature/FDB-327-fdb-compare
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,674
β0
Open
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
b31efd8
added FDB compare to CmakeList tool is WIP and currently only loads tβ¦
stefaniereuter 140be9b
Create FDB from path in tool.cc directly
stefaniereuter 7f471fc
comparison of mars keys
stefaniereuter 7e0d412
can compare FDB but not optimized and exceptiions are missing
stefaniereuter ea7200f
Bitexact Memcmp, bitexact eccodes, data compare numerical
stefaniereuter 1e5404a
move from map to vector in md5compare, add usage exampl and command lβ¦
stefaniereuter 86e5c38
changed the way the mars message keys are compared,added option to igβ¦
stefaniereuter 69e135a
Adding option to ignore and select grib keys
stefaniereuter fa60969
added gribcompare eccodes_detail to allow direct use of detailed check
stefaniereuter 5752bc5
removed annoying debug output
stefaniereuter 14e7b3a
Added eccodes hack for buffer size adaption
stefaniereuter 9009bdb
remove eccodes 'hack' and use grib_string_length instead
stefaniereuter 10b7177
deleted buffer before return to avoid memleak
stefaniereuter 3efbf62
Bugfixes after rebase
stefaniereuter 2bff5dc
CLI improvments
stefaniereuter 564257a
Adding comparison tests
stefaniereuter e59d7ac
Feature, single fdb divergent experiment
stefaniereuter 56c24d5
Add more tests, bugfix grib comparison header only
stefaniereuter f1603af
Refactor Mars key compare
stefaniereuter fb1a7da
Mars refactor cleanup, Test fix
stefaniereuter b0b4e40
refactoring start
stefaniereuter 5a4a728
formatting
stefaniereuter b6071ff
Misc naminging and small structure fixes
pgeier 178997f
Rename and delete unused files
pgeier 81cab14
Use metkit/codes/api instead of directly using eccodes\.h
pgeier 871c092
Clean up compare/grib structure
pgeier fea7aeb
Rework handling difference in mars requests
pgeier 15b1167
Small restructures, remove comments
pgeier 58cdc31
Remove IComporator und move directories
pgeier 8367a32
Restructure tests
pgeier aab54c3
Fix fdb-compare tests and add FP data checks
pgeier ef574d0
Add licensce to .h and .cc files
pgeier 6dc8d26
Add more documentation; remove grib/Message
pgeier d42befa
Address PR comments
pgeier ce404ce
Avoid duplicating data file
pgeier 0436ed8
Fix bitwise comparison; add tests for methods
pgeier 059fce7
Finalize PR
pgeier bc344c8
Use eckit::Log; Fix headers in CMakeLists; Refactor grib compare Result
pgeier 615b645
Check return code in test; Minor changes
pgeier d549af6
Use fdb5::Key and fdb5::ListElement instead of custom types
pgeier File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,258 @@ | ||
| /* | ||
| * (C) Copyright 2025- ECMWF. | ||
| * | ||
| * This software is licensed under the terms of the Apache Licence Version 2.0 | ||
| * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
| * In applying this licence, ECMWF does not waive the privileges and immunities | ||
| * granted to it by virtue of its status as an intergovernmental organisation nor | ||
| * does it submit to any jurisdiction. | ||
| */ | ||
| #include "Types.h" | ||
|
|
||
| #include "eckit/exception/Exceptions.h" | ||
| #include "eckit/log/Log.h" | ||
|
|
||
| #include <sstream> | ||
|
|
||
| namespace compare { | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const KeyDiffMap& km) { | ||
| os << "{"; | ||
| for (const auto& [k, v] : km) { | ||
| os << k << "=" << "(" << (v.first ? *v.first : "<MISSING>") << ", " << (v.second ? *v.second : "<MISSING>") | ||
| << ")" << ", "; | ||
| } | ||
| os << "}"; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const KeySet& km) { | ||
| os << "{"; | ||
| for (const auto& k : km) { | ||
| os << k << ", "; | ||
| } | ||
| os << "}"; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const DataIndex& idx) { | ||
| for (const auto& [km, loc] : idx) { | ||
| os << "Key: " << km << " -> Value: " << loc << "\n"; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| void parseKeySet(KeySet& container, const std::string& keyStr) { | ||
| std::istringstream stream(keyStr); | ||
| std::string entry; | ||
|
|
||
| while (std::getline(stream, entry, ',')) { | ||
| container.insert(entry); // Insert the whole entry as a single string | ||
| } | ||
| } | ||
|
|
||
| KeySet parseKeySet(const std::string& keyStr) { | ||
| KeySet container; | ||
| parseKeySet(container, keyStr); | ||
| return container; | ||
| } | ||
|
|
||
| compare::KeyDiffMap requestDiff(const fdb5::Key& l, const fdb5::Key& r) { | ||
| compare::KeyDiffMap res; | ||
| for (const auto& [lk, lv] : l) { | ||
| auto [search, isValid] = r.find(lk); | ||
| if (isValid) { | ||
| if (search->second != lv) { | ||
| res.insert({lk, {lv, search->second}}); | ||
| } | ||
| } | ||
| else { | ||
| res.insert({lk, {lv, {}}}); | ||
| } | ||
| } | ||
|
|
||
| for (const auto& [rk, rv] : r) { | ||
| auto [search, isValid] = l.find(rk); | ||
| if (!isValid) { | ||
| res.insert({rk, {{}, rv}}); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| fdb5::Key applyKeyDiff(fdb5::Key k, const KeyDiffMap& diff, bool swapDiff) { | ||
| for (const auto& [field, val_pair] : diff) { | ||
| const auto& val = swapDiff ? val_pair.first : val_pair.second; | ||
| if (val) { | ||
| k.set(field, *val); | ||
| } | ||
| else { | ||
| // Delete | ||
| k.unset(field); | ||
| } | ||
| } | ||
| return k; // return modified copy | ||
| }; | ||
|
|
||
| Scope parseScope(const std::string& s) { | ||
| if (s == "header-only") { | ||
| return Scope::HeaderOnly; | ||
| } | ||
| else if (s == "all") { | ||
| return Scope::All; | ||
| } | ||
| else if (s == "mars") { | ||
| return Scope::Mars; | ||
| } | ||
| throw eckit::UserError("Unknown comparison scope " + s, Here()); | ||
| } | ||
| std::ostream& operator<<(std::ostream& os, const Scope& scope) { | ||
| switch (scope) { | ||
| case Scope::HeaderOnly: | ||
| os << "header-only"; | ||
| break; | ||
| case Scope::All: | ||
| os << "all"; | ||
| break; | ||
| case Scope::Mars: | ||
| os << "mars"; | ||
| break; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
| Method parseMethod(const std::string& s) { | ||
| if (s == "bit-identical") { | ||
| return Method::BitIdentical; | ||
| } | ||
| else if (s == "hash-keys") { | ||
| return Method::Hash; | ||
| } | ||
| else { | ||
| // default ("grib-keys") or "mars" | ||
| return Method::KeyByKey; | ||
| } | ||
| } | ||
| std::ostream& operator<<(std::ostream& os, const Method& method) { | ||
| switch (method) { | ||
| case Method::BitIdentical: | ||
| os << "bit-identical"; | ||
| break; | ||
| case Method::Hash: | ||
| os << "hash-keys"; | ||
| break; | ||
| case Method::KeyByKey: | ||
| os << "grib-keys"; | ||
| break; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const NumericError& err) { | ||
| os << " Average: \t" << err.avg() << std::endl; | ||
| os << " Min: \t\t" << err.min << std::endl; | ||
| os << " Max: \t\t" << err.max << std::endl; | ||
| os << " Count: \t" << err.count << std::endl; | ||
| return os; | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& os, const Result& res) { | ||
| os << (res.match ? "SUCCESS" : "FAILURE") << std::endl; | ||
| if (res.relativeError) { | ||
| os << std::endl; | ||
| os << "Relative Error:" << std::endl; | ||
| os << *res.relativeError << std::endl; | ||
| } | ||
| if (res.absoluteError) { | ||
| os << std::endl; | ||
| os << "Absolute Error:" << std::endl; | ||
| os << *res.absoluteError << std::endl; | ||
| } | ||
| return os; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| double NumericError::avg() const { | ||
| return sum / count; | ||
| } | ||
|
|
||
| void NumericError::update(const NumericError& other) { | ||
| this->sum += other.sum; | ||
| this->min = std::min(this->min, other.min); | ||
| this->max = std::max(this->max, other.max); | ||
| this->count += other.count; | ||
| } | ||
|
|
||
| void NumericError::update(double val) { | ||
| this->sum += val; | ||
| this->min = std::min(this->min, val); | ||
| this->max = std::max(this->max, val); | ||
| this->count += 1; | ||
| } | ||
|
|
||
| void Result::update(const Result& other) { | ||
| if (this->relativeError) { | ||
| if (other.relativeError) { | ||
| this->relativeError->update(*other.relativeError); | ||
| } | ||
| } | ||
| else { | ||
| this->relativeError = other.relativeError; | ||
| } | ||
|
|
||
| if (this->absoluteError) { | ||
| if (other.absoluteError) { | ||
| this->absoluteError->update(*other.absoluteError); | ||
| } | ||
| } | ||
| else { | ||
| this->absoluteError = other.absoluteError; | ||
| } | ||
|
|
||
| this->match = this->match && other.match; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| bool isSubset(const fdb5::Key& a, const fdb5::Key& b) { | ||
| for (const auto& kv : a) { | ||
| auto [it, isValid] = b.find(kv.first); | ||
| if (!isValid || it->second != kv.second) | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| DataIndex assembleCompareMap(fdb5::FDB& fdb, const fdb5::FDBToolRequest& req, const fdb5::Key& ignore) { | ||
| DataIndex out; | ||
|
|
||
| auto list = fdb.list(req); | ||
| fdb5::ListElement elem; | ||
|
|
||
| while (list.next(elem)) { | ||
| fdb5::Key km = elem.combinedKey(); | ||
| if (ignore.empty() || !isSubset(ignore, km)) { | ||
| out.emplace(km, elem); | ||
| } | ||
| } | ||
| eckit::Log::info() << "[LOG] FDB request: " << req << " resulted in " << out.size() << " entries.\n"; | ||
| return out; | ||
| } | ||
|
|
||
| //--------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| } // namespace compare |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.