bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDFDMRArray_EOS2LL.cc
1
2// This file is part of the hdf4 data handler for the OPeNDAP data server.
3// It retrieves HDF-EOS2 latitude/longtitude values for a direct DMR-mapping DAP4 response.
4// Each SDS will be mapped to a DAP variable.
5
6// Authors: Kent Yang <myang6@hdfgroup.org>
7// Copyright (c) The HDF Group
9
10
11#include "HDFDMRArray_EOS2LL.h"
12#include "hdf.h"
13#include "mfhdf.h"
14#include "HdfEosDef.h"
15#include <iostream>
16#include <sstream>
17#include <libdap/debug.h>
18#include <libdap/InternalErr.h>
19#include <BESDebug.h>
20
21using namespace std;
22using namespace libdap;
23
24
25bool
26HDFDMRArray_EOS2LL::read ()
27{
28
29 BESDEBUG("h4","Coming to HDFDMRArray_EOS2LL read "<<endl);
30 if (length() == 0)
31 return true;
32
33 // Declaration of offset,count and step
34 vector<int>offset;
35 offset.resize(ll_rank);
36 vector<int>count;
37 count.resize(ll_rank);
38 vector<int>step;
39 step.resize(ll_rank);
40
41 string err_msg;
42
43 // Obtain offset,step and count from the client expression constraint
44 int nelms = format_constraint(offset.data(),step.data(),count.data());
45
46 int32 gridfd = GDopen(const_cast < char *>(filename.c_str()), DFACC_READ);
47 if (gridfd <0) {
48 ostringstream eherr;
49 err_msg = "HDF-EOS: GDopen failed";
50 throw InternalErr (__FILE__, __LINE__, err_msg);
51 }
52
53 int32 gridid = GDattach(gridfd, const_cast<char *>(gridname.c_str()));
54 if (gridid <0) {
55 ostringstream eherr;
56 err_msg = "HDF-EOS: GDattach failed to attach " + gridname;
57 GDclose(gridfd);
58 throw InternalErr (__FILE__, __LINE__, err_msg);
59 }
60
61 // Declare projection code, zone, etc grid parameters.
62 int32 projcode = -1;
63 int32 zone = -1;
64 int32 sphere = -1;
65 float64 params[16];
66
67 int32 xdim = 0;
68 int32 ydim = 0;
69
70 float64 upleft[2];
71 float64 lowright[2];
72
73 if (GDprojinfo (gridid, &projcode, &zone, &sphere, params) <0) {
74 GDdetach(gridid);
75 GDclose(gridfd);
76 err_msg = "GDprojinfo failed for grid name: " + gridname;
77 throw InternalErr (__FILE__, __LINE__, err_msg);
78 }
79
80 // Retrieve dimensions and X-Y coordinates of corners
81 if (GDgridinfo(gridid, &xdim, &ydim, upleft,
82 lowright) == -1) {
83 GDdetach(gridid);
84 GDclose(gridfd);
85 err_msg = "GDgridinfo failed for grid name: " + gridname;
86 throw InternalErr (__FILE__, __LINE__, err_msg);
87 }
88
89 // Retrieve pixel registration information
90 int32 pixreg = 0;
91 intn r = GDpixreginfo (gridid, &pixreg);
92 if (r != 0) {
93 GDdetach(gridid);
94 GDclose(gridfd);
95 err_msg = "GDpixreginfo failed for grid name: " + gridname;
96 throw InternalErr (__FILE__, __LINE__, err_msg);
97 }
98
99 //Retrieve grid pixel origin
100 int32 origin = 0;
101 r = GDorigininfo (gridid, &origin);
102 if (r != 0) {
103 GDdetach(gridid);
104 GDclose(gridfd);
105 err_msg = "GDoriginfo failed for grid name: " + gridname;
106 throw InternalErr (__FILE__, __LINE__, err_msg);
107 }
108
109 vector<int32>rows;
110 vector<int32>cols;
111 vector<float64>lon;
112 vector<float64>lat;
113 rows.resize(xdim*ydim);
114 cols.resize(xdim*ydim);
115 lon.resize(xdim*ydim);
116 lat.resize(xdim*ydim);
117
118
119 int i = 0;
120 int j = 0;
121 int k = 0;
122
123 /* Fill two arguments, rows and columns */
124 // rows cols
125 // /- xdim -/ /- xdim -/
126 // 0 0 0 ... 0 0 1 2 ... x
127 // 1 1 1 ... 1 0 1 2 ... x
128 // ... ...
129 // y y y ... y 0 1 2 ... x
130
131 for (k = j = 0; j < ydim; ++j) {
132 for (i = 0; i < xdim; ++i) {
133 rows[k] = j;
134 cols[k] = i;
135 ++k;
136 }
137 }
138
139
140 r = GDij2ll (projcode, zone, params, sphere, xdim, ydim, upleft, lowright,
141 xdim * ydim, rows.data(), cols.data(), lon.data(), lat.data(), pixreg, origin);
142
143 if (r != 0) {
144 GDdetach(gridid);
145 GDclose(gridfd);
146 err_msg = "cannot calculate grid latitude and longitude for grid name: " + gridname;
147 throw InternalErr (__FILE__, __LINE__, err_msg);
148 }
149
150 if (is_lat) {
151 // Need to check if CEA or GEO
152 if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
153 vector<float64>out_lat;
154 out_lat.resize(ydim);
155 j=0;
156 for (i =0; i<xdim*ydim;i = i+xdim){
157 out_lat[j] = lat[i];
158 j++;
159 }
160
161 // Need to consider the subset case.
162 vector<float64>out_lat_subset;
163 out_lat_subset.resize(nelms);
164 for (i=0;i<count[0];i++)
165 out_lat_subset[i] = out_lat[offset[0]+i*step[0]];
166 set_value(out_lat_subset.data(),nelms);
167
168 }
169 else {
170 vector<float64>out_lat_subset;
171 out_lat_subset.resize(nelms);
172 LatLon2DSubset(out_lat_subset.data(),xdim,lat.data(),offset.data(),count.data(),step.data());
173 set_value(out_lat_subset.data(),nelms);
174 }
175 }
176 else {
177 if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
178 vector<float64>out_lon;
179 out_lon.resize(xdim);
180 for (i =0; i<xdim;i++)
181 out_lon[i] = lon[i];
182
183 // Need to consider the subset case.
184 vector<float64>out_lon_subset;
185 out_lon_subset.resize(nelms);
186 for (i=0;i<count[0];i++)
187 out_lon_subset[i] = out_lon[offset[0]+i*step[0]];
188 set_value(out_lon_subset.data(),nelms);
189
190 }
191 else {
192 vector<float64>out_lon_subset;
193 out_lon_subset.resize(nelms);
194 LatLon2DSubset(out_lon_subset.data(),xdim,lon.data(),offset.data(),count.data(),step.data());
195 set_value(out_lon_subset.data(),nelms);
196 }
197
198 }
199 set_read_p(true);
200 GDdetach(gridid);
201 GDclose(gridfd);
202 return true;
203}
204// Standard way to pass the coordinates of the subsetted region from the client to the handlers
205// Returns the number of elements
206int
207HDFDMRArray_EOS2LL::format_constraint (int *offset, int *step, int *count)
208{
209 int nels = 1;
210 int id = 0;
211
212 Dim_iter p = dim_begin ();
213 while (p != dim_end ()) {
214
215 int start = dimension_start (p, true);
216 int stride = dimension_stride (p, true);
217 int stop = dimension_stop (p, true);
218
219 // Check for illegal constraint
220 if (start > stop) {
221 ostringstream oss;
222 oss << "Array/Grid hyperslab start point "<< start <<
223 " is greater than stop point " << stop <<".";
224 throw Error(malformed_expr, oss.str());
225 }
226
227 offset[id] = start;
228 step[id] = stride;
229 count[id] = ((stop - start) / stride) + 1; // count of elements
230 nels *= count[id]; // total number of values for variable
231
232 BESDEBUG ("h4",
233 "=format_constraint():"
234 << "id=" << id << " offset=" << offset[id]
235 << " step=" << step[id]
236 << " count=" << count[id]
237 << endl);
238
239 id++;
240 p++;
241 }
242
243 return nels;
244}
245
246// Map the subset of the lat/lon buffer to the corresponding 2D array.
247template<class T> void
248HDFDMRArray_EOS2LL::LatLon2DSubset (T * outlatlon,
249 int minordim, T * latlon,
250 const int * offset, const int * count,
251 const int * step) const
252{
253 int i = 0;
254 int j = 0;
255
256 // do subsetting
257 // Find the correct index
258 int dim0count = count[0];
259 int dim1count = count[1];
260 int dim0index[dim0count];
261 int dim1index[dim1count];
262
263 for (i = 0; i < count[0]; i++) // count[0] is the least changing dimension
264 dim0index[i] = offset[0] + i * step[0];
265
266
267 for (j = 0; j < count[1]; j++)
268 dim1index[j] = offset[1] + j * step[1];
269
270 // Now assign the subsetting data
271 int k = 0;
272
273 for (i = 0; i < count[0]; i++) {
274 for (j = 0; j < count[1]; j++) {
275
276 outlatlon[k] = *(latlon + (dim0index[i] * minordim) + dim1index[j]);
277 k++;
278
279 }
280 }
281}
282
283
284