ROPO
Loading...
Searching...
No Matches
rave_fmi_volume.c
Go to the documentation of this file.
1/* --------------------------------------------------------------------
2Copyright (C) 2011 Swedish Meteorological and Hydrological Institute, SMHI,
3
4This file is part of bRopo.
5
6bRopo is free software: you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11bRopo is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License
17along with bRopo. If not, see <http://www.gnu.org/licenses/>.
18------------------------------------------------------------------------*/
19
27#include "rave_fmi_volume.h"
28#include "rave_debug.h"
29#include "rave_alloc.h"
30
35 RAVE_OBJECT_HEAD
38};
39
44static int RaveFmiVolume_constructor(RaveCoreObject* obj)
45{
46 RaveFmiVolume_t* this = (RaveFmiVolume_t*)obj;
47 this->image = NULL;
48 this->sweepCount = 0;
49 return 1;
50}
51
56static void RaveFmiVolumeInternal_resetImage(RaveFmiVolume_t* img)
57{
58 int i = 0;
59 if (img->image != NULL) {
60 for (i = 0; i < img->sweepCount; i++) {
61 if (img->image[i].heights != NULL) {
62 RAVE_FREE(img->image[i].heights);
63 }
64 if (img->image[i].array != NULL) {
65 RAVE_FREE(img->image[i].array);
66 }
67 if (img->image[i].original != NULL) {
68 RAVE_FREE(img->image[i].original);
69 }
70 }
71 RAVE_FREE(img->image);
72 }
73 img->image = NULL;
74 img->sweepCount = 0;
75}
76
80static void RaveFmiVolume_destructor(RaveCoreObject* obj)
81{
83 RaveFmiVolumeInternal_resetImage(src);
84}
85
91static int RaveFmiVolumeInternal_getSweepCount(PolarVolume_t* volume, const char* quantity)
92{
93 int sweepCount = 0;
94 int i = 0;
95 int nrScans = 0;
96 RAVE_ASSERT((volume != NULL), "volume == NULL");
97
98 nrScans = PolarVolume_getNumberOfScans(volume);
99
103 for (i = 0; i < nrScans; i++) {
104 PolarScan_t* scan = PolarVolume_getScan(volume, i);
105 if (scan != NULL) {
106 if (quantity == NULL || PolarScan_hasParameter(scan, quantity)) {
107 sweepCount++;
108 }
109 }
110 RAVE_OBJECT_RELEASE(scan);
111 }
112
113 return sweepCount;
114}
115
123static int RaveFmiVolumeInternal_scanToFmiImage(PolarScan_t* scan, const char* quantity, FmiImage* image)
124{
125 int i = 0, j = 0;
126 int result = 0;
127 PolarScanParam_t* param = NULL;
128
129 RAVE_ASSERT((scan != NULL), "scan == NULL");
130 RAVE_ASSERT((image != NULL), "image == NULL");
131
132 image->width=PolarScan_getNbins(scan);
133 image->height=PolarScan_getNrays(scan);
134 image->bin_depth=PolarScan_getRscale(scan);
135 image->elevation_angle=PolarScan_getElangle(scan) * 180.0 / M_PI; /* elangles in degrees for ropo */
136 image->max_value=255;
137 image->channels=1;
138
139 initialize_image(image);
140
141 if (quantity == NULL) {
142 param = PolarScan_getParameter(scan, "DBZH");
143 } else {
144 param = PolarScan_getParameter(scan, quantity);
145 }
146
147 if (param == NULL) {
148 RAVE_WARNING1("Failed to extract parameter %s from scan", quantity);
149 goto done;
150 }
151 if (PolarScanParam_getDataType(param) != RaveDataType_CHAR &&
152 PolarScanParam_getDataType(param) != RaveDataType_UCHAR) {
153 RAVE_WARNING0("FmiImages can only support 8-bit data");
154 goto done;
155 }
156
157 for (j = 0; j < image->height; j++) {
158 for (i = 0; i < image->width; i++) {
159 double value = 0.0;
160 PolarScanParam_getValue(param, i, j, &value);
161 put_pixel(image, i, j, 0, (Byte)(value)); // why + 0.5 ?
162 }
163 }
164
165 result = 1;
166done:
167 RAVE_OBJECT_RELEASE(param);
168 return result;
169}
170
177static int RaveFmiVolumeInternal_fieldToFmiImage(RaveField_t* field, FmiImage* image)
178{
179 int i = 0, j = 0;
180 int result = 0;
181
182 RAVE_ASSERT((field != NULL), "field == NULL");
183 RAVE_ASSERT((image != NULL), "image == NULL");
184
185 image->width=RaveField_getXsize(field);
186 image->height=RaveField_getYsize(field);
187 image->channels=1;
188
189 initialize_image(image);
190
191 if (RaveField_getDataType(field) != RaveDataType_CHAR &&
192 RaveField_getDataType(field) != RaveDataType_UCHAR) {
193 RAVE_WARNING0("FmiImages can only support 8-bit data");
194 goto done;
195 }
196
197 for (j = 0; j < image->height; j++) {
198 for (i = 0; i < image->width; i++) {
199 double value = 0.0;
200 RaveField_getValue(field, i, j, &value);
201 put_pixel(image, i, j, 0, (Byte)(value)); // why + 0.5 ?
202 }
203 }
204
205 result = 1;
206done:
207 return result;
208}
209
216static PolarScan_t* RaveFmiVolumeInternal_fmiImageToScan(FmiImage* image, const char* quantity)
217{
218 PolarScan_t* scan = NULL;
219 PolarScan_t* result = NULL;
220 PolarScanParam_t* param = NULL;
221 int ray = 0, bin = 0;
222 RAVE_ASSERT((image != NULL), "image == NULL");
223
224 scan = RAVE_OBJECT_NEW(&PolarScan_TYPE);
225 param = RAVE_OBJECT_NEW(&PolarScanParam_TYPE);
226 if (scan == NULL || param == NULL) {
227 RAVE_CRITICAL0("Failed to allocate memory for polar scan");
228 goto done;
229 }
230
231 PolarScanParam_setGain(param, 1.0);
232 PolarScanParam_setOffset(param, 0.0);
233 PolarScanParam_setNodata(param, 255.0);
234 PolarScanParam_setUndetect(param, 0.0);
235 if (quantity != NULL) {
236 PolarScanParam_setQuantity(param, quantity);
237 } else {
238 PolarScanParam_setQuantity(param, "DBZH");
239 }
240 if (!PolarScanParam_createData(param, image->width, image->height, RaveDataType_UCHAR)) {
241 RAVE_CRITICAL0("Failed to allocate memory for data");
242 goto done;
243 }
244
245 for (ray = 0; ray < image->height; ray++) {
246 for (bin = 0; bin < image->width; bin++) {
247 PolarScanParam_setValue(param, bin, ray, (double)get_pixel(image, bin, ray, 0));
248 }
249 }
250 if (!PolarScan_addParameter(scan, param)) {
251 RAVE_CRITICAL0("Failed to add parameter to scan");
252 goto done;
253 }
254 PolarScan_setRscale(scan, image->bin_depth);
255 PolarScan_setElangle(scan, image->elevation_angle * M_PI / 180.0);
256 PolarScan_setRstart(scan, 0.0);
257
258 result = RAVE_OBJECT_COPY(scan);
259done:
260 RAVE_OBJECT_RELEASE(scan);
261 RAVE_OBJECT_RELEASE(param);
262 return result;
263}
264
269{
270 int result = 0;
271 RAVE_ASSERT((self != NULL), "self == NULL");
272 if (sweepCount <= 0) {
273 RAVE_ERROR0("You can not initialize a fmi image with sweepCount <= 0");
274 } else {
275 FmiImage* images = new_image(sweepCount);
276 if (images != NULL) {
277 RaveFmiVolumeInternal_resetImage(self);
278 self->image = images;
279 self->sweepCount = sweepCount;
280 result = 1;
281 }
282 }
283 return result;
284}
285
287{
288 RAVE_ASSERT((self != NULL), "self == NULL");
289 return self->sweepCount;
290}
291
293{
294 RAVE_ASSERT((self != NULL), "self == NULL");
295 return self->image;
296}
297
299{
300 RAVE_ASSERT((self != NULL), "self == NULL");
301 if (sweep >= 0 && sweep < self->sweepCount) {
302 return &self->image[sweep];
303 }
304 return NULL;
305}
306
307PolarVolume_t* RaveFmiVolume_toRave(RaveFmiVolume_t* self, const char* quantity)
308{
309 PolarVolume_t* result = NULL;
310 PolarVolume_t* volume = NULL;
311 PolarScan_t* scan = NULL;
312
313 int i = 0;
314
315 RAVE_ASSERT((self != NULL), "self == NULL");
316
317 volume = RAVE_OBJECT_NEW(&PolarVolume_TYPE);
318 if (volume == NULL) {
319 RAVE_CRITICAL0("Failed to create volume");
320 goto done;
321 }
322
323 for (i = 0; i < self->sweepCount; i++) {
324 scan = RaveFmiVolumeInternal_fmiImageToScan(&self->image[i], quantity);
325 if (scan == NULL) {
326 RAVE_CRITICAL0("Failed to convert image to scan");
327 goto done;
328 }
329 if (!PolarVolume_addScan(volume, scan)) {
330 RAVE_CRITICAL0("Failed to add scan to volume");
331 goto done;
332 }
333 RAVE_OBJECT_RELEASE(scan);
334 }
335
336 result = RAVE_OBJECT_COPY(volume);
337done:
338 RAVE_OBJECT_RELEASE(scan);
339 RAVE_OBJECT_RELEASE(volume);
340 return result;
341}
342
344{
345 RaveFmiVolume_t* result = RAVE_OBJECT_NEW(&RaveFmiVolume_TYPE);
346 if (result != NULL) {
347 if (!RaveFmiVolume_initialize(result, sweepCount)) {
348 RAVE_OBJECT_RELEASE(result);
349 }
350 }
351 return result;
352}
353
354RaveFmiVolume_t* RaveFmiVolume_fromPolarVolume(PolarVolume_t* volume, const char* quantity)
355{
356 int sweepCount = 0;
357 int nrScans = 0;
358 int i = 0;
359 int sweepIndex = 0;
360 RaveFmiVolume_t* image = NULL;
361 RaveFmiVolume_t* result = NULL;
362
363 RAVE_ASSERT((volume != NULL), "volume == NULL");
364
365 PolarVolume_sortByElevations(volume, 1);
366 nrScans = PolarVolume_getNumberOfScans(volume);
367 sweepCount = RaveFmiVolumeInternal_getSweepCount(volume, quantity);
368
369 if (sweepCount <= 0) {
370 RAVE_WARNING0("Volume does not contain any wanted parameters");
371 goto done;
372 }
373
374 image = RaveFmiVolume_new(sweepCount);
375 if (image == NULL) {
376 RAVE_CRITICAL0("Failed to create fmi image");
377 goto done;
378 }
379
380 for (i = 0; i < nrScans; i++) {
381 PolarScan_t* scan = PolarVolume_getScan(volume, i);
382 if (quantity == NULL || PolarScan_hasParameter(scan, quantity)) {
383 if (!RaveFmiVolumeInternal_scanToFmiImage(scan, quantity, &image->image[sweepIndex])) {
384 RAVE_ERROR0("Failed to convert scan to fmi image");
385 RAVE_OBJECT_RELEASE(scan);
386 goto done;
387 }
388 sweepIndex++;
389 }
390 RAVE_OBJECT_RELEASE(scan);
391 }
392
393 result = RAVE_OBJECT_COPY(image);
394done:
395 RAVE_OBJECT_RELEASE(image);
396 return result;
397}
398
399RaveFmiVolume_t* RaveFmiVolume_fromPolarScan(PolarScan_t* scan, const char* quantity)
400{
401 RaveFmiVolume_t* image = NULL;
402 RaveFmiVolume_t* result = NULL;
403
404 RAVE_ASSERT((scan != NULL), "scan == NULL");
405
406 image = RaveFmiVolume_new(1);
407 if (image == NULL) {
408 RAVE_CRITICAL0("Failed to create fmi image");
409 goto done;
410 }
411
412 if (quantity == NULL || PolarScan_hasParameter(scan, quantity)) {
413 if (!RaveFmiVolumeInternal_scanToFmiImage(scan, quantity, &image->image[0])) {
414 RAVE_ERROR0("Failed to convert scan to fmi image");
415 goto done;
416 }
417 }
418
419 result = RAVE_OBJECT_COPY(image);
420done:
421 RAVE_OBJECT_RELEASE(image);
422 return result;
423}
424
426{
427 RaveFmiVolume_t* image = NULL;
428 RaveFmiVolume_t* result = NULL;
429
430 RAVE_ASSERT((field != NULL), "field == NULL");
431
432 image = RaveFmiVolume_new(1);
433 if (image == NULL) {
434 RAVE_CRITICAL0("Failed to create fmi image");
435 goto done;
436 }
437
438 if (!RaveFmiVolumeInternal_fieldToFmiImage(field, &image->image[0])) {
439 RAVE_ERROR0("Failed to convert rave field to fmi image");
440 goto done;
441 }
442
443 result = RAVE_OBJECT_COPY(image);
444done:
445 RAVE_OBJECT_RELEASE(image);
446 return result;
447}
448
449RaveFmiVolume_t* RaveFmiVolume_fromRave(RaveCoreObject* object, const char* quantity)
450{
451 RAVE_ASSERT((object != NULL), "object == NULL");
452 if (RAVE_OBJECT_CHECK_TYPE(object, &PolarVolume_TYPE)) {
453 return RaveFmiVolume_fromPolarVolume((PolarVolume_t*)object, quantity);
454 } else if (RAVE_OBJECT_CHECK_TYPE(object, &PolarScan_TYPE)) {
455 return RaveFmiVolume_fromPolarScan((PolarScan_t*)object, quantity);
456 } else if (RAVE_OBJECT_CHECK_TYPE(object, &RaveField_TYPE)) {
457 return RaveFmiVolume_fromRaveField((RaveField_t*)object);
458 } else {
459 RAVE_ERROR1("RaveFmiVolume_fromRave does not support %s", object->roh_type->name);
460 }
461 return NULL;
462}
463
465RaveCoreObjectType RaveFmiVolume_TYPE = {
466 "RaveFmiVolume",
467 sizeof(RaveFmiVolume_t),
468 RaveFmiVolume_constructor,
469 RaveFmiVolume_destructor,
470 NULL /* No copy constructor */
471};
FmiImage * RaveFmiVolume_getImage(RaveFmiVolume_t *self)
int RaveFmiVolume_getSweepCount(RaveFmiVolume_t *self)
RaveFmiVolume_t * RaveFmiVolume_fromRaveField(RaveField_t *field)
RaveFmiVolume_t * RaveFmiVolume_fromRave(RaveCoreObject *object, const char *quantity)
RaveCoreObjectType RaveFmiVolume_TYPE
int RaveFmiVolume_initialize(RaveFmiVolume_t *self, int sweepCount)
RaveFmiVolume_t * RaveFmiVolume_fromPolarScan(PolarScan_t *scan, const char *quantity)
RaveFmiVolume_t * RaveFmiVolume_new(int sweepCount)
RaveFmiVolume_t * RaveFmiVolume_fromPolarVolume(PolarVolume_t *volume, const char *quantity)
PolarVolume_t * RaveFmiVolume_toRave(RaveFmiVolume_t *self, const char *quantity)
FmiImage * RaveFmiVolume_getSweep(RaveFmiVolume_t *self, int sweep)
struct _RaveFmiVolume_t RaveFmiVolume_t
RAVE_OBJECT_HEAD FmiImage * image
double * original
Definition fmi_image.h:154