libsim Versione 8.0.0
v7d_qctem.F90

Sample program for module qctem.

Sample program for module qctem

1! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
2! authors:
3! Davide Cesari <dcesari@arpa.emr.it>
4! Paolo Patruno <ppatruno@arpa.emr.it>
5
6! This program is free software; you can redistribute it and/or
7! modify it under the terms of the GNU General Public License as
8! published by the Free Software Foundation; either version 2 of
9! the License, or (at your option) any later version.
10
11! This program is distributed in the hope that it will be useful,
12! but WITHOUT ANY WARRANTY; without even the implied warranty of
13! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14! GNU General Public License for more details.
15
16! You should have received a copy of the GNU General Public License
17! along with this program. If not, see <http://www.gnu.org/licenses/>.
18! Program to quality control data with climatological values
19
20#include "config.h"
21
22program v7d_qctem
23
29USE modqc
32!use vol7d_dballeold_class
35use modqctem
36
37implicit none
38
39integer :: io,ier,i,iun,n,ind
40TYPE(l4f_handle) :: category
41character(len=512):: a_name,output_format, output_template
42
43 !tipi derivati.
44TYPE(optionparser) :: opt
45TYPE(geo_coord) :: coordmin, coordmax
46TYPE(datetime) :: time, timeiqc, timefqc
47type(qctemtype) :: v7dqctem
48type(vol7d) :: v7dana
49
50integer, parameter :: maxvar=10
51character(len=6) :: var(maxvar)=cmiss ! variables to elaborate
52#ifdef HAVE_DBALLE
53type(vol7d_dballe) :: v7ddballe,v7ddballeana,v7d_dba_out
54character(len=512) :: dsn='test1',user='test',password=''
55character(len=512) :: dsne='test',usere='test',passworde=''
56character(len=512) :: dsntem='test',usertem='test',passwordtem=''
57#endif
58integer :: years=imiss,months=imiss,days=imiss,hours=imiss,yeare=imiss,monthe=imiss,daye=imiss,houre=imiss,nvar=0
59doubleprecision :: lons=dmiss,lats=dmiss,lone=dmiss,late=dmiss
60logical :: height2level=.false.,version
61CHARACTER(len=512) :: input_file, output_file
62INTEGER :: optind, optstatus, ninput
63CHARACTER(len=20) :: operation
64TYPE(ARRAYOF_REAL):: grad
65real :: val
66integer :: iostat
67REAL, DIMENSION(11) :: perc_vals=(/(10.*i,i=0,10)/) !(/0.,10.,20.,30.,40.,50.,60.,70.,80.,90.,100./) !<the percentiles values to be computed, between 0. and 100.
68REAL, DIMENSION(size(perc_vals)-1) :: ndi !< normalized density index
69REAL, DIMENSION(size(perc_vals)) :: nlimbins !< the extreme values of data taken in account for ndi computation
70double precision, dimension(2) :: percentile
71TYPE(cyclicdatetime) :: cyclicdt !< cyclic date and time
72type(vol7d_level) :: level,levelo
73type(vol7d_timerange) :: timerange,timerangeo
74type(vol7d_var) :: varia,variao
75CHARACTER(len=vol7d_ana_lenident) :: ident
76integer :: indcana,indctime,indclevel,indctimerange,indcdativarr,indcnetwork,indcattr,iana
77INTEGER,POINTER :: w_s(:), w_e(:)
78logical :: file
79
80#ifdef HAVE_DBALLE
81namelist /odbc/ dsn,user,password,dsne,usere,passworde
82namelist /odbctem/ dsntem,usertem,passwordtem ! namelist to define DSN
83#endif
84namelist /switchtem/ height2level
85namelist /minmax/ years,months,days,hours,lons,lats,yeare,monthe,daye,houre,lone,late
86namelist /varlist/ var
87
88!init log4fortran
89ier=l4f_init()
90
91! unique name from launcher
92call l4f_launcher(a_name,a_name_force="v7d_qctem")
93
94! set a_name
95category=l4f_category_get_handle(a_name//".main")
96
97
98! define the option parser
99opt = optionparser_new(description_msg= &
100 'Spatial quality control: compute gradient; compute NDI from gradient; apply quality control', &
101 usage_msg='Usage: v7d_qctem [options] [inputfile1] [inputfile2...] [outputfile] \n&
102 &If input-format is of file type, inputfile ''-'' indicates stdin,'&
103#ifdef HAVE_DBALLE
104 //'if output-format is of database type, outputfile specifies &
105 &database access info in YRI form,' &
106#endif
107 //'if empty or ''-'', a suitable default is used. &
108&')
109
110! options for defining input
111CALL optionparser_add(opt, ' ', 'operation', operation, "run", help= &
112 'operation to execute: ''gradient'' compute gradient and write on files; '&
113 //'''ndi'' compute NDI from gradient;' &
114 //'''run'' apply quality control ')
115
116
117! options for defining output
118output_template = ''
119CALL optionparser_add(opt, ' ', 'output-format', output_format, 'native', help= &
120 'format of output file for "ndi" operation only, in the form ''name[:template]''; ''native'' for vol7d &
121 &native binary format (no template to be specified)'&
122#ifdef HAVE_DBALLE
123 //'; ''BUFR'' and ''CREX'' for corresponding formats, with template as an alias like ''synop'', ''metar'', &
124 &''temp'', ''generic'', empty for ''generic'''&
125#endif
126)
127
128! help options
129CALL optionparser_add_help(opt, 'h', 'help', help='show an help message and exit')
130CALL optionparser_add(opt, ' ', 'version', version, help='show version and exit')
131
132! parse options and check for errors
133CALL optionparser_parse(opt, optind, optstatus)
134
135IF (optstatus == optionparser_help) THEN
136 CALL exit(0) ! generate a clean manpage
137ELSE IF (optstatus == optionparser_err) THEN
138 CALL l4f_category_log(category,l4f_error,'in command-line parameters')
139 CALL raise_fatal_error()
140ENDIF
141IF (version) THEN
142 WRITE(*,'(A,1X,A)')'v7d_qctem',version
143 CALL exit(0)
144ENDIF
145
146
147if (operation /= "gradient" .and. operation /= "ndi" .and. operation /= "run") then
148 CALL optionparser_printhelp(opt)
149 CALL l4f_category_log(category, l4f_error, &
150 'argument to --operation is wrong')
151 CALL raise_fatal_error()
152end if
153
154
155! check output format/template
156n = word_split(output_format, w_s, w_e, ':')
157IF (n >= 2) THEN ! set output template if present
158 output_template = output_format(w_s(2):w_e(2))
159 output_format(w_e(1)+1:) = ' '
160ENDIF
161DEALLOCATE(w_s, w_e)
162
163if (operation == "ndi") then
164
165 ! check input/output files
166 i = iargc() - optind
167 IF (i < 0) THEN
168 CALL optionparser_printhelp(opt)
169 CALL l4f_category_log(category,l4f_error,'input file missing')
170 CALL raise_fatal_error()
171 ELSE IF (i < 1) THEN
172 CALL optionparser_printhelp(opt)
173 CALL l4f_category_log(category,l4f_error,'output file missing')
174 CALL raise_fatal_error()
175 ENDIF
176 CALL getarg(iargc(), output_file)
177
178 call init(levelo)
179 call init(timerangeo)
180 call init (variao)
181
182 do ninput = optind, iargc()-1
183 call getarg(ninput, input_file)
184
185 CALL l4f_category_log(category,l4f_info,"open file:"//t2c(input_file))
186 open (10,file=input_file,status="old")
187 read (10,*) level,timerange,varia
188
189 if (c_e(levelo)) then
190 if ( level /= levelo .or. timerange /= timerangeo .or. varia /= variao ) then
191 call l4f_category_log(category,l4f_error,"Error reading grad files: file are incoerent")
192 call raise_error("")
193 end if
194 else
195 levelo = level
196 timerangeo = timerange
197 variao = varia
198 end if
199
200 do while (.true.)
201 read (10,*,iostat=iostat) val
202 if (iostat /= 0) exit
203 if (val /= 0.) call insert(grad,val)
204 end do
205
206 close(10)
207 end do
208
209 call delete(v7dqctem%clima)
210 CALL init(v7dqctem%clima, time_definition=0)
211 call vol7d_alloc(v7dqctem%clima,nana=size(perc_vals)-1, &
212 nlevel=1, ntimerange=1, &
213 ndativarr=1, nnetwork=2,ntime=1,ndativarattrr=1,ndatiattrr=1)
214
215 call vol7d_alloc_vol(v7dqctem%clima,inivol=.true.)
216
217 v7dqctem%clima%level=level
218 v7dqctem%clima%timerange=timerange
219 v7dqctem%clima%dativar%r(1)=varia
220 v7dqctem%clima%dativarattr%r(1)=varia
221 call init(v7dqctem%clima%datiattr%r(1), btable="*B33209") ! NDI order number
222 cyclicdt = cyclicdatetime_new(chardate="/////////") !TMMGGhhmm
223 v7dqctem%clima%time(1)=cyclicdatetime_to_conventional(cyclicdt)
224
225 indctime=1
226 indclevel=1
227 indcattr=1
228 indcdativarr=1
229 indctimerange=1
230
231
232 indcnetwork=1
233 call init(v7dqctem%clima%network(indcnetwork),name="qctemsndi")
234
235 CALL l4f_category_log(category,l4f_info,"compute NDI spike")
236
237 CALL l4f_category_log(category,l4f_info,"compute percentile to remove the tails")
238 percentile = stat_percentile(abs(pack(grad%array(:grad%arraysize),mask=grad%array(:grad%arraysize) >= 0.)),(/10.,90./))
239 !print *,percentile
240
241 call normalizeddensityindex(abs(pack(grad%array(:grad%arraysize),&
242 mask=(abs(grad%array(:grad%arraysize)) < percentile(2) .and. grad%array(:grad%arraysize) >= 0. ))), perc_vals, ndi, nlimbins)
243
244 do indcana=1,size(perc_vals)-1
245 write(ident,'("#",i2.2,2i3.3)')0,0,nint(perc_vals(indcana))
246 call init(v7dqctem%clima%ana(indcana),ident=ident,lat=0d0,lon=0d0)
247 if (c_e(nlimbins(indcana)).and.c_e(ndi(indcana)))then
248 ind=index_c(tem_btable,varia%btable)
249 v7dqctem%clima%voldatir(indcana, indctime, indclevel, indctimerange, indcdativarr, indcnetwork)=&
250 nlimbins(indcana)*tem_a(ind) + tem_b(ind)
251 v7dqctem%clima%voldatiattrr(indcana, indctime, indclevel, indctimerange, indcdativarr, indcnetwork,indcattr)=&
252 ndi(indcana)*100.
253 end if
254 end do
255
256 indcnetwork=2
257 call init(v7dqctem%clima%network(indcnetwork),name="qctemgndi")
258
259 CALL l4f_category_log(category,l4f_info,"compute NDI gap")
260 CALL l4f_category_log(category,l4f_info,"compute percentile to remove the tails")
261 percentile = stat_percentile(abs(pack(grad%array(:grad%arraysize),mask=grad%array(:grad%arraysize) < 0.)),(/10.,90./))
262
263 call normalizeddensityindex(abs(pack(grad%array(:grad%arraysize),&
264 mask=(abs(grad%array(:grad%arraysize)) < percentile(2) .and. grad%array(:grad%arraysize) < 0. ))), perc_vals, ndi, nlimbins)
265
266 do indcana=1,size(perc_vals)-1
267 write(ident,'("#",i2.2,2i3.3)')0,0,nint(perc_vals(indcana))
268 call init(v7dqctem%clima%ana(indcana),ident=ident,lat=0d0,lon=0d0)
269 if (c_e(nlimbins(indcana)).and.c_e(ndi(indcana)))then
270 ind=index_c(tem_btable,varia%btable)
271 v7dqctem%clima%voldatir(indcana, indctime, indclevel, indctimerange, indcdativarr, indcnetwork)=&
272 nlimbins(indcana)*tem_a(ind) + tem_b(ind)
273 v7dqctem%clima%voldatiattrr(indcana, indctime, indclevel, indctimerange, indcdativarr, indcnetwork,indcattr)=&
274 ndi(indcana)*100.
275 end if
276 end do
277
278 call delete(grad)
279 call display(v7dqctem%clima)
280
281! print *,">>>>>> Clima Temporal Volume <<<<<<"
282! call display (v7dqctem%clima)
283
284 IF (output_format == 'native') THEN
285 IF (output_file == '-') THEN ! stdout_unit does not work with unformatted
286 CALL l4f_category_log(category, l4f_info, 'trying /dev/stdout as stdout unit.')
287 output_file='/dev/stdout'
288 ENDIF
289 iun = getunit()
290 OPEN(iun, file=output_file, form='UNFORMATTED', access='STREAM')
291 CALL export(v7dqctem%clima, unit=iun)
292 CLOSE(iun)
293 CALL delete(v7dqctem%clima)
294
295#ifdef HAVE_DBALLE
296 ELSE IF (output_format == 'BUFR' .OR. output_format == 'CREX' .OR. output_format == 'dba') THEN
297 IF (output_format == 'BUFR' .OR. output_format == 'CREX') THEN
298 IF (output_file == '-') THEN
299 CALL l4f_category_log(category, l4f_info, 'trying /dev/stdout as stdout unit.')
300 output_file='/dev/stdout'
301 ENDIF
302 file=.true.
303
304 ELSE IF (output_format == 'dba') THEN
305 file=.false.
306 ENDIF
307
308 IF (output_template == '') output_template = 'generic'
309 ! check whether wipe=file is reasonable
310 CALL init(v7d_dba_out, filename=output_file, format=output_format, &
311 dsn=output_file, file=file, write=.true., wipe=file)
312
313 v7d_dba_out%vol7d = v7dqctem%clima
314 CALL init(v7dqctem%clima) ! nullify without deallocating
315 CALL export(v7d_dba_out, template=output_template)
316 CALL delete(v7d_dba_out)
317#endif
318
319 end if
320
321 stop
322
323end if
324
325!------------------------------------------------------------------------
326! read the namelist to define DSN
327!------------------------------------------------------------------------
328
329open(10,file='qc.nml',status='old')
330read(10,nml=odbc,iostat=io)
331if ( io == 0 ) read(10,nml=odbctem,iostat=io)
332if ( io == 0 ) read(10,nml=switchtem,iostat=io)
333if ( io == 0 ) read(10,nml=minmax,iostat=io)
334if ( io == 0 ) read(10,nml=varlist,iostat=io)
335
336if (io /= 0 )then
337 call l4f_category_log(category,l4f_error,"Error reading namelist qc.nml")
338 call raise_error()
339end if
340close(10)
341
342
343!------------------------------------------------------------------------
344! Define what you want to QC
345!------------------------------------------------------------------------
346
347nvar=count(c_e(var))
348
349if (nvar == 0) then
350 call l4f_category_log(category,l4f_error,"0 variables defined")
351 call raise_error()
352end if
353 ! Definisco le date iniziale e finale
354CALL init(timeiqc, year=years, month=months, day=days, hour=hours)
355CALL init(timefqc, year=yeare, month=monthe, day=daye, hour=houre)
356!print *,"time extreme"
357call display(timeiqc)
358call display(timefqc)
359
360 ! Define coordinate box
361CALL init(coordmin,lat=lats,lon=lons)
362CALL init(coordmax,lat=late,lon=lone)
363
364!call getval(coordmin,lon=lon,lat=lat)
365print*,"lon lat minimum -> ",to_char(coordmin)
366!call getval(coordmax,lon=lon,lat=lat)
367print*,"lon lat maximum -> ",to_char(coordmax)
368
369!------------------------------------------------------------------------
370call l4f_category_log(category,l4f_info,"QC on "//t2c(nvar)//" variables")
371do i=1,nvar
372 call l4f_category_log(category,l4f_info,"QC on "//var(i)//" variable")
373enddo
374if (c_e(lons)) call l4f_category_log(category,l4f_info,"QC on "//t2c(lons)//" lon min value")
375if (c_e(lone)) call l4f_category_log(category,l4f_info,"QC on "//t2c(lone)//" lon max value")
376if (c_e(lats)) call l4f_category_log(category,l4f_info,"QC on "//t2c(lats)//" lat min value")
377if (c_e(late)) call l4f_category_log(category,l4f_info,"QC on "//t2c(late)//" lat max value")
378if (c_e(timeiqc)) call l4f_category_log(category,l4f_info,"QC on "//t2c(timeiqc)//" datetime min value")
379if (c_e(timefqc)) call l4f_category_log(category,l4f_info,"QC on "//t2c(timefqc)//" datetime max value")
380!------------------------------------------------------------------------
381
382
383CALL init(v7ddballeana,dsn=dsn,write=.false.,wipe=.false.,categoryappend="QCtarget-anaonly")
384call l4f_category_log(category,l4f_info,"start ana import")
385CALL import(v7ddballeana,var=var(:nvar),timei=timeiqc,timef=timefqc,coordmin=coordmin,coordmax=coordmax,anaonly=.true.)
386call vol7d_copy(v7ddballeana%vol7d,v7dana)
387call delete(v7ddballeana)
388
389!!$ an alternative to copy is:
390
391!!$idbhandle=v7ddballeana%idbhandle
392!!$CALL init(v7ddballe,dsn=dsn,user=user,password=password,write=.true.,wipe=.false.,categoryappend="QCtarget-"//t2c(time),&
393!!$ idbhandle=idbhandle)
394!!$call delete(v7ddballeana,preserveidbhandle=.true.)
395
396print *,"anagrafica:"
397call display(v7dana)
398
399do iana=1, size(v7dana%ana)
400
401 call l4f_category_log(category,l4f_info,"elaborate station "//trim(to_char(v7dana%ana(iana))))
402
403 ! Chiamo il costruttore della classe vol7d_dballe per il mio oggetto in import
404 CALL init(v7ddballe,dsn=dsn,write=.true.,wipe=.false.,categoryappend="QCtarget-"//t2c(time))
405 call l4f_category_log(category,l4f_info,"start data import")
406
407 CALL import(v7ddballe,var=var(:nvar),varkind=(/("r",i=1,nvar)/),&
408 anavar=(/"B07030"/),anavarkind=(/"r"/),&
409 attr=(/qcattrvarsbtables(1),qcattrvarsbtables(2),qcattrvarsbtables(3)/),attrkind=(/"b","b","b"/)&
410 ,timei=timeiqc,timef=timefqc, ana=v7dana%ana(iana))
411
412 ! this depend on witch version of dballe is in use: with dballe 6.6 comment this out
413 if (size(v7ddballe%vol7d%time)==0) then
414 CALL l4f_category_log(category,l4f_info,'skip empty volume: you are not using dballe >= 6.6 !')
415 call delete(v7ddballe)
416 cycle
417 end if
418
419 print *,"input volume"
420 call display(v7ddballe%vol7d)
421 call l4f_category_log(category,l4f_info,"end data import")
422 call l4f_category_log(category,l4f_info, "input N staz="//t2c(size(v7ddballe%vol7d%ana)))
423
424 call l4f_category_log(category,l4f_info,"start peeling")
425
426 !remove data invalidated and gross error only
427 !qcpar=qcpartype(0_int_b,0_int_b,0_int_b)
428 qcpar%att=bmiss
429 !call vol7d_peeling(v7ddballe%vol7d,v7ddballe%data_id,keep_attr=(/qcattrvarsbtables(3)/),purgeana=.true.)
430 call vol7d_peeling(v7ddballe%vol7d,keep_attr=(/qcattrvarsbtables(3)/),purgeana=.true.)
431 !call display(v7ddballe%vol7d)
432
433 call l4f_category_log(category,l4f_info, "filtered N time="//t2c(size(v7ddballe%vol7d%time)))
434
435 call l4f_category_log(category,l4f_info,"initialize QC")
436
437 ! chiamiamo il "costruttore" per il Q.C.
438
439 call init(v7dqctem,v7ddballe%vol7d,var(:nvar),timei=timeiqc,timef=timefqc, &
440 coordmin=v7dana%ana(iana)%coord, coordmax=v7dana%ana(iana)%coord,&
441! data_id_in=v7ddballe%data_id, &
442 dsne=dsne, usere=usere, passworde=passworde,&
443 dsntem=dsntem, usertem=usertem, passwordtem=passwordtem,&
444 height2level=height2level, operation=operation,&
445 categoryappend="temporal")
446
447! print *,">>>>>> Clima Temporal Volume <<<<<<"
448! call display(v7dqcspa%clima)
449
450 call alloc(v7dqctem)
451
452 ! temporal QC
453 call l4f_category_log(category,l4f_info,"start temporal QC")
454 call quacontem(v7dqctem,timemask= ( v7dqctem%v7d%time >= timeiqc .and. v7dqctem%v7d%time <= timefqc ))
455 call l4f_category_log(category,l4f_info,"end temporal QC")
456
457 ! prepare data_id to be recreated
458 !deallocate(v7ddballe%data_id)
459 !nullify(v7ddballe%data_id)
460
461 if (v7dqctem%operation == "run") then
462 call l4f_category_log(category,l4f_info,"start export data")
463 print *,"output volume"
464 call display(v7ddballe%vol7d)
465
466 ! data_id to use is the new one
467 !v7ddballe%data_id => v7dqctem%data_id_out
468 !CALL export(v7ddballe,attr_only=.true.)
469 CALL export(v7ddballe, attr_only=.true.)
470 call l4f_category_log(category,l4f_info,"end export data")
471 end if
472
473 call delete(v7dqctem)
474 ! data_id was allready deleted
475 !nullify(v7ddballe%data_id)
476 call delete(v7ddballe)
477
478end do
479
480call delete(v7dana)
481
482!close logger
483call l4f_category_delete(category)
484ier=l4f_fini()
485
486end program v7d_qctem
Destructor for finalizing an array object.
Method for inserting elements of the array at a desired position.
Operatore di valore assoluto di un intervallo.
Costruttori per le classi datetime e timedelta.
Functions that return a trimmed CHARACTER representation of the input variable.
Restituiscono il valore dell'oggetto in forma di stringa stampabile.
Export one or more geo_coordvect objects to a plain text file or to a file in ESRI/Shapefile format.
Import one or more geo_coordvect objects from a plain text file or for a file in ESRI/Shapefile forma...
Emit log message for a category with specific priority.
Global log4fortran destructor.
Global log4fortran constructor.
Allocazione di memoria.
Definition modqctem.F90:303
Add a new option of a specific type.
Compute a set of percentiles for a random variable.
This module defines usefull general purpose function and subroutine.
Classi per la gestione delle coordinate temporali.
Classes for handling georeferenced sparse points in geographical corodinates.
classe per la gestione del logging
Definitions of constants and functions for working with missing values.
Utilities and defines for quality control.
Definition modqc.F90:357
Controllo di qualità temporale.
Definition modqctem.F90:256
Module for parsing command-line optons.
Module for basic statistical computations taking into account missing data.
Classe per la gestione di un volume completo di dati osservati.
classe per import ed export di volumi da e in DB-All.e

Generated with Doxygen.