File: ThermoView.cc

package info (click to toggle)
metview 5.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 44,932 kB
  • sloc: cpp: 211,811; ansic: 33,467; xml: 3,942; sh: 2,942; yacc: 1,183; fortran: 762; lex: 761; perl: 700; python: 340; f90: 236; makefile: 92
file content (383 lines) | stat: -rw-r--r-- 11,842 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "ThermoView.h"
#include "MvRequestUtil.hpp"
#include "ObjectList.h"
#include "PlotMod.h"
#include "PmContext.h"
#include "Root.h"

// Thermo types
static const string THERMOTEPHI   = "TEPHIGRAM";
static const string THERMOSKEWT   = "SKEW_T";
static const string THERMOEMAGRAM = "EMAGRAM";

// Thermo data types
map<string,string> create_dataTypeMap()
{
   map<string,string> m;
   m["GRIB"] = "GRIB_THERMO";
   m["BUFR"] = "BUFR_THERMO";
   m["ODB"]  = "ODB_THERMO";
   return m;
}

static map<string,string> DATA_TYPE = create_dataTypeMap();

//--------------------------------------------------------

static ThermoViewFactory thermoViewFactoryInstance;

PlotModView*
ThermoViewFactory::Build ( Page& page,
                           const MvRequest& contextRequest,
                           const MvRequest& setupRequest )
{
   // Expand request
   MvRequest expReq = ObjectList::ExpandRequest(contextRequest,EXPAND_DEFAULTS);

   // Copy hidden parameters
   expReq.mars_merge(contextRequest);

   // Instantiate a Thermo view
   return new ThermoView ( page, expReq, setupRequest );
}

//-----------------------------------------------------------------

ThermoView::ThermoView ( Page& owner,
                         const MvRequest& viewRequest,
                         const MvRequest& setupRequest ):
               CommonXSectView ( owner, viewRequest, setupRequest )
{
   SetVariables(viewRequest,true);
}

ThermoView::ThermoView ( const ThermoView &old ) :
               CommonXSectView(old)
{
   type_ = old.type_;
}

string ThermoView::Name()
{
   int id =  Owner().Id();
   string name = (const char*)ObjectInfo::ObjectName ( viewRequest_, "ThermoView", id );

   return name;
}

void ThermoView::DescribeYourself ( ObjectInfo& description )
{
   // Convert my request to Macro
   set<Cached> skipSet;
   description.ConvertRequestToMacro ( appViewReq_, PUT_END, MacroName().c_str(),"thermoview", skipSet);
   description.PutNewLine (" " );
}

void ThermoView::SetVariables(const MvRequest &in, bool)
{
   // Set Thermo type
   type_ = (const char*)in("TYPE");
}

