Opened 11 years ago
Closed 8 years ago
#50 closed task (fixed)
Upgrade CF Checker to use CDAT-5.x and udunits2
Reported by: | ros | Owned by: | ros |
---|---|---|---|
Priority: | medium | Milestone: | |
Component: | cf-checker | Version: | |
Keywords: | Cc: |
Description
Upgrade CF Checker to work with CDAT-5.x and udunits2
Change History (9)
comment:1 Changed 11 years ago by ros
- Owner changed from cf-checker@… to ros
- Status changed from new to assigned
comment:2 Changed 11 years ago by ros
comment:3 Changed 11 years ago by ros
Used the Python module ctypes to interface to the UDUNITS2 C library as no other Python interfaces to udunits2 are available.
A couple of the udunits functions used are no longer available with udunits2, nameley utIsTime() and utCalendar()
The udunits support gave me the following substitutions:
utIsTime()
Convert the unit to seconds. All time units should be convertible with seconds and if it fails then it was not a time unit.
if(ut_are_convertible(unit,udunits.ut_parse(self.unitSystem, "second", "UT_ASCII")):
Similarly for utCalendar() try converting units to seconds with a reference time.
comment:4 Changed 11 years ago by ros
The valid units are slightly different between udunits1 and udunits2.
In udunits1 units like M/S in uppercase were acceptable. udunits2 is more fussy (accurate!) and deems M/S as an invalid unit. This will lead to some netcdf files that used to be CF-compliant being flagged as uncompliant after the upgrade.
There are, however, a few inconsistencies. METRES and DAY or Day are valid units. I've sent an email to the udunits team to report this.
comment:5 Changed 11 years ago by ros
First working version of checker with CDAT-5.2 and udunits2 lodged at revision: r109
Note that in order for the script to load the libudunits2.so library it must be in the system library path or the environment variable LD_LIBRARY_PATH must be set.
comment:6 Changed 11 years ago by ros
When udunits2 is initialised (ut_read_xml) there is a lot of verbosity.
Definition of "kt" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 86, overrides prefixed-unit "1000000 kilogram" Definition of "microns" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 304, overrides prefixed-unit "1e-15 second" Definition of "ft" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 401, overrides prefixed-unit "1e-12 kilogram" Definition of "yd" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 409, overrides prefixed-unit "8.64e-20 second" Definition of "pt" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 630, overrides prefixed-unit "1e-09 kilogram" Definition of "at" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 1027, overrides prefixed-unit "1e-15 kilogram" Definition of "ph" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 1545, overrides prefixed-unit "3.6e-09 second" Definition of "nt" in "/home/ros/software/udunits2/share/udunits/udunits2-common.xml", line 1552, overrides prefixed-unit "1e-06 kilogram"
The solution, as described on the udunits mailing list (http://www.unidata.ucar.edu/support/help/MailArchives/udunits/msg00503.html) ,is to temporarily switch off printing of messages to stderr.
udunits.ut_set_error_message_handler(ut_ignore) self.unitSystem=udunits.ut_read_xml(self.udunits) ut_set_error_message_handler(ut_write_to_stderr)
comment:7 Changed 11 years ago by ros
Correction... calling ut_set_message_handler is not as straightforward since it takes as it's argument a pointer to a ut_error_message_handler object. See http://www.unidata.ucar.edu/software/udunits/udunits-2/udunits2lib.html#Messages
With help from the ctypes-users mailing list the solution is to use callback functions. It also isn't possible with ctypes to deal with varargs functions. A slight cheat is needed, where we misdeclare ut_error_message_handler omitting the va_list part and use that as the signature for any functions you want to pass.
So
uemh = CFUNCTYPE(c_int,c_char_p) ut_set_error_message_handler = CFUNCTYPE(uemh,uemh)(("ut_set_error_message_handler",udunits)) ut_write_to_stderr = uemh(("ut_write_to_stderr",udunits)) ut_ignore = uemh(("ut_ignore",udunits)) old_handler = ut_set_error_message_handler(ut_ignore) self.unitSystem=udunits.ut_read_xml(self.udunits) old_handler = ut_set_error_message_handler(ut_write_to_stderr)
This does the trick. No "Definition of ..." override warnings are now displayed.
r111
comment:8 Changed 11 years ago by ros
Merged cdat-5.1.0 branch into trunk.
cd cf-checker/trunk svn merge -r 105:117 http://cf-pcmdi.llnl.gov/svn/repository-cf/cf-checker/branches/cdat-5.1.0
comment:9 Changed 8 years ago by ros
- Resolution set to fixed
- Status changed from assigned to closed
source:cf-checker/branches/cdat-5.1.0/src/cfchecks-cdat-5.1.0.py r107 works with CDAT5.x and UDUNITS1