Skip to content

Commit fab3764

Browse files
authored
Merge pull request #111 from ecmwf/feature/fix-geopotential-in-upper-level-bufr-plots
Fix geopotential plotting on upper air charts
2 parents c3f4e45 + 7017fb1 commit fab3764

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ build
2929
.ipynb_checkpoints
3030

3131
.vscode
32+
.vscode/
3233
*.sublime-workspace
3334
notebook/.ipynb_checkpoints
3435
compile_commands.json
@@ -42,5 +43,6 @@ tmp.*
4243
.env
4344
*.swp
4445

46+
4547
# mac
4648
.DS_Store

share/magics/bufr_98.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
<type value='2'>
104104
<subtype value='91'>pilot</subtype>
105105
<subtype value='101' template='temp'>temp</subtype>
106+
<subtype value='109' template='temp'>temp</subtype>
107+
<subtype value='111' template='temp'>temp</subtype>
106108
</type>
107109

108110
<type value='4'>

share/magics/obs.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@
106106
<obs_identification row='-1' column='-1'/>
107107
</obs_template>
108108

109-
<obs_template type='temp' rows='4' columns='5'>:
109+
<obs_template type='temp' rows='4' columns='6'>:
110110
<obs_station_ring row='0' column='0'/>
111111
<obs_wind/>
112112
<obs_temperature row='1' column='-1'/>
113113
<obs_dewpoint row='-1' column='-1'/>
114-
<obs_height row='1' column='1'/>
114+
<obs_height row='1' column='4'/>
115115
<obs_thickness row='0' column='1' justification='left'/>
116116
<obs_time_plot row='0' column='-1' />
117117
<obs_identification row='-2' column='-1'/>

src/decoders/ObsDecoder.cc

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
#include "TextVisitor.h"
2828
#include "expat.h"
2929

30+
#include <algorithm>
31+
#include <set>
32+
#include <string>
33+
#include <vector>
34+
3035
using namespace magics;
3136

