IODA Bundle
read.f90
Go to the documentation of this file.
1 
3 
4  use odc
5  use odc_config
6  use, intrinsic :: iso_fortran_env
7  implicit none
8 
9 contains
10 
11  subroutine check_call(err, msg, success)
12  integer, intent(in) :: err
13  character(*), intent(in) :: msg
14  logical, intent(inout) :: success
15 
16  if (err /= odc_success) then
17  write(error_unit, *) 'Failed API call: ', msg
18  write(error_unit, *) 'Error: ', odc_error_string(err)
19  success = .false.
20  end if
21  end subroutine
22 
23 
24  function test_count_lines() result(success)
25 
26  ! Test that we obtain the expected version number
27 
28  type(odc_reader) :: reader
29  type(odc_frame) :: frame
30  integer(8) :: frame_count, row_count, tmp_8
31  integer :: err, tmp_4
32  logical :: success
33 
34  success = .true.
35  call check_call(reader%open_path("../2000010106.odb"), "open ODB", success)
36  call check_call(frame%initialise(reader), "initialise frame", success)
37 
38  frame_count = 0
39  row_count = 0
40 
41  err = frame%next()
42  do while (err == odc_success)
43 
44  call check_call(frame%row_count(tmp_8), "row count", success)
45 
46  frame_count = frame_count + 1
47  row_count = row_count + tmp_8
48 
49  call check_call(frame%column_count(tmp_4), "column count", success)
50  if (tmp_4 /= 51) then
51  write(error_unit, *) 'Unexpected column count: ', tmp_4, ' /= 51'
52  success = .false.
53  endif
54 
55  err = frame%next()
56  end do
57 
58  if (err /= odc_iteration_complete) call check_call(err, "next frame", success)
59 
60  if (frame_count /= 333) then
61  write(error_unit, *) 'Unexpected frame count: ', frame_count, ' /= 333'
62  success = .false.
63  endif
64 
65  if (row_count /= 3321753) then
66  write(error_unit, *) 'Unexpected row count: ', row_count, ' /= 3321753'
67  success = .false.
68  endif
69 
70  call check_call(reader%close(), "close reader", success)
71 
72  end function
73 
74  function test_column_details() result(success)
75 
76  type(odc_reader) :: reader
77  type(odc_frame) :: frame
78  character(:), allocatable :: column_name, field_name
79  integer :: ncols, col, column_type, field, field_size, expected_offset, field_offset
80  integer :: element_size, element_size_doubles, bitfield_count
81  logical :: success
82 
83  character(23), parameter :: example_column_names(*) = [ character(23) :: &
84  "expver@desc", "andate@desc", "antime@desc", "seqno@hdr", "obstype@hdr", &
85  "obschar@hdr", "subtype@hdr", "date@hdr", "time@hdr", "rdbflag@hdr", &
86  "status@hdr", "event1@hdr", "blacklist@hdr", "sortbox@hdr", "sitedep@hdr", &
87  "statid@hdr", "ident@hdr", "lat@hdr", "lon@hdr", "stalt@hdr", &
88  "modoro@hdr", "trlat@hdr", "trlon@hdr", "instspec@hdr", "event2@hdr", &
89  "anemoht@hdr", "baroht@hdr", "sensor@hdr", "numlev@hdr", "varno_presence@hdr", &
90  "varno@body", "vertco_type@body", "rdbflag@body", "anflag@body", "status@body", &
91  "event1@body", "blacklist@body", "entryno@body", "press@body", "press_rl@body", &
92  "obsvalue@body", "aux1@body", "event2@body", "ppcode@body", "level@body", &
93  "biascorr@body", "final_obs_error@errstat", "obs_error@errstat", "repres_error@errstat", &
94  "pers_error@errstat", "fg_error@errstat"]
95 
96  integer, parameter :: example_column_types(*) = [ &
106 
107 
108  character(14), parameter :: column_10_bitfield_names(*) = [ character(14) :: &
109  "lat_humon", "lat_qcsub", "lat_override", "lat_flag", "lat_hqc_flag", "lon_humon", "lon_qcsub", &
110  "lon_override", "lon_flag", "lon_hqc_flag", "date_humon", "date_qcsub", "date_override", &
111  "date_flag", "date_hqc_flag", "time_humon", "time_qcsub", "time_override", "time_flag", &
112  "time_hqc_flag", "stalt_humon", "stalt_qcsub", "stalt_override", "stalt_flag", "stalt_hqc_flag" &
113  ]
114 
115  integer, parameter :: column_10_bitfield_sizes(*) = [ &
116  1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1]
117 
118  success = .true.
119  call check_call(reader%open_path("../2000010106.odb"), "open reader", success)
120  call check_call(frame%initialise(reader), "initialise frame", success)
121 
122  call check_call(frame%next(), "get the first frame", success)
123 
124  call check_call(frame%column_count(ncols), "column count", success)
125  if (ncols /= 51) then
126  write(error_unit, *) 'Expected 51 columns'
127  success = .false.
128  endif
129 
130  ! n.b. -- 1-based indexing!
131  do col = 1, ncols
132 
133  call check_call(frame%column_attributes(col, &
134  name=column_name, &
135  type=column_type, &
136  element_size=element_size, &
137  element_size_doubles=element_size_doubles, &
138  bitfield_count=bitfield_count), "column attrs", success)
139 
140  if (column_name /= trim(example_column_names(col))) then
141  write(error_unit,'(3a,i2,3a)') 'Unexpected column name ', column_name, &
142  ' for column ', col, ' (expected ', trim(example_column_names(col)), ')'
143  success = .false.
144  end if
145 
146  if (column_type /= example_column_types(col)) then
147  write(error_unit, '(a,i1,a,i2,a,i1,a)') 'Unexpected column type ', column_type, &
148  ' for column ', col, ' (expected ', example_column_types(col), ')'
149  success = .false.
150  end if
151 
152  if (element_size /= 8) then
153  write(error_unit, '(a,i1,a,i2,a)') 'Unexpected column data size ', element_size, &
154  ' for column ', col, ' (expected 8)'
155  success = .false.
156  end if
157 
158  if (element_size_doubles /= 1) then
159  write(error_unit, '(a,i1,a,i2,a)') 'Unexpected column doubles data size ', &
160  element_size_doubles, ' for column ', col, ' (expected 1)'
161  success = .false.
162  end if
163 
164  if (column_type == odc_bitfield) then
165  if (bitfield_count <= 0) then
166  write(error_unit, *) "Bitfields expected for bitfield column"
167  success = .false.
168  end if
169  else
170  if (bitfield_count /= 0) then
171  write(error_unit, *) "Unexpected bitfields for non-bitfield column"
172  success = .false.
173  end if
174  end if
175 
176  end do
177 
178  ! Test bitfields for column 10
179 
180  call check_call(frame%column_attributes(10, bitfield_count=bitfield_count), "bitfield count", success)
181  if (bitfield_count /= 25) then
182  write(error_unit, *) "Expected 25 bitfield fields for column 10. Got ", bitfield_count
183  success = .false.
184  end if
185 
186  expected_offset = 0
187  do field = 1, 25
188 
189  ! Look at column 10
190  call check_call(frame%bitfield_attributes(10, field, &
191  name=field_name, &
192  offset=field_offset, &
193  size=field_size), "bitfield attrs", success)
194 
195  if (field_name /= trim(column_10_bitfield_names(field))) then
196  write(error_unit, '(3a,i2,3a)') 'Unexpected field name ', field_name, ' for field ', &
197  field, ' (expected ', trim(column_10_bitfield_names(field)), ')'
198  success = .false.
199  end if
200 
201  if (field_size /= column_10_bitfield_sizes(field)) then
202  write(error_unit, '(a,i2,a,i2,a,i2,a)') 'Unexpected field size ', field_size, &
203  ' for field ', field, ' (expected ', column_10_bitfield_sizes(field), ')'
204  success = .false.
205  end if
206 
207  if (field_offset /= expected_offset) then
208  write(error_unit, '(a,i2,a,i2,a,i2,a)') 'Unexpected field offset ', field_offset, &
209  ' for field ', field, ' (expected ', expected_offset, ')'
210  success = .false.
211  end if
212 
213  expected_offset = expected_offset + field_size
214  end do
215 
216  call check_call(frame%free(), "free frame", success)
217  call check_call(reader%close(), "close reader", success)
218  end function
219 
220  function check_frame_2_values(array_data) result(success)
221 
222  real(8) :: array_data(:,:)
223  logical :: success
224 
225  integer :: row, i
226  integer, parameter :: expected_seqno(*) = [6106691, 6002945, 6003233, 6105819]
227  integer, parameter :: expected_obschar(*) = [537918674, 135265490, 135265490, 537918674]
228  integer(8) :: missing_integer
229  real(8) :: missing_double
230 
231  success = .true.
232 
233  call check_call(odc_missing_integer(missing_integer), "missing integer", success)
234  call check_call(odc_missing_double(missing_double), "missing double", success)
235 
236  do i = 1, 4
237  row = 1 + ((i-1) * 765)
238 
239  ! Expver
240  if (trim(transfer(array_data(row, 1), " ")) /= "0018") then
241  write(error_unit, *) 'unexpected expver in row ', row, ' (expected 0018, got ', &
242  transfer(array_data(row, 1), " ") ,')'
243  success = .false.
244  end if
245 
246  ! Test seqno (INTEGER)
247  if (int(array_data(row, 4)) /= expected_seqno(i)) then
248  write(error_unit, *) 'Unexpected seqno value. row=', row, ", expected=", &
249  expected_seqno(i), ", got=", int(array_data(row, 4))
250  success = .false.
251  end if
252 
253  ! obschar (BITFIELD)
254  if (int(array_data(row, 6)) /= expected_obschar(i)) then
255  write(error_unit, *) 'Unexpected obschar value. row=', row, ", expected=", &
256  expected_obschar(i), ", got=", int(array_data(row, 6))
257  success = .false.
258  end if
259 
260  ! Sortbox (INTEGER, missing)
261  if (int(array_data(row, 14)) /= missing_integer) then
262  write(error_unit, *) 'Expected value with set missing value. Got ', int(array_data(row, 14)), ', &
263  &expected ', missing_integer
264  success = .false.
265  end if
266 
267  ! repres_error (REAL, missing)
268  if (array_data(row, 49) /= missing_double) then
269  write(error_unit, *) 'Expected value with set missing value. Got ', array_data(row, 49), ', &
270  &expected ', missing_double
271  success = .false.
272  end if
273  end do
274 
275  end function
276 
277  function test_decode_columns_allocate() result(success)
278 
279  type(odc_reader) :: reader
280  type(odc_frame) :: frame
281  type(odc_decoder) :: decoder
282  integer(8) :: nrows, nrows2
283  integer :: ncols
284  logical :: success, column_major
285  real(8), pointer :: array_data(:,:)
286 
287  success =.true.
288  call check_call(reader%open_path("../2000010106.odb"), "open reader", success)
289  call check_call(frame%initialise(reader), "initialise frame", success)
290 
291  ! Read the second frame, because why not.
292  call check_call(frame%next(), "get first frame", success)
293  call check_call(frame%next(), "get second frame", success)
294 
295  call check_call(decoder%initialise(), "initialise decoder", success)
296  call check_call(decoder%defaults_from_frame(frame), "decoder from frame", success)
297  call check_call(decoder%decode(frame, nrows), "do decode", success)
298 
299  if (nrows /= 10000) then
300  write(error_unit, *) 'Unexpected number of rows decoded'
301  success = .false.
302  end if
303 
304  call check_call(decoder%row_count(nrows2), "decoder row count", success)
305  if (nrows2 /= 10000) then
306  write(error_unit, *) 'Got row count ', nrows, ' not 10000'
307  success = .false.
308  end if
309 
310  call check_call(decoder%column_count(ncols), "decoder column count", success)
311  if (ncols /= 51) then
312  write(error_unit, *) 'Got column count ', ncols, ' not 51'
313  success = .false.
314  end if
315 
316  call check_call(decoder%data(array_data, column_major), "get decoded data", success)
317 
318  if (any(shape(array_data) /= [10000, 51])) then
319  write(error_unit, *) 'Unexpected data dimensions'
320  success = .false.
321  end if
322 
323  if (.not. column_major) then
324  write(error_unit, *) 'Expected column major by default'
325  success = .false.
326  end if
327 
328  success = success .and. check_frame_2_values(array_data)
329 
330  call check_call(decoder%free(), "free decoder", success)
331  call check_call(reader%close(), "free reader", success)
332 
333  end function
334 
335  function test_decode_array_reuse() result(success)
336 
337  use, intrinsic :: iso_c_binding
338 
339  type(odc_reader) :: reader
340  type(odc_frame) :: frame
341  type(odc_decoder) :: decoder
342  integer(8) :: rows_decoded, nrows
343  integer :: ncols
344  logical :: success
345  real(8), target :: array_data(11000, 51)
346 
347  success = .true.
348  call check_call(reader%open_path("../2000010106.odb"), "open reader", success)
349  call check_call(frame%initialise(reader), "initialise frame", success)
350 
351  call check_call(frame%next(), "get first frame", success)
352 
353  call check_call(decoder%initialise(), "initialise decoder", success)
354  call check_call(decoder%defaults_from_frame(frame), "decoder frame defaults", success)
355  call check_call(decoder%set_data(array_data), "set array data", success)
356  call check_call(decoder%decode(frame, rows_decoded), "decode first frame", success)
357 
358  if (rows_decoded /= 10000) then
359  write(error_unit, *) 'Unexpected number of rows decoded'
360  success = .false.
361  end if
362 
363  call check_call(frame%next(), "get second frame", success)
364 
365  call check_call(decoder%decode(frame, rows_decoded), "decode second frame", success)
366 
367  if (rows_decoded /= 10000) then
368  write(error_unit, *) 'Unexpected number of rows decoded'
369  success = .false.
370  end if
371 
372  call check_call(decoder%row_count(nrows), "decoder row count", success)
373  if (nrows /= 11000) then
374  write(error_unit, *) 'Got row count ', nrows, ' not 11000'
375  write(error_unit, *) 'Row count should be related to the size of the decode target, not the decode data'
376  success = .false.
377  end if
378 
379  call check_call(decoder%column_count(ncols), "decoder column count", success)
380  if (ncols /= 51) then
381  write(error_unit, *) 'Got column count ', ncols, ' not 51'
382  success = .false.
383  end if
384 
385  success = success .and. check_frame_2_values(array_data)
386 
387  call check_call(decoder%free(), "free decoder", success)
388  call check_call(reader%close(), "close reader", success)
389 
390  end function
391 
392  function test_decode_aggregate() result(success)
393 
394  type(odc_reader) :: reader
395  type(odc_frame) :: frame
396  type(odc_decoder) :: decoder
397  integer(8) :: rows_decoded, nrows
398  integer :: ncols
399  logical :: success
400  real(8), pointer :: array_data(:,:)
401 
402  success = .true.
403  call check_call(reader%open_path("../2000010106.odb"), "open reader", success)
404  call check_call(frame%initialise(reader), "initialise frame", success)
405 
406  call check_call(frame%next(maximum_rows=99999_8), "get first (aggregate) frame", success)
407 
408  call check_call(decoder%initialise(), "initialise decoder", success)
409  call check_call(decoder%defaults_from_frame(frame), "decoder frame defaults", success)
410  call check_call(decoder%decode(frame, rows_decoded, nthreads=4), "decode threaded", success)
411 
412  if (rows_decoded /= 90000) then
413  write(error_unit, *) 'Unexpected number of rows decoded'
414  success = .false.
415  end if
416 
417  call check_call(decoder%row_count(nrows), "decoder row count", success)
418  if (nrows /= 90000) then
419  write(error_unit, *) 'Got row count ', nrows, ' not 90000'
420  success = .false.
421  end if
422 
423  call check_call(decoder%column_count(ncols), "decoder column count", success)
424  if (ncols /= 51) then
425  write(error_unit, *) 'Got column count ', ncols, ' not 51'
426  success = .false.
427  end if
428 
429  call check_call(decoder%data(array_data), "get array data", success)
430 
431  if (any(shape(array_data) /= [90000, 51])) then
432  write(error_unit, *) 'Unexpected data dimensions'
433  success = .false.
434  end if
435 
436  call check_call(decoder%free(), "free decoder", success)
437  call check_call(reader%close(), "close reader", success)
438 
439  end function
440 
441 end module
442 
443 
445 
446  use fapi_read_tests
447  implicit none
448 
449  logical :: success
450 
451  success = .true.
452  call check_call(odc_initialise_api(), "initialise api", success)
453 
454  success = test_count_lines() .and. success
455  success = test_column_details() .and. success
456  success = test_decode_columns_allocate() .and. success
457  success = test_decode_array_reuse() .and. success
458  success = test_decode_aggregate() .and. success
459 
460  if (.not. success) stop -1
461 
462 end program
int odc_initialise_api()
Definition: api/odc.cc:203
const char * odc_error_string(int err)
Definition: api/odc.cc:93
program fapi_general
Definition: encode.f90:421
logical function test_column_details()
Definition: read.f90:75
logical function test_decode_aggregate()
Definition: read.f90:393
logical function check_frame_2_values(array_data)
Definition: read.f90:221
logical function test_count_lines()
Definition: read.f90:25
logical function test_decode_columns_allocate()
Definition: read.f90:278
logical function test_decode_array_reuse()
Definition: read.f90:336
Definition: ColumnInfo.h:23
integer(c_int), parameter, public odc_real
Definition: odc.f90:9
integer, parameter, public odc_iteration_complete
Definition: odc.f90:17
integer(c_int), parameter, public odc_string
Definition: odc.f90:10
integer(c_int), parameter, public odc_bitfield
Definition: odc.f90:11
integer(c_int), parameter, public odc_integer
Definition: odc.f90:8
integer, parameter, public odc_success
Definition: odc.f90:16
subroutine check_call(err, desc)
Definition: odc_ls.f90:47