bool ThermoView::UpdateView ()
{
   // It has already been updated
   if ( string(viewRequest_.getVerb()) == CARTESIANVIEW )
      return true;

   // Create a Cartesian View request related to Tephigram
   // Magics requires that the value for parameter map_projection be 
   // in lower case
   MvRequest cartView("CARTESIANVIEW");
   string sdata = type_;
   std::transform(sdata.begin(), sdata.end(), sdata.begin(), ::tolower);
   cartView("MAP_PROJECTION") = sdata.c_str();

   // Translate axes min/max values
   // Check where the values should be taken from
   if ( (const char*)viewRequest_("_DEFAULT") &&
        (int)viewRequest_("_DEFAULT") == 1 &&
        (const char*)viewRequest_("_DATAATTACHED") &&
        strcmp((const char*)viewRequest_("_DATAATTACHED"),"YES") == 0
      )
   {
      cartView("X_AUTOMATIC") = "on";
      cartView("Y_AUTOMATIC") = "on";
   }
   else
   {
      cartView("X_AUTOMATIC") = "off";
      cartView("Y_AUTOMATIC") = "off";

      // Get min/max axes coordinates
      cartView("X_MIN") = viewRequest_("MINIMUM_TEMPERATURE");
      cartView("X_MAX") = viewRequest_("MAXIMUM_TEMPERATURE");
      cartView("Y_MIN") = viewRequest_("BOTTOM_PRESSURE");
      cartView("Y_MAX") = viewRequest_("TOP_PRESSURE");
   }

   // Copy ThermoGrid definition
   MvRequest reqGrid = viewRequest_.getSubrequest("THERMO_GRID");
   if ( reqGrid )
      cartView("THERMO_GRID") = reqGrid;

   // Remove some unnecessary Page and SubPage parameters and
   // copy the remaining ones to the new View
   if ( (const char*)viewRequest_("PAGE_FRAME") &&
        strcmp((const char*)viewRequest_("PAGE_FRAME"),"OFF") == 0 )
      RemoveParameters( viewRequest_, "PAGE_FRAME" );

   if ( (const char*)viewRequest_("PAGE_ID_LINE") &&
        strcmp((const char*)viewRequest_("PAGE_ID_LINE"),"OFF") == 0 )
      RemoveParameters( viewRequest_, "PAGE_ID_LINE" );

   if ( (const char*)viewRequest_("SUBPAGE_FRAME") &&
        strcmp((const char*)viewRequest_("SUBPAGE_FRAME"),"OFF") == 0 )
      RemoveParameters( viewRequest_, "SUBPAGE_FRAME" );

   CopySomeParameters( viewRequest_,cartView,"PAGE" );
   CopySomeParameters( viewRequest_,cartView,"SUBPAGE" );

   // Copy the original request without certain parameteres (to avoid duplication)
   RemoveParameters( viewRequest_, "HORIZONTAL_AXIS" );
   RemoveParameters( viewRequest_, "VERTICAL_AXIS" );
   RemoveParameters( viewRequest_, "PAGE" );
   RemoveParameters( viewRequest_, "SUBPAGE" );
   RemoveParameters( viewRequest_, "_" );
   cartView("_ORIGINAL_REQUEST") = viewRequest_;

   // Update request
   viewRequest_ = cartView;

   // Indicate that the plotting tree needs to be rebuilt
   Root::Instance().Refresh(false);

   return true;
}

bool ThermoView::UpdateView ( MvRequest& viewRequest )
{
   // Get the original ThermoView request in case it has already
   // been translated to a CartesianView request
   MvRequest tview;
   string tverb;
   if ( !ObjectList::IsThermoView( viewRequest_.getVerb() ) )
   {
      // Retrieve the original ThermoView request
      tview = viewRequest_("_ORIGINAL_REQUEST");
   }
   else
      tview = viewRequest_;

   // Changing to another View is not allowed
   if ( !ObjectList::IsThermoView( viewRequest.getVerb() ) )
   {
      // Changing View is disabled at the moment
      char text[128];
      sprintf(text,"Changing View (%s to %s) is currently disabled",tview.getVerb(),viewRequest.getVerb() );
      PlotMod::Instance().errorMessage(text);
      return false;
   }

   // If the request came from an Application then ignore the new
   // View definition and use the current View to draw the new plot
   MvRequest contextReq = viewRequest.getSubrequest("_CONTEXT");
   if ( contextReq )
      return true;;

   // Expand request
   MvRequest req = ObjectList::ExpandRequest (viewRequest, EXPAND_DEFAULTS);

#if 0
   // FAMI20180426 
   // This consistency check was removed to allow users to change View
   // without constraints.

   // Parameters used to compute the thermo data
   // must have the same value
   string param;
   if ( !ConsistencyCheck(tview,req,param) )
   {
      char text[128];
      sprintf(text,"Changing View not allowed.\nParameter %s must have the same value (%s , %s)", param.c_str(), 
      (const char*)tview(param.c_str()),(const char*)req(param.c_str()) );
      PlotMod::Instance().errorMessage(text);
      return false;
   }
#endif

   // Update the current view
   type_ = (const char*)req("TYPE");

   // Update request
   // Owner().UpdateView(req);  // it will be updated later (CommonXSectView)

   // Indicate that the plotting tree needs to be rebuilt
   Root::Instance().Refresh(false);

   // Redraw this page
   //Owner().RedrawIfWindow();
   //Owner().NotifyObservers();

   //Owner().InitZoomStacks();

   return true;
}

void ThermoView::ApplicationInfo( const MvRequest& req)
{
   // Get the VIEW request
   MvRequest viewReq;
   if ( ObjectList::IsView(req.getVerb()) )
      viewReq = req;
   else
   {
      // Try to find a hidden VIEW in the request
      viewReq = req.getSubrequest("_VIEW_REQUEST");
      if ( !viewReq )
      {
         // Nothing to be done
         return;
      }
   }

   return;
}