3237
map<int, bool> multilevels_;
@@ -52,7 +57,7 @@ class BufrSubType : public map<string, string> {
5257
class BufrFamily : public map<string, BufrSubType> {
5358
public:
5459
BufrFamily(const string&);
55-
~BufrFamily(){};
60+
~BufrFamily() {};
5661

5762
void currentType(const map<string, string>& def) { type_ = def.find("value")->second; }
5863

@@ -176,7 +181,7 @@ static void XMLCALL character(void* userData, const char* s, int len) {
176181

177182
BufrIdentifiers::BufrIdentifiers(int centre) : centre_(centre) {
178183
ostringstream file, deffile;
179-
file << buildSharePath("bufr_" + to_string(centre) + ".xml");
184+
file << buildSharePath("bufr_" + to_string(centre) + ".xml");
180185
deffile << buildSharePath("bufr_98.xml");
181186
char buf[BUFSIZ];
182187
XML_Parser parser = XML_ParserCreate(NULL);
@@ -293,9 +298,9 @@ class BufrAccessor {
293298
BufrAccessor(const string& descriptor) : descriptor_(descriptor) {
294299
init();
295300
auto token = translator_.find(descriptor_);
296-
eccodes_ = (token == translator_.end()) ? descriptor_ : token->second;
301+
eccodes_ = (token == translator_.end()) ? descriptor_ : token->second;
297302
}
298-
virtual ~BufrAccessor(){};
303+
virtual ~BufrAccessor() {};
299304
virtual void operator()(const ObsDecoder&, MvObs&, string&) const {}
300305
virtual void operator()(const ObsDecoder&, MvObs& obs, double& val) const { val = obs.value(eccodes_); }
301306
virtual void print() {}
@@ -311,7 +316,7 @@ map<string, string> BufrAccessor::translator_;
311316
class BufrMultiValueAccessor : public BufrAccessor {
312317
public:
313318
BufrMultiValueAccessor(const string& descriptor, int index) : BufrAccessor(descriptor), index_(index) {}
314-
virtual ~BufrMultiValueAccessor(){};
319+
virtual ~BufrMultiValueAccessor() {};
315320
virtual void operator()(const ObsDecoder&, MvObs& obs, double& val) const {
316321
const BufrIdentifiers& table = BufrIdentTable::get(obs.originatingCentre());
317322
val = obs.valueByOccurrence(index_, descriptor_);
@@ -381,7 +386,7 @@ class BufrHighCloudHeightAccessor : public BufrMultiValueAccessor {
381386
class BufrTypeAccessor : public BufrAccessor {
382387
public:
383388
BufrTypeAccessor() { descriptor_ = "type"; };
384-
virtual ~BufrTypeAccessor(){};
389+
virtual ~BufrTypeAccessor() {};
385390
void operator()(const ObsDecoder&, MvObs& obs, string& val) const {
386391
val = obs.messageType();
387392

@@ -459,7 +464,7 @@ class BufrMultiLevelAccessor : public BufrAccessor {
459464
void operator()(const ObsDecoder& decoder, MvObs& obs, double& val) const {
460465
const BufrIdentifiers& table = BufrIdentTable::get(obs.originatingCentre());
461466
int type = obs.messageType();
462-
467+
463468
map<int, bool>::const_iterator multilevel = multilevels_.find(type);
464469
if (multilevel == multilevels_.end()) {
465470
MagLog::warning() << "BufrMultiLevelAccessor> Unknown observation type [" << val << "]\n";
@@ -468,7 +473,7 @@ class BufrMultiLevelAccessor : public BufrAccessor {
468473
if (type == 0 || type == 1) {
469474
// surface data
470475
val = obs.value(surface_);
471-
if ( val == kBufrMissingValue ) {
476+
if (val == kBufrMissingValue) {
472477
// Trying the descriptor for multilevel: some centres are using it for surface.
473478
val = obs.value(altitude_);
474479
}
@@ -492,8 +497,43 @@ class BufrMultiLevelAccessor : public BufrAccessor {
492497

493498
class BufrGeopotentialAccessor : public BufrMultiLevelAccessor {
494499
public:
495-
BufrGeopotentialAccessor() : BufrMultiLevelAccessor("geopotential") {}
500+
BufrGeopotentialAccessor() : BufrMultiLevelAccessor("geopotential") {
501+
keys_ = {"geopotential", "nonCoordinateGeopotential", "nonCoordinateGeopotentialHeight"};
502+
heightKeys_ = {"nonCoordinateGeopotentialHeight"};
503+
}
504+
496505
virtual ~BufrGeopotentialAccessor() {}
506+
507+
void operator()(const ObsDecoder& decoder, MvObs& obs, double& val) const {
508+
const BufrIdentifiers& table = BufrIdentTable::get(obs.originatingCentre());
509+
int type = obs.messageType();
510+
511+
map<int, bool>::const_iterator multilevel = multilevels_.find(type);
512+
if (multilevel == multilevels_.end()) {
513+
MagLog::warning() << "BufrMultiLevelAccessor> Unknown observation type [" << val << "]\n";
514+
val = kBufrMissingValue;
515+
}
516+
517+
if (type != 0 && type != 1 && type != 4 && type != 5) {
518+
for (auto key : keys_) {
519+
val = obs.valueByPressureLevel(decoder.level_, key);
520+
// std::cout << "level: " << decoder.level_ << " key: " << key << " val: " << val << std::endl;
521+
if (val != kBufrMissingValue) {
522+
if (heightKeys_.find(key) != heightKeys_.end()) {
523+
val *= 9.81;
524+
}
525+
return;
526+
}
527+
};
528+
}
529+
530+
BufrMultiLevelAccessor::operator()(decoder, obs, val);
531+
}
532+
533+
534+
protected:
535+
std::vector<std::string> keys_;
536+
std::set<std::string> heightKeys_;
497537
};
498538

499539
class BufrTemperatureAccessor : public BufrMultiLevelAccessor {
@@ -670,7 +710,6 @@ void ObsDecoder::customisedPoints(const Transformation& transformation, const st
670710

671711
map<string, BufrAccessor*> accessors;
672712
for (std::set<string>::const_iterator token = tokens.begin(); token != tokens.end(); ++token) {
673-
674713
try {
675714
BufrAccessor* accessor = SimpleObjectMaker<BufrAccessor>::create(*token);
676715
accessors.insert(make_pair(*token, accessor));
@@ -679,7 +718,6 @@ void ObsDecoder::customisedPoints(const Transformation& transformation, const st
679718
BufrAccessor* accessor = new BufrAccessor(*token);
680719
accessors.insert(make_pair(*token, accessor));
681720
}
682-
683721
}
684722

685723
// Create the type accessor!

0 commit comments

Comments
 (0)