void ThermoView::Drop ( PmContext& context )
{
   // Before processing the drop (parent's function), check for icon drops
   // specific to this class:
   // a) dataUnit: initializes the type of the ThermoData module to be called
   // b) thermogrid: update the View
   // c) thermoview: update the View
   MvRequest dropRequest = context.InRequest();
   bool first = true;
   while ( dropRequest )
   {
      // Data unit
      string verb = dropRequest.getVerb();
      if ( first && ObjectList::IsDataUnit ( verb.c_str() ) == true )
      {
         MvRequest req = dropRequest.justOneRequest();

         if ( !this->SetThermoType(req) )
            return;   // suitable thermo type not found

         first = false;
      }
      // Thermo grid
      else if ( ObjectList::IsThermoGrid ( verb.c_str() ) == true )
      {
         MvRequest req = dropRequest.justOneRequest();
         this->UpdateThermoGrid ( req );
      }
      else if ( ObjectList::IsThermoView( verb.c_str() ) )
      {
         // First: check and update the internal ThermoView structure
         // Second: ask CommonXSectView::Drop to update the Page
         MvRequest req = dropRequest.justOneRequest();
         if ( !this->UpdateView ( req ) )
            return;
      }

      dropRequest.advance();
   }

   // Call the parent to perform the Drop request
   CommonXSectView::Drop(context);

   return;
}

void ThermoView::UpdateThermoGrid ( MvRequest& req )
{
   // Update new thermo grid definition. The View will be updated later.
   viewRequest_("THERMO_GRID") = req;
}

bool ThermoView::SetThermoType( MvRequest& req )
{
   string thermoType;
   string verb = req.getVerb();
   map<string,string>::iterator it;
   it = DATA_TYPE.find(verb.c_str());
   if ( it != DATA_TYPE.end()  )
      thermoType = it->second;
   else if ( verb == "NETCDF" )
   {
      if ( (const char*)req("_VERB") )
         thermoType = (const char*)req("_VERB");
      else if ( (const char*)req("_CLASS") )
         thermoType = (const char*)req("_CLASS");
      else
      {
         // Thermo type not found
         char text[128];
         sprintf( text,"Suitable thermo type not found: %s ",verb.c_str() );
         PlotMod::Instance().errorMessage(text);
         return false;
      }
   }
   else if ( verb.find("NETCDF") != std::string::npos )
   {
      // The application has been already called to process the data.
      // These are a set of requests containing the NETCDF_XY_*;
      // therefore it will be processed withoug calling again the
      // application. There is no need to set the ApplicationName.
      return true;
   }
   else if ( verb.find("INPUT") != std::string::npos )
   {
      // The application has been already called to process the data.
      // These are a set of requests containing the _XY_*;
      // therefore it will be processed withoug calling again the
      // application. There is no need to set the ApplicationName.
      return true;
   }
   else
   {
      // Thermo type not found
      char text[128];
      sprintf( text,"Suitable thermo type not found: %s ",verb.c_str() );
      PlotMod::Instance().errorMessage(text);
      return false;
   }

   ApplicationName(thermoType);
   return true;
}

bool ThermoView::ConsistencyCheck(MvRequest& req1, MvRequest& req2, string& param)
{
   // Build a list of parameters to be checked
   std::vector<string> vparam;
   vparam.push_back("POINT_SELECTION");

   if ( (const char*)req1("COORDINATES") )
      vparam.push_back("COORDINATES");
   if ( (const char*)req1("AREA_AVERAGE") )
      vparam.push_back("AREA_AVERAGE");
   if ( (const char*)req1("STATION") )
      vparam.push_back("STATION");

   vparam.push_back("POINT_EXTRACTION");
   vparam.push_back("DEW_POINT_FORMULATION");
   vparam.push_back("TEMPERATURE_PARAM");
   vparam.push_back("SPECIFIC_HUMIDITY_PARAM");
   vparam.push_back("LNSP_PARAM");
   vparam.push_back("U_WIND_PARAM");
   vparam.push_back("V_WIND_PARAM");

   // Check one by one because we want to know which one is different
   return req1.checkParameters(req2,vparam,param);
}