ncdf4/0000755000176200001440000000000014531443302011247 5ustar liggesusersncdf4/NAMESPACE0000644000176200001440000000036314377671533012511 0ustar liggesusersuseDynLib( ncdf4 ) export( nc_version, ncdim_def, ncvar_def, nc_open, ncvar_change_missval, nc_create, ncvar_add, ncatt_get, ncatt_put, ncvar_put, ncvar_get, nc_sync, nc_redef, nc_enddef, nc_close, ncvar_rename ) S3method( print, ncdf4 ) ncdf4/tools/0000755000176200001440000000000014377671533012430 5ustar liggesusersncdf4/tools/regenerate0000754000176200001440000000015014377671533014472 0ustar liggesusers#!/bin/sh rm ../Makefile rm ../configure rm ../src/Makevars aclocal -I . autoconf mv configure .. ncdf4/tools/netcdf.m40000644000176200001440000001165414377671533014144 0ustar liggesusersdnl dnl AC_PATH_NETCDF() dnl dnl This macro looks for version 4 of the netcdf library. Specifically, it looks for a dnl version-4 netcdf library that includes the script "nc-config", which is queried dnl for the information. "nc-config" first appeared in netcdf release 4.1-beta2, which dnl is what this is tested with. dnl dnl Defines NETCDF_LIBS, NETCDF_CPPFLAGS, NETCDF_LDFLAGS, and NETCDF_RPATH, or exits with an error message. dnl I.e., the intent is to have this used when the application REQUIRES the netcdf v4 library. dnl dnl version 1.0 dnl 21 Jan 2010 dnl David W. Pierce dnl Climate Research Division dnl Scripps Institution of Oceanography dnl dpierce@ucsd.edu dnl dnl ******************************************************************************* dnl This code is in the public domain, and can be used for any purposes whatsoever. dnl ******************************************************************************* dnl dnl AC_DEFUN([AC_PATH_NETCDF],[ AC_ARG_WITH( nc_config, [ --with-nc-config=path to nc-config script from netcdf v4 package], NC_CONFIG=$withval) dnl dnl dnl ================================================================================= dnl check for netcdf include directory dnl err=0 if test x$NC_CONFIG = x; then NC_CONFIG_SHORT=nc-config NC_CONFIG_FULLQUAL=nc-config NC_CONFIG_PATH=$PATH else echo "user specified nc-config is $NC_CONFIG" NC_CONFIG_SHORT=`basename $NC_CONFIG` NC_CONFIG_FULLQUAL=$NC_CONFIG NC_CONFIG_PATH=`dirname $NC_CONFIG` fi AC_CHECK_PROG( HAS_NC_CONFIG, [$NC_CONFIG_SHORT], [yes], [no], [$NC_CONFIG_PATH] ) if test x$HAS_NC_CONFIG = xno; then echo "-----------------------------------------------------------------------------------" echo "Error, nc-config not found or not executable. This is a script that comes with the" echo "netcdf library, version 4.1-beta2 or later, and must be present for configuration" echo "to succeed." echo " " echo "If you installed the netcdf library (and nc-config) in a standard location, nc-config" echo "should be found automatically. Otherwise, you can specify the full path and name of" echo "the nc-config script by passing the --with-nc-config=/full/path/nc-config argument" echo "flag to the configure script. For example:" echo " " echo "./configure --with-nc-config=/sw/dist/netcdf4/bin/nc-config" echo " " echo "Special note for R users:" echo "-------------------------" echo "To pass the configure flag to R, use something like this:" echo " " echo "R CMD INSTALL --configure-args=\"--with-nc-config=/home/joe/bin/nc-config\" ncdf4" echo " " echo "where you should replace /home/joe/bin etc. with the location where you have" echo "installed the nc-config script that came with the netcdf 4 distribution." echo "-----------------------------------------------------------------------------------" exit -1 fi echo "Using nc-config: $NC_CONFIG_FULLQUAL" echo "Output of nc-config --all:" $NC_CONFIG_FULLQUAL --all echo "---" dnl NETCDF_CC=`$NC_CONFIG_FULLQUAL --cc` NETCDF_LDFLAGS=`$NC_CONFIG_FULLQUAL --libs` NETCDF_CPPFLAGS=`$NC_CONFIG_FULLQUAL --cflags` NETCDF_VERSION=`$NC_CONFIG_FULLQUAL --version` dnl dnl ------------------------------------------------------------------- dnl Convert the --libs string to a rpath string. dnl Example input string: dnl "-L/home/pierce/src/packages/data/netcdf/netcdf-4.1.2/install/lib -lnetcdf -L/home/pierce/lib -lhdf5_hl -lhdf5 -lz -lcurl -Wl,-Bsymbolic-functions -lgssapi_krb5" dnl Example output string: dnl "-Wl,-rpath,/home/pierce/src/packages/data/netcdf/netcdf-4.1.2/install/lib -Wl,-rpath,/home/pierce/lib" dnl ------------------------------------------------------------------- NETCDF_RPATH=' ' echo "netcdf.m4: about to set rpath, here is source string: >$NETCDF_LDFLAGS<" for word in $NETCDF_LDFLAGS; do v2=`expr "$word" : '-L/'` if test $v2 -eq 3; then slibdir=${word:2} NETCDF_RPATH="$NETCDF_RPATH -Wl,-rpath,$slibdir" fi done echo "netcdf.m4: final rpath: $NETCDF_RPATH" dnl dnl The following will be either "yes" or "no" NETCDF_V4=`$NC_CONFIG_FULLQUAL --has-nc4` dnl dnl If we get here, we assume that netcdf exists. It might not if, for example, dnl the package was installed and nc-config is present, but then the libraries dnl were erased. Assume such deliberately broken behavior is not the case. dnl AC_DEFINE([HAVE_NETCDF],1,[Define if you have the NETCDF library, either v3 or v4]) dnl if test x$NETCDF_V4 = xyes; then AC_DEFINE([HAVE_NETCDF4],1,[Define if you have version 4 of the NETCDF library]) fi dnl ----------------------------------------------------------------------------------- dnl At this piont, $NETCDF_V4 will be either "yes" or "no" dnl echo "Netcdf library version: $NETCDF_VERSION" echo "Netcdf library has version 4 interface present: $NETCDF_V4" echo "Netcdf library was compiled with C compiler: $NETCDF_CC" dnl dnl Export our variables dnl AC_SUBST(NETCDF_CPPFLAGS) AC_SUBST(NETCDF_LDFLAGS) AC_SUBST(NETCDF_LIBS) AC_SUBST(NETCDF_VERSION) AC_SUBST(NETCDF_CC) AC_SUBST(NETCDF_RPATH) dnl ]) ncdf4/tools/configure.ac0000644000176200001440000001325714377671533014726 0ustar liggesusersAC_INIT AC_CONFIG_SRCDIR([src/Makevars.in]) echo "configure.ac: starting" AC_CONFIG_MACRO_DIR([tools]) : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then echo "Could not determine R_HOME" exit 1 fi #--------------------------------------------------------------------------- # The way R's package installation mechanism works, the C compiler and flags # are set by R, and not changable at the package level. So this is really # just for information purposes. Changing these values will NOT result in # a different compiler being used!! #--------------------------------------------------------------------------- CC=`${R_HOME}/bin/R CMD config CC` CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS` # for ncdf4, I've chosen to REQUIRE the netcdf v4 interface AC_PATH_NETCDF if test $NETCDF_V4 = "no"; then echo "-------------------------------------------------------------------" echo "ncdf4 REQUIRES the netcdf library be version 4 or above," echo "AND installed with HDF-5 support (i.e., the netcdf library must be" echo "compiled with the --enable-netcdf-4 flag). If you don't want to install" echo "the full version of netcdf-4 with HDF-5 support, then please install" echo "the old, deprecated ncdf package instead." echo "-------------------------------------------------------------------" exit -1 fi HAVE_NETCDF=TRUE NETCDF_LDFLAGS="$NETCDF_RPATH $NETCDF_LDFLAGS $LDFLAGS" AC_SUBST(NETCDF_CPPFLAGS) AC_SUBST(NETCDF_LDFLAGS) AC_SUBST(NETCDF_RPATH) AC_SUBST(HAVE_NETCDF) AC_CONFIG_FILES([src/Makevars]) AC_OUTPUT echo " " echo "********************** Results of ncdf4 package configure *******************" echo " " echo "netCDF v4 CPP flags = $NETCDF_CPPFLAGS" echo "netCDF v4 LD flags = $NETCDF_LDFLAGS" echo "netCDF v4 runtime path = $NETCDF_RPATH" echo " " echo "netCDF C compiler used = $NETCDF_CC" echo "R C compiler used = $CC $CFLAGS" echo " " echo "******************************************************************************" echo " " #--------------------------------------------------------------------- # Check to see if a different compiler is being used for netcdf and R #--------------------------------------------------------------------- set $NETCDF_CC NETCDF_CC_ARG1=$1 set $CC R_CC_ARG1=$1 TEST_EMIT_WARNING=0 if test x$NETCDF_CC_ARG1 != x$R_CC_ARG1 -o $TEST_EMIT_WARNING -eq 1; then #------------------------------------------------------------------------------ # By default, we emit a warning if the compilers of R and netcdf are different. # This happens with some regularity to naive users. #------------------------------------------------------------------------------ emit_warning=1 #------------------------------------------------------------------------------------------------- # Skip warning if one is gcc and the other is clang -- seems to bother some overly sensitive folks #------------------------------------------------------------------------------------------------- NETCDF_IS_GCC=0 if echo "$NETCDF_CC_ARG1" | grep -q "gcc"; then NETCDF_IS_GCC=1 else AC_PROG_CC([$NETCDF_CC_ARG1]) if test "z$GCC" = zyes; then NETCDF_IS_GCC=1 fi fi NETCDF_IS_CLANG=0 if echo "$NETCDF_CC_ARG1" | grep -q "clang"; then NETCDF_IS_CLANG=1 fi R_IS_GCC=0 if echo "$R_CC_ARG1" | grep -q "gcc"; then R_IS_GCC=1 else AC_PROG_CC([$R_CC_ARG1]) if test "z$GCC" = zyes; then R_IS_GCC=1 fi fi R_IS_CLANG=0 if echo "$R_CC_ARG1" | grep -q "clang"; then R_IS_CLANG=1 fi #------------------------------------------------------------- # We don't bother emitting the warning if the two compilers in # use are clang and gcc -- supposedly they are compatible #------------------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi #----------------------------------------------------- # Both same, but different exact names of compilers... # not sure if this actually guarantees success?? #----------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi echo "netcdf cc arg1: $NETCDF_CC_ARG1 R cc arg1: $R_CC_ARG1 R_IS_GCC: $R_IS_GCC R_IS_CLANG: $R_IS_CLANG NETCDF_IS_GCC: $NETCDF_IS_GCC NETCDF_IS_CLANG: $NETCDF_IS_CLANG emit_warning: $emit_warning" if test $emit_warning -eq 1 -o $TEST_EMIT_WARNING -eq 1; then echo " " echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" echo "Dear ncdf4 user: The software configuration tool thinks that perhaps different compilers are being" echo "used for R and the netcdf library. However, we all know that software configuration tools are" echo "not that smart. If ncdf4 compiles fine for you, then please ignore this message. However, if" echo "installation fails, it might be that you are using different compilers for R and the netcdf library." echo "If so, then you must create a new version of the netcdf library that was compiled with the same" echo "compiler that was used to install R (see information above). Then, try installing the ncdf4" echo "package again using that new netcdf library. If necessary, you can specify the location of" echo "the new nc-config (the one that uses the same compiler used by R) like this:" echo " " echo "R CMD INSTALL --configure-args=\"--with-nc-config=/home/joe/bin/nc-config\"" echo " " echo "(obviously, put in the correct path to YOUR nc-config, don't just use my example location!)" echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" echo " " fi fi ncdf4/tools/aclocal.m40000644000176200001440000000120214377671533014263 0ustar liggesusers# generated automatically by aclocal 1.11.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, # Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_include([netcdf.m4]) ncdf4/tools/winlibs.R0000644000176200001440000000064314377671533014225 0ustar liggesusers# Build against imagemagick static website. VERSION <- commandArgs(TRUE) if(!file.exists(sprintf("../windows/netcdf-%s/include/netcdf.h", VERSION))){ if(getRversion() < "3.3.0") setInternet2() download.file(sprintf("https://github.com/rwinlib/netcdf/archive/v%s.zip", VERSION), "lib.zip", quiet = TRUE) dir.create("../windows", showWarnings = FALSE) unzip("lib.zip", exdir = "../windows") unlink("lib.zip") } ncdf4/ChangeLog0000644000176200001440000000253314377704462013043 0ustar liggesusersRelease 1.22 (2023-03-01) Added "na_replace" argument to ncvar_put(). Release 1.21 (2023-01-05) Minor change to fix compatibility with latest version of R (removed C lang sprintf). Another small update to libraries linked for windows by request of Tomas Kalibera. Release 1.20 (2022-11-30) Small warning message bug fix (thank you to Javier Vaquero-Martinez!) and updates to windows Makefile requested by CRAN (Tomas Kalibera). Release 1.19 (2021-12-14) Changed as per request of R developers to build correctly on Windows using the new R toolchain (Rtools42). Specifically, added the supplided Makevars.ucrt to src/. Release 1.18 (2021-11-17) Fixed a bug in the way files with complicated nested groups were processed. Release 1.17 (2019-10-22): At the request of Jeroen Ooms, added some files to better support operation of the ncdf4 package in Windows. Release 1.0 (2010-02-23): Initial release of the ncdf4 package, which provides a high-level R interface to the netcdf library, versions 4 and earlier. Package ncdf4 REPLACES package ncdf, which supplied an interface to version 3 of the netcdf library. Due to changing coding standards requested by CRAN over the years, the NAMES of the functions in ncdf4 are different than the names in ncdf. For example, the function that used to be called "dim.def.ncdf" in ncdf is now called "ncdim_def" in ncdf4. ncdf4/man/0000755000176200001440000000000014377705264012042 5ustar liggesusersncdf4/man/ncdf4-package.Rd0000644000176200001440000000670714377671533014733 0ustar liggesusers\name{ncdf4-package} \alias{ncdf4-package} \title{Read, write, and create netCDF files (including version 4 format)} \description{ Read from or write to existing netCDF format files, or create new ones. } \references{ http://dwpierce.com/software } \details{ More information on this package, including detailed installation instructions, can be found at http://dwpierce.com/software. The netCDF data file format from Unidata is a platform-independent, binary file that also contains metadata describing the contents and format of the data in the file. Version 4 of the netcdf library stores data in HDF5 format files; earlier versions stored data in a custom format. The R package ncdf4 can read either format. NetCDF files contain one or more variables, which are usually structured as regular N-dimensional arrays. For example, you might have a variable named "Temperature" that is a function of longitude, latitude, and height. NetCDF files also contain dimensions, which describe the extent of the variables' arrays. In our Temperature example, the dimensions are "longitude", "latitude", and "height". Data can be read from or written to variables in arbitrary hyperslabs (for example, you can read or write all the Temperature values at a given height, or at a given latitude). The R package 'ncdf4' allows reading from, writing to, and creation of netCDF files, either netCDF version 3 or (optionally) netCDF version 4. If you choose to create version 4 output files, be aware that older netcdf software might only be able to read version 3 files. Note that both the netCDF library and the HDF5 library must already be installed on your machine for this R interface to the library to work. If you are new to netCDF files, they can be a little overwhelming, so here is a brief sketch of what documentation you need to read next. If you want to READ data from an already-existing netCDF file, first call \code{\link[ncdf4]{nc_open}} to open the file, then call \code{\link[ncdf4]{ncvar_get}} to read the data from a variable in the file. If you want to WRITE data to a new netCDF file, the procedure is to first define the dimensions your data array has, then define the variable, then create the file. So, first call \code{\link[ncdf4]{ncdim_def}} to define the dimensions that your data exists along (for example, latitude, longitude, and time). Then call \code{\link[ncdf4]{ncvar_def}} to define a variable that uses those dimensions, and will hold your data. Then call \code{\link[ncdf4]{nc_create}} to create the netCDF file. Finally, call \code{\link[ncdf4]{ncvar_put}} to write your data to the newly created netCDF file, and \code{\link[ncdf4]{nc_close}} when you are done. Not all features of netcdf-4 are supported yet. This version supports compression, chunking, groups, vlen strings, and multiple unlimited dimensions. User-defined types and vlen data arrays (variable-length arrays) are not supported yet. } \seealso{ \code{\link[ncdf4]{print.ncdf4}}, \code{\link[ncdf4]{nc_open}}, \code{\link[ncdf4]{nc_close}}, \code{\link[ncdf4]{nc_create}}, \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{ncvar_def}}, \code{\link[ncdf4]{ncvar_get}}, \code{\link[ncdf4]{ncvar_put}}, \code{\link[ncdf4]{ncvar_change_missval}}, \code{\link[ncdf4]{ncatt_get}}, \code{\link[ncdf4]{ncatt_put}}, \code{\link[ncdf4]{nc_sync}}, \code{\link[ncdf4]{nc_redef}}. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \keyword{utilities} ncdf4/man/ncvar_rename.Rd0000644000176200001440000000637514377671533015005 0ustar liggesusers\name{ncvar_rename} \alias{ncvar_rename} \title{Rename an Existing Variable in a netCDF File} \description{ Renames an existing variable that currently is part of a netCDF file that is on disk. } \usage{ ncvar_rename( nc, old_varname, new_varname, verbose=FALSE ) } \arguments{ \item{nc}{The already-existing netCDF file that we want to manipulate. This must be a value of class "ncdf4" returned by a call to \code{\link[ncdf4]{nc_open}}\code{(...,write=TRUE).}} \item{old_varname}{The variable in the file that is to be renamed. This can be a string with the name of the variable to be renamed, or a value of class "ncvar4" returned by a call to \code{ncvar_def()}.} \item{new_varname}{A string containing the new name of the variable.} \item{verbose}{If true, run verbosely.} } \value{ The updated value of nc that contains the new name. This needs to replace the old value of nc in the code. I..e, \code{ncid <- ncvar_rename( ncid, ... )}. } \references{ http://dwpierce.com/software } \details{ This call allows you to rename a variable that already exists in a netCDF file. NOTE that the return value of this routine should replace the old netCDF file handle that you were using. This newly returned value reflects the modifications to the file that were accomplished by calling this routine. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{nc_create}}, \code{\link[ncdf4]{ncvar_def}}. } \examples{ \dontrun{ #=================================================================== # PART 1. MAKE A TEST NETCDF FILE THAT WE WILL MANIPULATE IN PART 2 #=================================================================== #---------------- # Make dimensions #---------------- xvals <- 1:360 yvals <- -90:90 nx <- length(xvals) ny <- length(yvals) xdim <- ncdim_def( 'Lon', 'degreesE', xvals ) ydim <- ncdim_def( 'Lat', 'degreesE', yvals ) tdim <- ncdim_def( 'Time', 'days since 1900-01-01', 0, unlim=TRUE ) #--------- # Make var #--------- mv <- 1.e30 # missing value var_temp <- ncvar_def( 'Temperature', 'K', list(xdim,ydim,tdim), mv ) #--------------------- # Make new output file #--------------------- output_fname <- 'test_real3d.nc' ncid_new <- nc_create( output_fname, list(var_temp)) #------------------------------- # Put some test data in the file #------------------------------- data_temp <- array(0.,dim=c(nx,ny,1)) for( j in 1:ny ) for( i in 1:nx ) data_temp[i,j,1] <- sin(i/10)*sin(j/10) ncvar_put( ncid_new, var_temp, data_temp, start=c(1,1,1), count=c(nx,ny,1)) #-------------------------- # Close our new output file #-------------------------- nc_close( ncid_new ) #=========================================================================== # PART 2. RENAME A NEW VARIABLE TO THE FILE #=========================================================================== #------------------------------------------------- # Open the existing file we're going to manipulate #------------------------------------------------- ncid_old <- nc_open( output_fname, write=TRUE ) old_varname <- 'Temperature' new_varname <- 'T' ncid_old <- ncvar_rename( ncid_old, old_varname, new_varname ) print(ncid_old) nc_close( ncid_old ) # Clean up our example file.remove( output_fname ) } } \keyword{utilities} ncdf4/man/nc_enddef.Rd0000644000176200001440000000310514377671533014236 0ustar liggesusers\name{nc_enddef} \alias{nc_enddef} \title{Takes a netCDF file out of define mode} \description{ Changes a netCDF that is currently in define mode back into data mode. } \usage{ nc_enddef( nc ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned by either function \code{\link[ncdf4]{nc_open}} or function \code{\link[ncdf4]{nc_create}}, indicating what file to operate upon.} } \references{ http://dwpierce.com/software } \details{ NOTE: typical users will never need to use this function. NetCDF files can be in "define mode", at which time dimensions and variables can be defined, or new attributes added to a file, or in "data mode", at which time data can be read from the file. This call puts a file that is currently in define mode back into data mode. The ncdf4 package manages this process transparently, so normally, an end user will not need to call this explicitly. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{nc_redef}}. } \examples{ # This function is for advanced useage only, and will never # be needed by the typical users R code. } \note{ The typical user will never need this call, nor will ever have to worry about "define mode" or "data mode". THIS CALL IS PROVIDED FOR ADVANCED USERS ONLY! If the user goes through this package's standard functional interface, the file will always automatically be set to whatever mode it needs to be in without the user having to do anything. For example, the call to write an attribute (\code{\link[ncdf4]{ncatt_put}}) handles this automatically. } \keyword{utilities} ncdf4/man/nc_version.Rd0000644000176200001440000000072314377671533014501 0ustar liggesusers\name{nc_version} \alias{nc_version} \title{Report version of ncdf4 library} \description{ Returns a string that is the version number of the ncdf4 package. } \usage{ nc_version() } \value{ A string (not float) that is the version number of the ncdf4 package. } \references{ http://dwpierce.com/software } \details{ Note that the returned value it is a string, not a floating point number. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \keyword{utilities} ncdf4/man/print.ncdf4.Rd0000644000176200001440000000204714377671533014466 0ustar liggesusers\name{print.ncdf4} \alias{print.ncdf4} \title{Print Information About a netCDF File} \description{ Prints information about a netCDF file, including the variables and dimensions it contains. } \usage{ \method{print}{ncdf4}( x, ... ) } \arguments{ \item{x}{An object of class "ncdf4".} \item{...}{Extra arguments are passed to the generic print function.} } \references{ http://dwpierce.com/software } \details{ NetCDF files contain variables, which themselves have dimensions. This routine prints out useful information about a netCDF file's variables and dimensions. It is overloaded on the regular print function, so if "nc" is an object of class "ncdf4", then just calling \code{print(nc)} will suffice. Objects of class "ncdf4" are returned from \code{\link[ncdf4]{nc_open}} and \code{\link[ncdf4]{nc_create}}. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncvar_def}} } \examples{ \dontrun{ # Open a netCDF file, print information about it nc <- nc_open( "salinity.nc" ) print(nc) } } \keyword{utilities} ncdf4/man/nc_create.Rd0000644000176200001440000000441514377671533014261 0ustar liggesusers\name{nc_create} \alias{nc_create} \title{Create a netCDF File} \description{ Creates a new netCDF file on disk, given the variables the new file is to contain. } \usage{ nc_create( filename, vars, force_v4=FALSE, verbose=FALSE ) } \arguments{ \item{filename}{Name of the netCDF file to be created.} \item{vars}{Either an object of class \code{ncvar4} describing the variable to be created, or a vector (or list) of such objects to be created.} \item{force_v4}{If TRUE, then the created output file will always be in netcdf-4 format (which supports more features, but cannot be read by version 3 of the netcdf library). If FALSE, then the file is created in netcdf version 3 format UNLESS the user has requested features that require version 4. Deafult is FALSE.} \item{verbose}{If TRUE, then information is printed while the file is being created.} } \value{ An object of class \code{ncdf4}, which has the fields described in \code{\link[ncdf4]{nc_open}}. } \references{ http://dwpierce.com/software } \details{ This routine creates a new netCDF file on disk. The routine must be called with the variables that will be created in the file. Keep in mind that the new file may not actually be written to disk until \code{\link[ncdf4]{nc_close}} is called. Always call \code{\link[ncdf4]{nc_close}} when you are done with your file, or before exiting R! } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{ncvar_def}}. } \examples{ \dontrun{ # Define an integer dimension dimState <- ncdim_def( "StateNo", "count", 1:50 ) # Make an integer variable. Note that an integer variable can have # a double precision dimension, or vice versa; there is no fixed # relationship between the precision of the dimension and that of the # associated variable. We just make an integer variable here for # illustration purposes. varPop <- ncvar_def("Pop", "count", dimState, -1, longname="Population", prec="integer") # Create a netCDF file with this variable ncnew <- nc_create( "states_population.nc", varPop ) # Write some values to this variable on disk. popAlabama <- 4447100 ncvar_put( ncnew, varPop, popAlabama, start=1, count=1 ) nc_close(ncnew) # Clean up example file.remove( "states_population.nc" ) } } \keyword{utilities} ncdf4/man/nc_close.Rd0000644000176200001440000000167414377671533014127 0ustar liggesusers\name{nc_close} \alias{nc_close} \title{Close a netCDF File} \description{ Closes an open netCDF file, which flushes any unwritten data to disk. Always close a netCDF file when you are done with it! You are risking data loss otherwise. } \usage{ nc_close( nc ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned by either function \code{\link[ncdf4]{nc_open}} or function \code{\link[ncdf4]{nc_create}}.} } \references{ http://dwpierce.com/software } \details{ Data written to a netCDF file is cached in memory, for better performance. This data is only written out to disk when the file is closed. Therefore, always remember to close a netCDF file when done with it. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{nc_sync}}. } \examples{ \dontrun{nc <- nc_open("salinity.nc")} \dontrun{data <- ncvar_get( nc ) # Read the "only" var in the file} \dontrun{nc_close(nc)} } \keyword{utilities} ncdf4/man/ncvar_change_missval.Rd0000644000176200001440000000742214377671533016513 0ustar liggesusers\name{ncvar_change_missval} \alias{ncvar_change_missval} \title{Change the Missing Value For a netCDF Variable} \description{ Changes the missing_value attribute for a netCDF variable. } \usage{ ncvar_change_missval( nc, varid, missval ) } \arguments{ \item{nc}{An object of class \code{ncdf4}, as returned by \code{\link[ncdf4]{nc_open}}\code{(...,write=TRUE)} or \code{\link[ncdf4]{nc_create}}.} \item{varid}{Either the name of the variable or an \code{ncvar} object indicating whose missing value will be changed.} \item{missval}{The missing value to change to.} } \references{ http://dwpierce.com/software } \details{ Note: this specialty function is only used to change a variable's missing value after it has already been defined, which is rare. The proper way to set a variable's missing value in the first place is by setting the missing value argument to routine \code{\link[ncdf4]{ncvar_def}} appropriately. Missing values are special values in netCDF files whose value is to be taken as indicating the data is "missing". This is a convention, and is indicated by the netCDF variable having an attribute named "missing_value" that holds this number. This function sets the "missing_value" attribute for a variable. R uses a similar concept to indicate missing values, the "NA" value. When the ncdf library reads in data set from a pre-existing file, all data values that equal that variable's missing value attribute appear to the R code as being "NA" values. When the R code writes values to a netCDF variable, any "NA" values are set to that variable's missing value before being written out. This makes the mapping between netCDF's "missing_value" attribute and R's "NA" values transparent to the user. For this to work, though, the user still has to specify a missing value for a variable. Usually this is specified when the variable is created, as a required argument to \code{\link[ncdf4]{ncvar_def}}. However, sometimes it is useful to add (or change) a missing value for variable that already exists in a disk file. This function enables that. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncvar_def}}. } \examples{ \dontrun{ # Make an example netCDF file with a given missing value. We will # then change the missing value in the file using ncvar_change_missval origMissVal <- -1. dimX <- ncdim_def( "X", "meters", 1:7 ) varAlt <- ncvar_def( "Altitude", "km", dimX, origMissVal ) ncnew <- nc_create( "transect.nc", varAlt ) data <- c(10.,2.,NA,1.,7.,NA,8.) ncvar_put( ncnew, varAlt, data ) nc_close(ncnew) # At this point, the actual data values in the netCDF # file will be: 10 2 -1 1 7 -1 8 # because the "NA" values were filled with the missing # value, -1. Also, the missing_value attribute of variable # "varAlt" will be equal to -1. # Now change the missing value to something else. Remember # we have to open the file as writable to be able to change # the missing value on disk! newMissVal <- 999.9 nc <- nc_open( "transect.nc", write=TRUE ) varname <- "Altitude" data <- ncvar_get( nc, varname ) # data now has: 10., 2., NA, 1., 7., NA, 8. print(data) ncvar_change_missval( nc, varname, newMissVal ) ncvar_put( nc, varname, data ) nc_close(nc) # Now, the actual data values in the netCDF file will be: # 10 2 999.9 1 7 999.9 8 # and the variables "missing_value" attributre will be 999.9 # **NOTE** that we had to explicitly read in the data and write # it out again in order for the on-disk missing values in the # data array to change! The on-disk missing_value attribute for # the variable is set automatically by this function, but it is # up to you whether or not you want to read in all the existing # data and change the values to the new missing value. # Clean up our example file.remove( "transect.nc" ) } } \keyword{utilities} ncdf4/man/ncvar_get.Rd0000644000176200001440000001434414377671533014310 0ustar liggesusers\name{ncvar_get} \alias{ncvar_get} \title{Read data from a netCDF file} \description{ Reads data from an existing netCDF file. } \usage{ ncvar_get(nc, varid=NA, start=NA, count=NA, verbose=FALSE, signedbyte=TRUE, collapse_degen=TRUE, raw_datavals=FALSE ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned by either function \code{\link[ncdf4]{nc_open}} or function \code{\link[ncdf4]{nc_create}}), indicating what file to read from.} \item{varid}{What variable to read the data from. Can be a string with the name of the variable or an object of class \code{ncvar4} If left unspecified, the function will determine if there is only one variable in the file and, if so, read from that. If left unspecified and there are multiple variables in the file, an error is generated. This argument can also, optionally, specify the name of a dimension (usually the unlimited dimension) in order to read values from a coordinate variable. Note this is not usual practice, because the \code{ncdim} object already contains all the dimension's values in the field named "vals". However, it can sometimes be faster to turn off this automatic reading of the unlimited dimension's values by using \code{nc_open(filename, readunlim=FALSE)}, then read the dimension values in later with this function.} \item{start}{A vector of indices indicating where to start reading the passed values (beginning at 1). The length of this vector must equal the number of dimensions the variable has. Order is X-Y-Z-T (i.e., the time dimension is last). If not specified, reading starts at the beginning of the file (1,1,1,...).} \item{count}{A vector of integers indicating the count of values to read along each dimension (order is X-Y-Z-T). The length of this vector must equal the number of dimensions the variable has. If not specified and the variable does NOT have an unlimited dimension, the entire variable is read. As a special case, the value "-1" indicates that all entries along that dimension should be read.} \item{verbose}{If TRUE, then progress information is printed.} \item{signedbyte}{If TRUE (default), then on-disk byte variables are interpreted as signed. This is in accord with the netCDF standard. If FALSE, then on-disk byte variables are interpreted as unsigned.} \item{collapse_degen}{If TRUE (the default), then degenerate (length==1) dimensions in the returned array are removed.} \item{raw_datavals}{If TRUE, then the actual raw data values from the file are returned with no conversion to NA (if equal to the missing value/fill value) or scale/offset applied. Default is FALSE.} } \references{ http://dwpierce.com/software } \details{ This routine reads data values from a variable in an existing netCDF file. The file must already have been opened with a call to \code{\link[ncdf4]{nc_open}}. Returned values will be in ordinary R double precision if the netCDF variable type is float or double. Returned values will be in R's integer storage mode if the netCDF variable type is short or int. Returned values will be of character type if the netCDF variable is of character type. Values of "NA" are supported; values in the data file that match the variable's missing value attribute are automatically converted to "NA" before being returned to the user. See \code{\link[ncdf4]{ncvar_change_missval}} for more information. Data in a netCDF file is conceived as being a multi-dimensional array. The number and length of dimensions is determined when the variable is created. The 'start' and 'count' indices that this routine takes indicate where the writing starts along each dimension, and the count of values along each dimension to write. Note that the special count value "-1" means "all the values along that dimension". If the variable in the netCDF file has a scale and/or offset attribute defined, the returned data are automatically and silently scaled and/or offset as requested. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncvar_put}}. } \examples{ \dontrun{ # Start with the simplest example. If the file only has one variable in it, # you can read the data as easily as this: # nc <- nc_open("salinity.nc") # NOTE how not specifying varid reads the "only" var in the file data <- ncvar_get( nc ) nc_close(nc) # In this next example we read values from file "writevals.nc", which is created by # the R code in the example section for function "ncvar_put". We open the # file with readunlim=FALSE for potentially faster access, and to illustrate # (below) how to read in the unlimited dimension values. # nc <- nc_open( "writevals.nc", readunlim=FALSE ) print(paste("The file has",nc$nvars,"variables")) # This illustrates how to read all the data from a variable v1 <- nc$var[[1]] data1 <- ncvar_get( nc, v1 ) # by default, reads ALL the data print(paste("Data for var ",v1$name,":",sep="")) print(data1) # This shows how the shape of the read data is preserved v2 <- nc$var[[2]] data2 <- ncvar_get( nc, v2 ) print(paste("Var 2 has name",v2$name,"and is of shape",dim(data2), ". Here are the values:")) print(data2) # This illustrates how to read data one timestep at a time. In this # example we will elaborately show how to deal with a variable whose # shape is completely unknown (i.e., how many dimensions, and what their # sizes are). We will also, for illustration of a common case, show how # to read in the values of the time dimension at each timestep. v3 <- nc$var[[3]] varsize <- v3$varsize ndims <- v3$ndims nt <- varsize[ndims] # Remember timelike dim is always the LAST dimension! for( i in 1:nt ) { # Initialize start and count to read one timestep of the variable. start <- rep(1,ndims) # begin with start=(1,1,1,...,1) start[ndims] <- i # change to start=(1,1,1,...,i) to read timestep i count <- varsize # begin w/count=(nx,ny,nz,...,nt), reads entire var count[ndims] <- 1 # change to count=(nx,ny,nz,...,1) to read 1 tstep data3 <- ncvar_get( nc, v3, start=start, count=count ) # Now read in the value of the timelike dimension timeval <- ncvar_get( nc, v3$dim[[ndims]]$name, start=i, count=1 ) print(paste("Data for variable",v3$name,"at timestep",i, " (time value=",timeval,v3$dim[[ndims]]$units,"):")) print(data3) } nc_close(nc) } } \keyword{utilities} ncdf4/man/ncatt_get.Rd0000644000176200001440000000740314377671533014306 0ustar liggesusers\name{ncatt_get} \alias{ncatt_get} \title{Get attribute from netCDF file} \description{ Reads an attribute from a netCDF file. } \usage{ ncatt_get( nc, varid, attname=NA, verbose=FALSE ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned from \code{\link[ncdf4]{nc_open}}), indicating what file to read from.} \item{varid}{The variable whose attribute is to be read. Can be a character string with the variable's name or an object of class \code{ncvar4}. As a special case, if varid==0, then a global (file) attribute will be read rather than a particular variable's attribute. In netcdf version 4 files, attributes can be stored in a group without an associated variable (as if they were global attributes for the group instead of for the file). In this case, set varid to a string holding the fully qualified group name using forward slashes for subgroups. For example, "group1/metadata".} \item{attname}{Name of the attribute to read; if not specified, a list containg ALL attributes of the selected variable or file is returned.} \item{verbose}{If TRUE, then debugging information is printed.} } \value{ If an attribute name is supplied (i.e., argument attname is given), this returns a list with two components, "hasatt" and "value". "hasatt" is TRUE if the named attribute was found, and FALSE otherwise. "value" is the (possibly vector) value of the attribute. If the on-disk type of the attribute is short or integer, then an integer value is returned. If the on-disk type is float or double, than a double value is returned. If the on-disk type is character, than a character string is returned. If no attribute name is supplied, then this returns a list containing ALL the attributes for the specified variable along with their associated values. For example, if attlist is the list returned by this call, then names(attlist) shows all the attributes defined for the variable, and attlist[[N]] is the value of the N'th attribute. } \references{ http://dwpierce.com/software } \details{ This function gets an attribute from a netCDF variable (or a global attribute from a netCDF file, if the passed argument "varid" is zero). Multiple attributes are returned in a vector. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncatt_put}}. } \examples{ \dontrun{ # Make a simple netCDF file filename <- "atttest_types.nc" dim <- ncdim_def( "X", "inches", 1:12 ) var <- ncvar_def( "Data", "unitless", dim, -1 ) ncnew <- nc_create( filename, var ) # Define some attributes of various types attvaldbl <- 3.1415926536 ncatt_put( ncnew, var, "testatt_dbl", attvaldbl, prec="double" ) attvalfloat <- c(1.0,4.0,9.0,16.0) ncatt_put( ncnew, var, "testatt_float", attvalfloat ) # varid=0 means it is a global attribute ncatt_put( ncnew, 0, "globalatt_int", 32000, prec="int" ) ncatt_put( ncnew, 0, "globalatt_short", 7, prec="short" ) ncatt_put( ncnew, 0, "description", "this is a test file with attributes of various types") nc_close(ncnew) # Now illustrate the use of the ncatt_get function by reading them back in doitfor <- function( nc, var, attname ) { av <- ncatt_get( nc, var, attname ) if( av$hasatt ) { print(paste("File",nc$filename,", var",var,"DOES have attribute", attname)) print(paste("Storage mode:",storage.mode(av$value))) print("Attribute value:") print(av$value) } else { print(paste("File",nc$filename,", var",var,"does NOT have", "attribute", attname)) } } nc <- nc_open( filename ) var <- "Data" doitfor( nc, var, "testatt_dbl" ) doitfor( nc, var, "testatt_float" ) doitfor( nc, var, "testatt_wacko" ) doitfor( nc, 0, "globalatt_int" ) doitfor( nc, 0, "globalatt_short" ) doitfor( nc, 0, "description" ) nc_close( nc ) # Clean up after our test file.remove( filename ) } } \keyword{utilities} ncdf4/man/ncatt_put.Rd0000644000176200001440000000543114377671533014336 0ustar liggesusers\name{ncatt_put} \alias{ncatt_put} \title{Put an attribute into a netCDF file} \description{ Writes an attribute to a netCDF file. } \usage{ ncatt_put( nc, varid, attname, attval, prec=NA, verbose=FALSE, definemode=FALSE ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned from \code{\link[ncdf4]{nc_open}}), indicating what file to write to.} \item{varid}{The variable whose attribute is to be written. Can be a character string with the variable's name, an object of class \code{ncvar4}, or an id contained in the "id" field of a \code{ncvar} object. As a special case, if varid==0, then a global attribute is written instead of a variable's attribute.} \item{attname}{Name of the attribute to write.} \item{attval}{Attribute to write.} \item{prec}{Precision to write the attribute. If not specified, the written precision is the same as the variable whose attribute this is. This can be overridden by specifying this argument with a value of "short", "float", "double", or "text".} \item{verbose}{Can be set to TRUE if additional information is desired while the attribute is being created.} \item{definemode}{If FALSE (the default), it is assumed that the file is NOT already in define mode. Since the file must be in define mode for this call to work, the file will be put in define mode, the attribute defined, and then the file taken out of define mode. If this argument is set to TRUE, it is assumed the file is already in define mode, and the file is also left in define mode. If you don't know what any of this means, just leave this at the default value.} } \references{ http://dwpierce.com/software } \details{ This function write an attribute to a netCDF variable (or a global attribute to a netCDF file, if the passed argument "varid" is zero). The type of the written variable can be controlled by the "prec" argument, if the default behavior (the precision follows that of the associated variable) is not wanted. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncatt_get}}. } \examples{ \dontrun{ # Make a simple netCDF file filename <- "atttest_types.nc" dim <- ncdim_def( "X", "inches", 1:12 ) var <- ncvar_def( "Data", "unitless", dim, -1 ) ncnew <- nc_create( filename, var ) # Define some attributes of various types attvaldbl <- 3.1415926536 ncatt_put( ncnew, var, "testatt_dbl", attvaldbl, prec="double" ) attvalfloat <- c(1.0,4.0,9.0,16.0) ncatt_put( ncnew, var, "testatt_float", attvalfloat ) # varid=0 means it is a global attribute ncatt_put( ncnew, 0, "globalatt_int", 32000, prec="int" ) ncatt_put( ncnew, 0, "globalatt_short", 7, prec="short" ) ncatt_put( ncnew, 0, "description", "this is a test file with attributes of various types") nc_close(ncnew) # Clean up our test file.remove( filename ) } } \keyword{utilities} ncdf4/man/ncdim_def.Rd0000644000176200001440000001561014377671533014245 0ustar liggesusers\name{ncdim_def} \alias{ncdim_def} \title{Define a netCDF Dimension} \description{ Defines a netCDF dimension. This dimension initially only exists in memory. The dimension is later added to a netCDF variable using a call to \code{ncvar_def()}, and written to disk using \code{nc_create()}. } \usage{ ncdim_def( name, units, vals, unlim=FALSE, create_dimvar=TRUE, calendar=NA, longname=name ) } \arguments{ \item{name}{Name of the dimension to be created (character string). The dimension name can optionally have forward slashes in it, in which case the dimension will be defined in the indicated group. For example, a dimension named \code{model3/run1/Longitude} will define a group named \code{model3}, with a subgroup named \code{run1}, which will hold a dimension named \code{Longitude}. Using groups forces a netcdf version 4 file to be written. Note that older software might not be able to read netcdf version 4 files.} \item{units}{The dimension's units (character string).} \item{vals}{The dimension's values (vector of numeric type). If integers are passed, the associated dimensional variable will be integer type; otherwise, it will be double precision.} \item{unlim}{If TRUE, this dimension is unlimited. Unlimited dimensions are convenient for storing, for example, data that extends over time; the time dimension can be made unlimited, and extended as needed. Or, an unlimited dimension could be the number of stations, and extended as more stations come on-line. Note that in netCDF version 4, multiple dimensions can be unlimited. In netCDF version 3, there could only be one unlimited dimension, typically the time dimension.} \item{create_dimvar}{If TRUE, a dimensional variable (aka coordinate variable) will be created for this dimension. Note: if this is set to FALSE, then 'units' must be an empty string. It is good practice to always leave this as TRUE.} \item{calendar}{If set, the specified string will be added as an attribute named "calendar" to the dimension variable. Used almost exclusively with unlimited time dimensions. Useful values include "standard" (or "gregorian"), "noleap" (or "365_day"), and "360_day"). } \item{longname}{If set, AND create_dimvar is TRUE, then the created dimvar will have a long_name attribute with this value.} } \value{ An object of class \code{ncdim4} that can later be passed to \code{ncvar_def()}. } \references{ http://dwpierce.com/software } \details{ This routine creates a netCDF dimension in memory. The created dimension can then later be passed to the routine \code{ncvar_def()} when defining a variable. Note that this interface to the netCDF library by default includes that more than the minimum required by the netCDF standard. I.e., the netCDF standard allows dimensions with no units or values. This call encourages creating dimensions that have units and values, as it is useful to ensure that all dimensions have units and values, and considerably easier to include them in this call than it is to add them later. The units and values are implemented through "dimensional variables," which are variables with the same name as the dimension. By default, these dimensional variables are created automatically -- there is no need for the user to create them explicitly. Dimensional variables are standard practice in netCDF files. To suppress the creation of the dimensional variable for the dimension, set passed parameter create_dimvar to FALSE. As a check, if create_dimvar is FALSE, you must ALSO pass an empty string ('') as the unit, and the values must be simple integers from 1 to the length of the dimension (e.g., 1:10 to make a dimension of length 10). This empahsizes that without a dimensional variable, a netCDF file cannot store a dimension's units or values. The dimensional variable is usually created as a double precision floating point. The other possibility is to pass integer values (using \code{as.integer}, for example), in which case the dimensional variable with be integer. The return value of this function is an object of class \code{ncdim4}, which describes the newly created dimension. The \code{ncdim} object is used for more than just creating a new dimension, however. When opening an existing file, function \code{\link[ncdf4]{nc_open}} returns a \code{ncdf4} class object, which itself has a list of \code{ncdim} objects that describe all the dimensions in that existing file. The \code{ncdim} object has the following fields, which are all read only: 1) name, which is a character string containing the name of the dimension; 2) units, which is a character string containing the units for the dimension, if there are any (technically speaking, this is the "units" attribute of the associated coordinate variable); 3) vals, which is a vector containing the dimension's values (i.e., the values of the associated coordinate variable, or, if there is none, an integer sequence from 1 to the length of the dimension); 3) len, which is the length of this dimension; 4) unlim, which is a boolean indicating whether or not this is an unlimited dimension; 5) (optional) calendar, which is set if and only if the on-disk dimvar had an attribute named "calendar" (in which case, it is set to the value of that attribute). } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncvar_def}}, \code{\link[ncdf4]{nc_create}} } \examples{ \dontrun{ # Define some straightforward dimensions x <- ncdim_def( "Lon", "degreesE", 0.5:359.5) y <- ncdim_def( "Lat", "degreesN", as.double(-89:89)) t <- ncdim_def( "Time", "days since 1900-01-01", 1:10, unlim=TRUE) # Make a variable with those dimensions. Note order: time is LAST salinity <- ncvar_def("Salinity", "ppt", list(x,y,t), 1.e30 ) # Create a netCDF file with this variable ncnew <- nc_create( "salinity.nc", salinity ) nc_close(ncnew) # Now, illustrate some manipulations of the ncdim object. filename <- "salinity.nc" nc <- nc_open( filename ) print(paste("File",filename,"contains",nc$ndims,"dimensions")) for( i in 1:nc$ndims ) { print(paste("Here is information about dimension number",i,":")) d <- nc$dim[[i]] print(paste(" Name :",d$name)) print(paste(" Units :",d$units)) print(paste(" Length:",d$len)) print(" Values:") print(d$vals) print(paste(" Unlimited:",d$unlim)) } nc_close( nc ) # Clean up example file.remove( filename ) } } \note{It is good practice, but not necessary, to pass the dimension's values to this routine when the dimension is created. It is also possible to write them later with a call to 'ncvar_put', using as the dimension name as the 'varid' in the call. This is useful when creating large variables with long unlimited dimensions; it can take a long time to write out the unlimited dimension's values. In this case, it can be more efficient to step through the file, writing one timestep at a time, and write that timestep's dimensional value at the same time. } \keyword{utilities} ncdf4/man/nc_redef.Rd0000644000176200001440000000317614377671533014106 0ustar liggesusers\name{nc_redef} \alias{nc_redef} \title{Puts a netCDF file back into define mode} \description{ Puts a netCDF that is not currently in define mode back into define mode. } \usage{ nc_redef( nc ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned by either function \code{\link[ncdf4]{nc_open}}(..., write=TRUE) or function \code{\link[ncdf4]{nc_create}}, indicating what file to operate on.} } \references{ http://dwpierce.com/software } \details{ Typically, users will never need this function. NetCDF files can be in "define mode", at which time dimensions and variables can be defined, or new attributes added to a file, or in "data mode", at which time data can be read from the file. This call puts a file that is currently in data mode back into define mode. This functionality is handled transparently by the ncdf4 library, so users will never need to call this unless they are doing advanced manipulations of netcdf files. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{nc_enddef}}. } \examples{ # This function is for advanced useage only, and will never # be needed by the typical users R code. } \note{ The typical user will never need this call, nor will ever have to worry about "define mode" or "data mode". THIS CALL IS PROVIDED FOR ADVANCED USERS ONLY! If the user goes through this package's standard functional interface, the file will always automatically be set to whatever mode it needs to be in without the user having to do anything. For example, the call to write an attribute (\code{\link[ncdf4]{ncatt_put}}) handles this automatically. } \keyword{utilities} ncdf4/man/nc_open.Rd0000644000176200001440000001465514377671533013766 0ustar liggesusers\name{nc_open} \alias{nc_open} \title{Open a netCDF File} \description{ Opens an existing netCDF file for reading (or, optionally, writing). } \usage{ nc_open( filename, write=FALSE, readunlim=TRUE, verbose=FALSE, auto_GMT=TRUE, suppress_dimvals=FALSE, return_on_error=FALSE ) } \arguments{ \item{filename}{Name of the existing netCDF file to be opened.} \item{write}{If FALSE (default), then the file is opened read-only. If TRUE, then writing to the file is allowed.} \item{readunlim}{When invoked, this function reads in the values of all dimensions from the associated variables. This can be slow for a large file with a long unlimited dimension. If set to FALSE, the values for the unlimited dimension are not automatically read in (they can be read in later, manually, using \code{ncvar_get()}).} \item{verbose}{If TRUE, then messages are printed out during execution of this function.} \item{auto_GMT}{If TRUE, then GMT files are automatically detected. Does not yet do anything.} \item{suppress_dimvals}{If TRUE, then NO dimensional values are automatically read in from the file. (Use this if there are so many dimensional values that a out-of-memory error is generated).} \item{return_on_error}{If TRUE, then nc_open always returns, and returned list element $error will be TRUE if an error was encountered and FALSE if no error was encountered. If return_on_error is FALSE (the default), nc_open halts with an error message if an error is encountered.} } \value{ An object of class \code{ncdf4} that has the fields described above. } \references{ http://dwpierce.com/software } \details{ This routine opens an existing netCDF file for reading (or, if write=TRUE, for writing). To create a new netCDF file, use \code{\link[ncdf4]{nc_create}} instead. In addition to simply opening the file, information about the file and its contents is read in and stored in the returned object, which is of class \code{ncdf4}. This class has the following user-accessible fields, all of which are read-only: 1) filename, which is a character string holding the name of the file; 2) ndims, which is an integer holding the number of dimensions in the file; 3) nvars, which is an integer holding the number of the variables in the file that are NOT coordinate variables (aka dimensional variables); 4) natts, which is an integer holding the number of global attributes; 5) unlimdimid, which is an integer holding the dimension id of the unlimited dimension, or -1 if there is none; 6) dim, which is a list of objects of class \code{ncdim4}; 7) var, which is a list of objects of class \code{ncvar4}; 8) writable, which is TRUE or FALSE, depending on whether the file was opened with write=TRUE or write=FALSE. The concept behind the R interface to a netCDF file is that the \code{ncdf4} object returned by this function, as well as the list of \code{ncdim4} objects contained in the ncdf object's "dim" list and the \code{ncvar4} objects contained in the ncdf object's "var" list, completely describe the netCDF file. I.e., they hold the entire contents of the file's metadata. Therefore, there are no R interfaces to the explicit netCDF query functions, such as "nc_inq_nvars" or "nc_inq_natts". The upshot is, look in the ncdf4 object or its children to get information about the netCDF file. (Note: the \code{ncdim4} object is described in the help file for \code{\link[ncdf4]{ncdim_def}}; the \code{ncvar4} object is described in the help file for \code{\link[ncdf4]{ncvar_def}}). Missing values: R uses "NA" as a missing value. Netcdf files have various standards for indicating a missing value. The most common is that a variable will have an attribute named "_FillValue" indicating the value that should be interpreted as a missing value. (For example, the _FillValue attribute might have the value of 1.e30, indicating that any data in the netcdf file with a value of 1.e30 should be interpreted as a missing value.) If the "_FillValue" attribute is found, then the ncdf4 package transparently maps all the netcdf file's missing values to NA's; this is the most common case. The attribute "missing_value" is also recognized if there is no "_FillValue" attribute. Some netcdf files specify both a "_FillValue" and a "missing_value" attribute for a variable. If these two attributes have the same value, then everything is fine. If they have different values, I consider this a malformed netcdf file and I suggest you contact the person who made your netcdf file to fix it. In this event you can set the "raw_datavals" flag in the ncvar_get() call and handle the conflicting missing values however you want. If the netcdf file does not have a missing value, then the ncdf4 package assigns a default missing value of 1.e30 to the netcdcf file so that R NA's, which are always possible in the R environment, can be sensibly handled in the netcdf file. On rare occasions this can cause problems with non-compliant or incorrect netcdf files that implicitly use some particular value, for example 9.96921e+36, to indicate a missing value but without setting a proper _FillValue attribute. The best way to fix such netcdf files is to explicitly put in the correct _FillValue attribute using an \code{\link[ncdf4]{ncatt_put}} call. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{ncvar_def}}, \code{\link[ncdf4]{ncatt_put}}. } \examples{ \dontrun{ # Define an integer dimension dimState <- ncdim_def( "StateNo", "count", 1:50 ) # Make an integer variable. Note that an integer variable can have # a double precision dimension, or vice versa; there is no fixed # relationship between the precision of the dimension and that of the # associated variable. We just make an integer variable here for # illustration purposes. varPop <- ncvar_def("Pop", "count", dimState, -1, longname="Population", prec="integer") # Create a netCDF file with this variable ncnew <- nc_create( "states_population.nc", varPop ) # Write some values to this variable on disk. popAlabama <- 4447100 ncvar_put( ncnew, varPop, popAlabama, start=1, count=1 ) # Add source info metadata to file ncatt_put( ncnew, 0, "source", "Census 2000 from census bureau web site") nc_close(ncnew) # Now open the file and read its data ncold <- nc_open("states_population.nc") data <- ncvar_get(ncold) print("here is the data in the file:") print(data) nc_close( ncold ) # Clean up example file.remove( "states_population.nc" ) } } \keyword{utilities} ncdf4/man/nc_sync.Rd0000644000176200001440000000410714377671533013770 0ustar liggesusers\name{nc_sync} \alias{nc_sync} \title{Synchronize (flush to disk) a netCDF File} \description{ Flushes any pending operations on a netCDF file to disk. } \usage{ nc_sync( nc ) } \arguments{ \item{nc}{An object of class \code{ncdf4} that is opened for writing (as returned by either function \code{\link[ncdf4]{nc_open}}\code{(..., write=TRUE)} or function \code{\link[ncdf4]{nc_create}}, indicating what file is being written to.} } \references{ http://dwpierce.com/software } \details{ Data in a netCDF file is cached in memory, for better performance. An example of when this might be bad is if a long-running job writes one timestep of the output file at a time; if the job crashes near the end, the results of many timesteps might be lost. In such an event, the user can manually force any cached data to be written to disk using this call. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \examples{ \dontrun{ # The time you would use the sync.ncdf function is when you have an unlimited # dimension and are writing to the file timestep-by-timestep. Make a netCDF file # that has an unlimited dimension for illustration. nx <- 5 ny <- 8 dimx <- ncdim_def( "X", "meters", 1:nx ) dimy <- ncdim_def( "Y", "meters", 1:ny ) dimt <- ncdim_def( "Time", "days since 1900-01-01", 0, unlim=TRUE ) vartemp <- ncvar_def( "Temperature", "degC", list(dimx,dimy,dimt), 1.e30 ) nc <- nc_create( "temperature.nc", vartemp ) nt <- 10 # Imagine this is actually some very large number of timesteps for( i in 1:nt ) { # Long, slow computation to get the data ... for illustration, we just # use the following: data <- runif(nx*ny) # Write the data to this timestep ncvar_put( nc, vartemp, data, start=c(1,1,i), count=c(nx,ny,1) ) # Write the time value for this timestep as well timeval <- i*10 ncvar_put( nc, dimt, timeval, start=i, count=1 ) # Flush this timestep's data to the file so we dont lose it # if there is a crash or other problem nc_sync( nc ) } # Always remember to close the file when done!! nc_close(nc) # Clean up example file.remove( "temperature.nc" ) } } \keyword{utilities} ncdf4/man/ncvar_def.Rd0000644000176200001440000002202414377671533014261 0ustar liggesusers\name{ncvar_def} \alias{ncvar_def} \title{Define a netCDF Variable} \description{ Defines a netCDF variable. This variable initially only exists in memory. It is later written to disk using \code{nc_create()}. } \usage{ ncvar_def( name, units, dim, missval=NULL, longname=name, prec="float", shuffle=FALSE, compression=NA, chunksizes=NA, verbose=FALSE ) } \arguments{ \item{name}{Name of the variable to be created (character string). The name can optionally have forward slashes in it, in which case the variable will be defined in the indicated group. For example, a variable named \code{model3/run1/Temperature} will define a group named \code{model3}, with a subgroup named \code{run1}, which will hold a variable named \code{Temperature}. Using groups forces a netcdf version 4 file to be written. Note that older software might not be able to read netcdf version 4 files.} \item{units}{The variable's units (character string). Or, pass a zero length string ('') to have no units attribute.} \item{dim}{The variable's dimension(s) (one or a list of "ncdim4" class objects, as returned by \code{ncdim_def}). To create a variable with NO dimensions, pass an empty list ("list()"). } \item{missval}{The variable's missing value. If NO missing value is desired, pass a NULL, or omit this argument entirely. If a NaN missing value is desired, pass an NA.} \item{longname}{Optional longer name for the variable, which is assigned to the variable's "long_name" attribute. For example, a variable named "TS" might have the longname "Surface Temperature"} \item{prec}{Precision of the created variable. Valid options: 'short' 'integer' 'float' 'double' 'char' 'byte'. See the special note below for how to create a character variable (strings).} \item{shuffle}{Turns on (if TRUE) or off (if FALSE, the default) the shuffle filter. According to netcdf docs, turning the shuffle filter on can improve compression for integer variables. Turning the shuffle filter on forces the created file to be in netcdf version 4 format, which will not be compatible with older software that only reads netcdf version 3 files.} \item{compression}{If set to an integer between 1 (least compression) and 9 (most compression), this enables compression for the variable as it is written to the file. Turning compression on forces the created file to be in netcdf version 4 format, which will not be compatible with older software that only reads netcdf version 3 files.} \item{chunksizes}{If set, this must be a vector of integers with a length equal to the number of dimensions in the variable. When data from this variable is written to the file, it will be buffered in blocks as indicated by the chunksize. The order of dimensions in this vector is the standard R ordering of XYZT. In some instances, setting a chunksize that reflects how the variable's data will be read or written can greatly reduce read or write times. See the netcdf documentation for more detail on how to set this parameter. Enabling this feature forces the created file to be in netcdf version 4 format, which will not be compatible with older software that only reads netcdf version 3 files.} \item{verbose}{Print debugging information.} } \value{ An object of class \code{ncvar4} that can later be passed to \code{nc_create()}. } \references{ http://dwpierce.com/software } \details{ This routine creates a netCDF variable in memory. The variable can then be passed to the routine \code{nc_create} when writing a file to disk. Note that this interface to the netCDF library includes more than the minimum required by the netCDF standard. I.e., the netCDF standard allows variables with no units or missing values. This call requires units and a missing value, as it is useful to ensure that all variables have units and missing values, and considerably easier to include them in this call than it is to add them later. The units and missing value are implemented through attributes to the variable, named "units" and "missing_value", respectively. This is standard practice in netCDF files. After a variable is defined with this call, and created on disk using \code{\link[ncdf4]{nc_create}}, then data values for the variable can be written to disk using \code{\link[ncdf4]{ncvar_put}}. This function returns a \code{ncvar} object, which describes the newly-created variable. However, the \code{ncvar} object is used for more than just creating new variables. The function \code{\link[ncdf4]{nc_open}} returns a \code{ncdf4} class object that itself contains a list of \code{ncvar4} objects that describe the variables in an existing, on-disk netCDF file. (Note that coordinate variables are NOT included in this list. Attributes of the coordinate variables are kept in the \code{ncdim4} class object instead.) The \code{ncvar4} class object has the following fields, which are all read-only: 1) name, which is a character string containing the name of the variable; 2) units, which is a character string containing the contents of the variable's "units" attribute; 3) missval, which contains the contents of the variable's "missing_value" attribute; 4) longname, which is the contents of the variable's "long_name" attribute, or defaults to the name of the variable if there is no "long_name" attribute; 5) ndims, which is the number of dimensions this variable has; 6) dim, which is a list of objects of class "ncdim4" (see \code{\link[ncdf4]{ncdim_def}}), and describe this variable's dimensions; 7) unlim, which is TRUE if this variable has an unlimited dimension and FALSE otherwise; 8) varsize, which is a convenience array that gives the shape of the variable (in XYZT ordering). Note that the missval attribute does not need to be used much in R, because R's special value NA is fully supported. I.e., when data is read in from an existing file, any values equal to the "missing" value are set to NA. When data is written out, any NAs are set equal to the missing value. If not explicitly set by the user, a default value of 1.e30 is used for the missing value. CHARACTER VARIABLES: Character-type variables (i.e., strings) are supported using the original netcdf library approach, which is used because it is backwards compatible with the older version 3 of the netcdf library. This approach uses fixed-size strings, which should be declared to be the maximum length of the string that will be stored. If the maximum string size is N, then an auxiliary dimension is first defined, with values running from 1 to N. For example, if N=12 and we call the new auxiliary dimension "nchar", then the code could look like this: dimnchar <- ncdim_def("nchar", "", 1:12, create_dimvar=FALSE ). The character type variable is then defined with the first dimension being this new auxiliary variable: varcolors <- ncvar_def("colors", "", list(dimnchar, dimcolorno), prec="char" ). See the manual page for \code{\link[ncdf4]{ncvar_put}} for a worked example. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{nc_create}}, \code{\link[ncdf4]{ncvar_put}}. } \examples{ \dontrun{ # Define an integer dimension dimState <- ncdim_def( "StateNo", "count", 1:50 ) # Make an integer variable. Note that an integer variable can have # a double precision dimension, or vice versa; there is no fixed # relationship between the precision of the dimension and that of the # associated variable. We just make an integer variable here for # illustration purposes. varPop <- ncvar_def("Pop", "count", dimState, -1, longname="Population", prec="integer") # Create a netCDF file with this variable ncnew <- nc_create( "states_population.nc", varPop ) # Write some values to this variable on disk. popAlabama <- 4447100 ncvar_put( ncnew, varPop, popAlabama, start=1, count=1 ) # Add source info metadata to file ncatt_put( ncnew, 0, "source", "Census 2000 from census bureau web site") nc_close(ncnew) # Now illustrate some manipulations of the var.ncdf object filename <- "states_population.nc" nc <- nc_open(filename) print(paste("File",nc$filename,"contains",nc$nvars,"variables")) for( i in 1:nc$nvars ) { v <- nc$var[[i]] print(paste("Here is information on variable number",i)) print(paste(" Name: ",v$name)) print(paste(" Units:",v$units)) print(paste(" Missing value:",v$missval)) print(paste(" # dimensions :",v$ndims)) print(paste(" Variable size:",v$varsize)) } # Illustrate creating variables of various types. You will find # that the type of the missing_value attribute automatically follows # the type of the variable. dimt <- ncdim_def( "Time", "days", 1:3 ) missval <- -1 varShort <- ncvar_def( "varShort", "meters", dimt, missval, prec="short") varInt <- ncvar_def( "varInt", "meters", dimt, missval, prec="integer") varFloat <- ncvar_def( "varFloat", "meters", dimt, missval, prec="single") varDouble<- ncvar_def( "varDouble","meters", dimt, missval, prec="double") nctypes <- nc_create("vartypes.nc", list(varShort,varInt,varFloat,varDouble) ) nc_close(nctypes) # Clean up example file.remove( filename ) file.remove( "vartypes.nc" ) } } \keyword{utilities} ncdf4/man/ancvar_put.Rd0000644000176200001440000001632314377705264014500 0ustar liggesusers\name{ncvar_put} \alias{ncvar_put} \title{Write data to a netCDF file} \description{ Writes data to an existing netCDF file. The variable to be written to must already exist on disk (i.e., you must call either \code{\link[ncdf4]{nc_create}} or \code{\link[ncdf4]{nc_open}} before calling this function). } \usage{ ncvar_put( nc, varid, vals, start=NA, count=NA, verbose=FALSE, na_replace="fast" ) } \arguments{ \item{nc}{An object of class \code{ncdf4} (as returned by either function \code{\link[ncdf4]{nc_open}} or \code{\link[ncdf4]{nc_create}}), indicating what file to write to.} \item{varid}{What variable to write the data to. Can be a string with the name of the variable or an object of class \code{ncvar4}, as returned by \code{\link[ncdf4]{ncvar_def}} or \code{\link[ncdf4]{nc_open}}.} \item{vals}{The values to be written.} \item{start}{A vector of indices indicating where to start writing the passed values (starting at 1). The length of this vector must equal the number of dimensions the variable has. Order is X-Y-Z-T (i.e., the time dimension is last). If not specified, writing starts at the beginning of the file (1,1,1,...).} \item{count}{A vector of integers indicating the count of values to write along each dimension (order is X-Y-Z-T). The length of this vector must equal the number of dimensions the variable has. If not specified and the variable does NOT have an unlimited dimension, the entire variable is written. If the variable has an unlimited dimension, this argument must be specified. As a special case, the value "-1" indicates that all entries along that dimension should be written.} \item{verbose}{If true, prints information while executing.} \item{na_replace}{This is either the string "fast" or the string "safe". When the 'vals' array is written out, NA's have to be replaced by the missing value specified when the variable was created. If na_replace is "fast", then this is done in-place without copying the 'vals' data array. This results in the passed 'vals' array being modified such that NA's are replaced with the missing value. This is fast but not standard in R and may be unexpected. If na_replace is "safe" then the vals array is copied before the NA replacement, so that the vals array is not modified. This is more expected and standard R, but can be slow and might cause memory issues if a very large 'vals' array is passed in. Default value is "fast".} } \references{ http://dwpierce.com/software } \details{ This routine writes data values to a variable in a netCDF file. The file should have either been created with \code{\link[ncdf4]{nc_create}}, or opened with \code{\link[ncdf4]{nc_open}} called with parameter \code{write=TRUE}. Note that the data type (i.e., precision) of the values written to the file is determined when the variable is created; in particular, it does not matter what type you pass to this function to be written. In other words, if the variable was created with type 'integer', passing double precision values to this routine will still result in integer values being written to disk. Values of "NA" are supported; they are converted to the netCDF variable's missing value attribute before being written. See \code{\link[ncdf4]{ncvar_change_missval}} for more information. Data in a netCDF file is conceived as being a multi-dimensional array. The number and length of dimensions is determined when the variable is created. The 'start' and 'count' indices that this routine takes indicate where the writing starts along each dimension, and the count of values along each dimension to write. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{nc_create}}, \code{\link[ncdf4]{nc_open}}, \code{\link[ncdf4]{ncvar_get}}. } \examples{ \dontrun{ #-------------------------------- # Make a few dimensions we can use #-------------------------------- nx <- 3 ny <- 4 nt <- 5 xvals <- (1:nx)*100. dimX <- ncdim_def( "X", "meters", xvals ) dimY <- ncdim_def( "Y", "meters", (1:ny)*100. ) dimT <- ncdim_def( "Time", "seconds", (1:nt)/100., unlim=TRUE ) #------------------------------------------------------------------- # Make varables of various dimensionality, for illustration purposes #------------------------------------------------------------------- mv <- 1.e30 # missing value to use var1d <- ncvar_def( "var1d", "units", dimX, mv ) var2d <- ncvar_def( "var2d", "units", list(dimX,dimY), mv ) var3d <- ncvar_def( "var3d", "units", list(dimX,dimY,dimT), mv ) #--------------------- # Create the test file #--------------------- nc <- nc_create( "writevals.nc", list(var1d,var2d,var3d) ) #---------------------------- # Write some data to the file #---------------------------- data1d <- runif(nx) ncvar_put( nc, var1d, data1d ) # no start or count: write all values ncvar_put( nc, var1d, 27.5, start=3, count=1 ) # Write a value to the third slot data2d <- runif(nx*ny) ncvar_put( nc, var2d, data2d ) # no start or count: write all values #-------------------------------- # Write a 1-d slice to the 2d var #-------------------------------- ncvar_put( nc, var2d, data1d, start=c(1,2), count=c(nx,1) ) #-------------------------------------------------------------- # Note how "-1" in the count means "the whole dimension length", # which equals nx in this case #-------------------------------------------------------------- ncvar_put( nc, var2d, data1d, start=c(1,3), count=c(-1,1) ) #------------------------------------------------------------------------------- # The 3-d variable has an unlimited dimension. We will loop over the timesteps, # writing one 2-d slice per timestep. #------------------------------------------------------------------------------- for( i in 1:nt) ncvar_put( nc, var3d, data2d, start=c(1,1,i), count=c(-1,-1,1) ) nc_close(nc) #---------------------------------------------------------------------- # Illustrate creating a character type variable #---------------------------------------------------------------------- cnames <- c("red", "orange", "green", "yellow", "puce", "colorwithverylongname" ) nstrings <- length(cnames) #-------------------------------------------------------------- # Make dimensions. Setting "dimnchar" to have a length of 12 # means that the maximum color name # length can be 12. Longer names will be truncated to this. # We don't need dimvars for this example. #-------------------------------------------------------------- dimnchar <- ncdim_def("nchar", "", 1:12, create_dimvar=FALSE ) dimcolorno <- ncdim_def("colorno", "", 1:nstrings, create_dimvar=FALSE ) #------------------------------------------------------------------------ # NOTE in the following call that units is set to the empty string (""), # which suppresses creation of a units attribute, and the missing value # is entirely omitted, which suppresses creation of the missing value att #------------------------------------------------------------------------ varcolors <- ncvar_def("colors", "", list(dimnchar, dimcolorno), " ", prec="char" ) ncid <- nc_create( "colornames.nc", list(varcolors) ) ncvar_put( ncid, "colors", cnames, verbose=TRUE ) nc_close( ncid ) #--------- # Clean up #--------- file.remove( "colornames.nc" ) file.remove( "writevals.nc" ) } } \keyword{utilities} ncdf4/man/ncdf4-internal.Rd0000644000176200001440000000173014377671533015143 0ustar liggesusers\name{ncdf4-internal} \title{Internal ncdf4 functions} \alias{ncdim_create} \alias{ncdim_same} \alias{default_missval_ncdf4} \alias{ncvar_name} \alias{vobjtovarid4} \alias{ncvar_inq} \alias{ncdim_inq} \alias{nc_unlimdim} \alias{ncvar_size} \alias{ncvar_ndims} \alias{ncdim_id} \alias{ncvar_id} \alias{ncvar_id_to_missing_value} \alias{ncvar_name} \alias{ncvar_type} \alias{blankstring_ncdf4} \alias{nslashes_ncdf4} \alias{ncvar_type_to_string} \alias{ncvar_inq_deflate} \alias{ncvar_inq_chunking} \alias{ncvar_get_inner} \alias{ncvar_def_deflate} \alias{ncvar_def_chunking} \alias{ncdf4_format} \alias{ncdf4_make_id} \alias{ncatt_put_inner} \alias{ncatt_get_n} \alias{ncatt_get_inner} \alias{nc_parse_group_structure} \alias{nc_make_group_inner} \alias{nc_grpname} \alias{nc_grpids} \alias{nc_groups_below} \alias{nc_get_grp_info} \alias{nc4_loop} \alias{nc4_basename} \description{ Internal ncdf functions. } \details{ These are not to be called by the user. } \keyword{internal} ncdf4/man/ncvar_add.Rd0000644000176200001440000001175214377671533014261 0ustar liggesusers\name{ncvar_add} \alias{ncvar_add} \title{Add New netCDF Variable to Existing File} \description{ Special purpose routine for adding a new variable to a netCDF file that already exists on disk. } \usage{ ncvar_add( nc, v, verbose=FALSE, indefine=FALSE ) } \arguments{ \item{nc}{The already-existing netCDF file we want to add a new variable to. This must be a value of class "ncdf4" returned by a call to \code{\link[ncdf4]{nc_open}}\code{(...,write=TRUE).}} \item{v}{The variable to be added to the file. This must be a value of class "ncvar4" returned by a call to \code{\link[ncdf4]{ncvar_def}}.} \item{verbose}{If true, prints diagnostic messages.} \item{indefine}{If true, the file is assumed to already be in define mode.} } \value{ A handle to the netCDF file that describes the newly modified file. This is an object of type 'ncdf', the same as returned by \code{\link[ncdf4]{nc_open}} or \code{\link[ncdf4]{nc_create}}. } \references{ http://dwpierce.com/software } \details{ There are two cases in which you might want to add a variable to a netCDF file. The first, and most common way, is when you are creating a new netCDF file. Usually when you create a netCDF file, you specify what variables you want the file to contain. This is the method most users will use to make netCDF files. To do this, do NOT use this routine; instead, pass a list of the variables you wish to have created in the output file to routine \code{\link[ncdf4]{nc_create}}. The second, less common, case is when you already have an existing netCDF file on disk and wish to add a new variable to it. In that case, use this routine. First define the variable you want to add to the existing file using routine \code{\link[ncdf4]{ncvar_def}}; then add it to the already-existing and opened (for writing) netCDF file using this routine. (This routine automatically creates any additional dimensions that are needed in the output file to handle the new variable.) NOTE that the return value of this routine should replace the old netCDF file handle that you were using. This newly returned value reflects the modifications to the file that were accomplished by calling this routine. } \author{David W. Pierce \email{dpierce@ucsd.edu}} \seealso{ \code{\link[ncdf4]{ncdim_def}}, \code{\link[ncdf4]{nc_create}}, \code{\link[ncdf4]{ncvar_def}}. } \examples{ \dontrun{ #=========================================================================== # PART 1. MAKE A TEST NETCDF FILE THAT WE WILL ADD A VARIABLE TO IN PART 2. #=========================================================================== #---------------- # Make dimensions #---------------- xvals <- 1:360 yvals <- -90:90 nx <- length(xvals) ny <- length(yvals) xdim <- ncdim_def( 'Lon', 'degreesE', xvals ) ydim <- ncdim_def( 'Lat', 'degreesE', yvals ) tdim <- ncdim_def( 'Time', 'days since 1900-01-01', 0, unlim=TRUE ) #--------- # Make var #--------- mv <- 1.e30 # missing value var_temp <- ncvar_def( 'Temperature', 'K', list(xdim,ydim,tdim), mv ) #--------------------- # Make new output file #--------------------- output_fname <- 'test_real3d.nc' ncid_new <- nc_create( output_fname, list(var_temp)) #------------------------------- # Put some test data in the file #------------------------------- data_temp <- array(0.,dim=c(nx,ny,1)) for( j in 1:ny ) for( i in 1:nx ) data_temp[i,j,1] <- sin(i/10)*sin(j/10) ncvar_put( ncid_new, var_temp, data_temp, start=c(1,1,1), count=c(nx,ny,1)) #-------------------------- # Close our new output file #-------------------------- nc_close( ncid_new ) #=========================================================================== # PART 2. ADD A NEW VARIABLE TO THE FILE #=========================================================================== #--------------------------------------------------- # Open the existing file we're going to add a var to #--------------------------------------------------- ncid_old <- nc_open( output_fname, write=TRUE ) #------------------------------------------------------------------ # Make a NEW variable to put into the file. Have this new variable # use the same dimensions already in the file #------------------------------------------------------------------ xdim2 <- ncid_old$dim[['Lon']] ydim2 <- ncid_old$dim[['Lat']] tdim2 <- ncid_old$dim[['Time']] mv2 <- 1.e30 var_q <- ncvar_def( 'Humidity', 'g/kg', list(xdim2,ydim2,tdim2), mv2 ) ncid_old <- ncvar_add( ncid_old, var_q ) # NOTE this returns a modified netcdf file handle #------------------------------------------------------------------- # Make a DIFFERENT new var that will be added to the file. This var # uses a dim that does NOT already exist in the file. #------------------------------------------------------------------- zdim <- ncdim_def( 'Level', 'hPa', seq(1000,100,by=-100)) var_cf <- ncvar_def( 'CloudFraction', 'percent', list(xdim2,ydim2,zdim,tdim2), mv2 ) ncid_old <- ncvar_add( ncid_old, var_cf ) print(ncid_old) nc_close( ncid_old ) # Clean up our example file.remove( output_fname ) } } \keyword{utilities} ncdf4/DESCRIPTION0000644000176200001440000000270114531443302012755 0ustar liggesusersPackage: ncdf4 Version: 1.22 Date: 2023-11-27 Title: Interface to Unidata netCDF (Version 4 or Earlier) Format Data Files Author: David Pierce Maintainer: David Pierce Description: Provides a high-level R interface to data files written using Unidata's netCDF library (version 4 or earlier), which are binary data files that are portable across platforms and include metadata information in addition to the data sets. Using this package, netCDF files (either version 4 or "classic" version 3) can be opened and data sets read in easily. It is also easy to create new netCDF dimensions, variables, and files, in either version 3 or 4 format, and manipulate existing netCDF files. This package replaces the former ncdf package, which only worked with netcdf version 3 files. For various reasons the names of the functions have had to be changed from the names in the ncdf package. The old ncdf package is still available at the URL given below, if you need to have backward compatibility. It should be possible to have both the ncdf and ncdf4 packages installed simultaneously without a problem. However, the ncdf package does not provide an interface for netcdf version 4 files. SystemRequirements: netcdf library version 4.1 or later License: GPL (>= 3) URL: https://cirrus.ucsd.edu/~pierce/ncdf/ NeedsCompilation: yes Packaged: 2023-11-28 19:05:38 UTC; pierce Repository: CRAN Date/Publication: 2023-11-28 20:00:02 UTC ncdf4/configure.ac0000644000176200001440000001325714377671533013566 0ustar liggesusersAC_INIT AC_CONFIG_SRCDIR([src/Makevars.in]) echo "configure.ac: starting" AC_CONFIG_MACRO_DIR([tools]) : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then echo "Could not determine R_HOME" exit 1 fi #--------------------------------------------------------------------------- # The way R's package installation mechanism works, the C compiler and flags # are set by R, and not changable at the package level. So this is really # just for information purposes. Changing these values will NOT result in # a different compiler being used!! #--------------------------------------------------------------------------- CC=`${R_HOME}/bin/R CMD config CC` CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS` # for ncdf4, I've chosen to REQUIRE the netcdf v4 interface AC_PATH_NETCDF if test $NETCDF_V4 = "no"; then echo "-------------------------------------------------------------------" echo "ncdf4 REQUIRES the netcdf library be version 4 or above," echo "AND installed with HDF-5 support (i.e., the netcdf library must be" echo "compiled with the --enable-netcdf-4 flag). If you don't want to install" echo "the full version of netcdf-4 with HDF-5 support, then please install" echo "the old, deprecated ncdf package instead." echo "-------------------------------------------------------------------" exit -1 fi HAVE_NETCDF=TRUE NETCDF_LDFLAGS="$NETCDF_RPATH $NETCDF_LDFLAGS $LDFLAGS" AC_SUBST(NETCDF_CPPFLAGS) AC_SUBST(NETCDF_LDFLAGS) AC_SUBST(NETCDF_RPATH) AC_SUBST(HAVE_NETCDF) AC_CONFIG_FILES([src/Makevars]) AC_OUTPUT echo " " echo "********************** Results of ncdf4 package configure *******************" echo " " echo "netCDF v4 CPP flags = $NETCDF_CPPFLAGS" echo "netCDF v4 LD flags = $NETCDF_LDFLAGS" echo "netCDF v4 runtime path = $NETCDF_RPATH" echo " " echo "netCDF C compiler used = $NETCDF_CC" echo "R C compiler used = $CC $CFLAGS" echo " " echo "******************************************************************************" echo " " #--------------------------------------------------------------------- # Check to see if a different compiler is being used for netcdf and R #--------------------------------------------------------------------- set $NETCDF_CC NETCDF_CC_ARG1=$1 set $CC R_CC_ARG1=$1 TEST_EMIT_WARNING=0 if test x$NETCDF_CC_ARG1 != x$R_CC_ARG1 -o $TEST_EMIT_WARNING -eq 1; then #------------------------------------------------------------------------------ # By default, we emit a warning if the compilers of R and netcdf are different. # This happens with some regularity to naive users. #------------------------------------------------------------------------------ emit_warning=1 #------------------------------------------------------------------------------------------------- # Skip warning if one is gcc and the other is clang -- seems to bother some overly sensitive folks #------------------------------------------------------------------------------------------------- NETCDF_IS_GCC=0 if echo "$NETCDF_CC_ARG1" | grep -q "gcc"; then NETCDF_IS_GCC=1 else AC_PROG_CC([$NETCDF_CC_ARG1]) if test "z$GCC" = zyes; then NETCDF_IS_GCC=1 fi fi NETCDF_IS_CLANG=0 if echo "$NETCDF_CC_ARG1" | grep -q "clang"; then NETCDF_IS_CLANG=1 fi R_IS_GCC=0 if echo "$R_CC_ARG1" | grep -q "gcc"; then R_IS_GCC=1 else AC_PROG_CC([$R_CC_ARG1]) if test "z$GCC" = zyes; then R_IS_GCC=1 fi fi R_IS_CLANG=0 if echo "$R_CC_ARG1" | grep -q "clang"; then R_IS_CLANG=1 fi #------------------------------------------------------------- # We don't bother emitting the warning if the two compilers in # use are clang and gcc -- supposedly they are compatible #------------------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi #----------------------------------------------------- # Both same, but different exact names of compilers... # not sure if this actually guarantees success?? #----------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi echo "netcdf cc arg1: $NETCDF_CC_ARG1 R cc arg1: $R_CC_ARG1 R_IS_GCC: $R_IS_GCC R_IS_CLANG: $R_IS_CLANG NETCDF_IS_GCC: $NETCDF_IS_GCC NETCDF_IS_CLANG: $NETCDF_IS_CLANG emit_warning: $emit_warning" if test $emit_warning -eq 1 -o $TEST_EMIT_WARNING -eq 1; then echo " " echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" echo "Dear ncdf4 user: The software configuration tool thinks that perhaps different compilers are being" echo "used for R and the netcdf library. However, we all know that software configuration tools are" echo "not that smart. If ncdf4 compiles fine for you, then please ignore this message. However, if" echo "installation fails, it might be that you are using different compilers for R and the netcdf library." echo "If so, then you must create a new version of the netcdf library that was compiled with the same" echo "compiler that was used to install R (see information above). Then, try installing the ncdf4" echo "package again using that new netcdf library. If necessary, you can specify the location of" echo "the new nc-config (the one that uses the same compiler used by R) like this:" echo " " echo "R CMD INSTALL --configure-args=\"--with-nc-config=/home/joe/bin/nc-config\"" echo " " echo "(obviously, put in the correct path to YOUR nc-config, don't just use my example location!)" echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" echo " " fi fi ncdf4/src/0000755000176200001440000000000014531435002012034 5ustar liggesusersncdf4/src/ncdf.c0000644000176200001440000026147614531434774013151 0ustar liggesusers #include #include #include #include #include #include /* These same values are hard-coded into the R source. Don't change them! * Note that they are not the same as values defined in the netcdf * library headers, since I don't want my R code to depend on those */ #define R_NC_TYPE_SHORT 1 #define R_NC_TYPE_INT 2 #define R_NC_TYPE_FLOAT 3 #define R_NC_TYPE_DOUBLE 4 #define R_NC_TYPE_TEXT 5 #define R_NC_TYPE_BYTE 6 /* New types in netcdf version 4 */ #define R_NC_TYPE_UBYTE 7 #define R_NC_TYPE_USHORT 8 #define R_NC_TYPE_UINT 9 #define R_NC_TYPE_INT64 10 #define R_NC_TYPE_UINT64 11 #define R_NC_TYPE_STRING 12 void R_nc4_inq_varid_hier( int *ncid, char **varname, int *returned_grpid, int *returned_varid ); int R_nc4_nctype_to_Rtypecode( nc_type nct ); void R_nc4_varsize( int *ncid, int *varid, int *ndims, int *varsize, int *retval ); void R_nc4_inq_varunlim( int *ncid, int *varid, int *isunlim, int *retval ); void R_nc4_inq_var( int *ncid, int *varid, char **varname, int *type, int *ndims, int *dimids, int *natts, int *precint, int *retval ); void R_nc4_inq_vartype( int *ncid, int *varid, int *precint, int *retval ); void R_nc4_inq_varname( int *ncid, int *varid, char **varname, int *retval ); void R_nc4_inq_varndims( int *ncid, int *varid, int *ndims, int *retval ); void R_nc4_inq_dimlen( int *ncid, char **dimname, int *dimlen ); void R_nc4_inq_dimid( int *ncid, char **dimname, int *dimid ); void R_nc4_inq_varid( int *ncid, char **varname, int *varid ); void R_nc4_inq_unlimdim( int *ncid, int *unlimdimid, int *retval ); void R_nc4_inq_dimids( int *ncid, int *dimids, int *retval ); void R_nc4_inq_dim( int *ncid, int *dimid, char **dimname, int *dimlen, int *unlim, int *retval ); void R_nc4_inq( int *ncid, int *ndims, int *nvars, int *natts, int *retval ); void R_nc4_open( char **filename, int *cmode, int *ncid, int *retval ); void R_nc4_create( char **filename, int *cmode, int *ncid, int *retval ); nc_type R_nc4_ttc_to_nctype( int type_to_create ); void R_nc4_put_att_logical( int *ncid, int *varid, char **attname, int *type_to_create, int *natts, int *attribute, int *retval ); void R_nc4_put_att_int ( int *ncid, int *varid, char **attname, int *type_to_create, int *natts, int *attribute, int *retval ); void R_nc4_put_att_double ( int *ncid, int *varid, char **attname, int *type_to_create, int *natts, double *attribute, int *retval ); void R_nc4_put_att_text ( int *ncid, int *varid, char **attname, int *type_to_create, int *natts, char **attribute, int *retval ); void R_nc4_inq_att ( int *ncid, int *varid, char **attname, int *type, int *attlen, int *retval ); void R_nc4_get_att_int ( int *ncid, int *varid, char **attname, int *attribute, int *retval ); void R_nc4_get_att_double( int *ncid, int *varid, char **attname, double *attribute, int *retval ); void R_nc4_get_att_text ( int *ncid, int *varid, char **attname, char **attribute, int *retval ); void R_nc4_def_var_byte ( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_var_int ( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_var_short ( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_var_float ( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_var_double( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_var_char ( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ); void R_nc4_def_dim( int *ncid, char **dimname, int *size, int *dimid, int *retval ); void R_nc4_redef( int *ncid ); void R_nc4_rename_var( int *ncid, int *varid, char **newname, int *retval ); void R_nc4_inq_attname( int *ncid, int *varid, int *attnum, char **attname, int *retval ); void R_nc4_def_var_chunking( int *root_id, int *varid, int *ndims, int *storage, int *chunksizesp, int *ierr ); void R_nc4_inq_var_chunking( int *root_id, int *varid, int *ndims, int *storage, int *chunksizesp, int *ierr ); void R_nc4_inq_var_deflate( int *root_id, int *varid, int *shuffle, int *deflate, int *deflate_level, int *ierr ); void R_nc4_def_var_deflate( int *root_id, int *varid, int *shuffle, int *deflate, int *deflate_level, int *ierr ); void R_nc4_inq_ngroups( int *root_id, int *ngroups, int *ierr ); void R_nc4_inq_groupids( int *root_id, int *gids, int *ierr ); int R_nc4_util_nslashes( char *s, int *idx_first_slash ); void R_nc4_inq_varid_hier_inner( int *ncid, char *varname, int *returned_grpid, int *returned_varid ); void R_nc4_inq_varid_hier( int *ncid, char **varname, int *returned_grpid, int *returned_varid ); void R_nc4_get_vara_text( int *ncid, int *varid, int *start, int *count, char **tempstore, char **data, int *retval ); void R_nc4_put_vara_text( int *ncid, int *varid, int *start, int *count, char **data, int *retval ); void R_nc4_enddef( int *ncid, int *retval ); void R_nc4_sync ( int *ncid ); void R_nc4_close ( int *ncid ); void R_nc4_def_grp( int *parent_ncid, char **grpname, int *new_ncid, int *retval ); int R_ncu4_varid_onlyvar( int ncid ); void R_ncu4_calc_start_count( int ncid, int varid, int *start_arg, int len_start, int *count_arg, int len_count, size_t *varsize, int ndims, size_t *start, size_t *count ); int R_ncu4_get_varsize( int ncid, int varid, int ndims, size_t *varsize ); int R_ncu4_isdimvar( int ncid, char *name ); SEXP Rsx_nc4_get_vara_double( SEXP sx_ncid, SEXP sx_varid, SEXP sx_start, SEXP sx_count, SEXP sx_fixmiss, SEXP sx_imvstate, SEXP sx_missval ); SEXP Rsx_nc4_get_vara_int ( SEXP sx_ncid, SEXP sx_varid, SEXP sx_start, SEXP sx_count, SEXP sx_byte_style ); SEXP R_nc4_get_att_string ( SEXP sx_ncid, SEXP sx_varid, SEXP sx_attname, SEXP sx_attlen, SEXP sx_ierr_returned ); SEXP Rsx_nc4_put_vara_double( SEXP sx_ncid, SEXP sx_varid, SEXP sx_start, SEXP sx_count, SEXP sx_data ); SEXP Rsx_nc4_put_vara_int ( SEXP sx_ncid, SEXP sx_varid, SEXP sx_start, SEXP sx_count, SEXP sx_data ); SEXP R_nc4_blankstring(SEXP size); SEXP R_nc4_grpname(SEXP sx_root_id, SEXP sx_ierr_retval); SEXP R_nc4_inq_format(SEXP sx_root_id, SEXP sx_ierr_retval); SEXP R_nc4_set_NA_to_val_double(SEXP sx_dat, SEXP sx_val ); SEXP R_nc4_get_vara_charvarid( SEXP sx_nc, SEXP sx_varid, SEXP sx_start, SEXP sx_count ) ; SEXP R_nc4_get_vara_numvarid( SEXP sx_nc, SEXP sx_varid, SEXP sx_start, SEXP sx_count ); SEXP R_ncu4_getListElement(SEXP list, char *str); SEXP R_nc4_get_vara_string( SEXP sx_nc, SEXP sx_varid, SEXP sx_start, SEXP sx_count ); SEXP R_nc4_inq_libvers( void ); /* For C calls that don't use SEXP type args */ static const R_CMethodDef cMethods[] = { {"R_nc4_nctype_to_Rtypecode", (DL_FUNC) &R_nc4_nctype_to_Rtypecode, 1}, {"R_nc4_varsize", (DL_FUNC) &R_nc4_varsize, 5}, {"R_nc4_inq_varunlim", (DL_FUNC) &R_nc4_inq_varunlim, 4}, {"R_nc4_inq_var", (DL_FUNC) &R_nc4_inq_var, 9}, {"R_nc4_inq_vartype", (DL_FUNC) &R_nc4_inq_vartype, 4}, {"R_nc4_inq_varname", (DL_FUNC) &R_nc4_inq_varname, 4}, {"R_nc4_inq_varndims", (DL_FUNC) &R_nc4_inq_varndims, 4}, {"R_nc4_inq_dimlen", (DL_FUNC) &R_nc4_inq_dimlen, 3}, {"R_nc4_inq_dimid", (DL_FUNC) &R_nc4_inq_dimid, 3}, {"R_nc4_inq_varid", (DL_FUNC) &R_nc4_inq_varid, 3}, {"R_nc4_inq_unlimdim", (DL_FUNC) &R_nc4_inq_unlimdim, 3}, {"R_nc4_inq_dimids", (DL_FUNC) &R_nc4_inq_dimids, 3}, {"R_nc4_inq_dim", (DL_FUNC) &R_nc4_inq_dim, 6}, {"R_nc4_inq", (DL_FUNC) &R_nc4_inq, 5}, {"R_nc4_open", (DL_FUNC) &R_nc4_open, 4}, {"R_nc4_create", (DL_FUNC) &R_nc4_create, 4}, {"R_nc4_ttc_to_nctype", (DL_FUNC) &R_nc4_ttc_to_nctype, 1}, {"R_nc4_put_att_logical", (DL_FUNC) &R_nc4_put_att_logical, 7}, {"R_nc4_put_att_int", (DL_FUNC) &R_nc4_put_att_int, 7}, {"R_nc4_put_att_double", (DL_FUNC) &R_nc4_put_att_double, 7}, {"R_nc4_put_att_text", (DL_FUNC) &R_nc4_put_att_text, 7}, {"R_nc4_inq_att", (DL_FUNC) &R_nc4_inq_att, 6}, {"R_nc4_get_att_int", (DL_FUNC) &R_nc4_get_att_int, 5}, {"R_nc4_get_att_double", (DL_FUNC) &R_nc4_get_att_double, 5}, {"R_nc4_get_att_text", (DL_FUNC) &R_nc4_get_att_text, 5}, {"R_nc4_def_var_byte", (DL_FUNC) &R_nc4_def_var_byte, 6}, {"R_nc4_def_var_int", (DL_FUNC) &R_nc4_def_var_int, 6}, {"R_nc4_def_var_short", (DL_FUNC) &R_nc4_def_var_short, 6}, {"R_nc4_def_var_float", (DL_FUNC) &R_nc4_def_var_float, 6}, {"R_nc4_def_var_double", (DL_FUNC) &R_nc4_def_var_double, 6}, {"R_nc4_def_var_char", (DL_FUNC) &R_nc4_def_var_char, 6}, {"R_nc4_def_dim", (DL_FUNC) &R_nc4_def_dim, 5}, {"R_nc4_redef", (DL_FUNC) &R_nc4_redef, 1}, {"R_nc4_rename_var", (DL_FUNC) &R_nc4_rename_var, 4}, {"R_nc4_inq_attname", (DL_FUNC) &R_nc4_inq_attname, 5}, {"R_nc4_def_var_chunking", (DL_FUNC) &R_nc4_def_var_chunking, 6}, {"R_nc4_inq_var_chunking", (DL_FUNC) &R_nc4_inq_var_chunking, 6}, {"R_nc4_def_var_deflate", (DL_FUNC) &R_nc4_def_var_deflate, 6}, {"R_nc4_inq_var_deflate", (DL_FUNC) &R_nc4_inq_var_deflate, 6}, {"R_nc4_inq_ngroups", (DL_FUNC) &R_nc4_inq_ngroups, 3}, {"R_nc4_inq_groupids", (DL_FUNC) &R_nc4_inq_groupids, 3}, {"R_nc4_util_nslashes", (DL_FUNC) &R_nc4_util_nslashes, 2}, {"R_nc4_inq_varid_hier_inner", (DL_FUNC) &R_nc4_inq_varid_hier_inner, 4}, {"R_nc4_inq_varid_hier", (DL_FUNC) &R_nc4_inq_varid_hier, 4}, {"R_nc4_get_vara_text", (DL_FUNC) &R_nc4_get_vara_text, 7}, {"R_nc4_put_vara_text", (DL_FUNC) &R_nc4_put_vara_text, 6}, {"R_nc4_enddef", (DL_FUNC) &R_nc4_enddef, 2}, {"R_nc4_sync", (DL_FUNC) &R_nc4_sync, 1}, {"R_nc4_close", (DL_FUNC) &R_nc4_close, 1}, {"R_nc4_def_grp", (DL_FUNC) &R_nc4_def_grp, 4}, {"R_ncu4_varid_onlyvar", (DL_FUNC) &R_ncu4_varid_onlyvar, 1}, {"R_ncu4_calc_start_count", (DL_FUNC) &R_ncu4_calc_start_count, 10}, {"R_ncu4_get_varsize", (DL_FUNC) &R_ncu4_get_varsize, 4}, {"R_ncu4_isdimvar", (DL_FUNC) &R_ncu4_isdimvar, 2}, {NULL} }; /* For C calls that use SEXP type args */ static const R_CallMethodDef callMethods[] = { {"Rsx_nc4_get_vara_double", (DL_FUNC) &Rsx_nc4_get_vara_double, 7}, {"Rsx_nc4_get_vara_int", (DL_FUNC) &Rsx_nc4_get_vara_int, 5}, {"R_nc4_get_att_string", (DL_FUNC) &R_nc4_get_att_string, 5}, {"Rsx_nc4_put_vara_double", (DL_FUNC) &Rsx_nc4_put_vara_double, 5}, {"Rsx_nc4_put_vara_int", (DL_FUNC) &Rsx_nc4_put_vara_int, 5}, {"R_nc4_blankstring", (DL_FUNC) &R_nc4_blankstring, 1}, {"R_nc4_grpname", (DL_FUNC) &R_nc4_grpname, 2}, {"R_nc4_inq_format", (DL_FUNC) &R_nc4_inq_format, 2}, {"R_nc4_set_NA_to_val_double", (DL_FUNC) &R_nc4_set_NA_to_val_double, 2}, {"R_nc4_get_vara_charvarid", (DL_FUNC) &R_nc4_get_vara_charvarid, 4}, {"R_nc4_get_vara_numvarid", (DL_FUNC) &R_nc4_get_vara_numvarid, 4}, {"R_ncu4_getListElement", (DL_FUNC) &R_ncu4_getListElement, 2}, {"R_nc4_get_vara_string", (DL_FUNC) &R_nc4_get_vara_string, 4}, {"R_nc4_inq_libvers", (DL_FUNC) &R_nc4_inq_libvers, 0}, {NULL} }; /********************************************************************* * Register our extnal routines for R */ void R_init_ncdf4( DllInfo *info ) { R_registerRoutines( info, cMethods, callMethods, NULL, NULL ); R_useDynamicSymbols( info, FALSE ); } /********************************************************************* * Converts from type "nc_type" to an integer as defined in the beginning * of this file. We do NOT use the raw nc_type integers because then the * R code would have a dependency on the arbitrary values in the netcdf * header files! */ int R_nc4_nctype_to_Rtypecode( nc_type nct ) { if( nct == NC_CHAR ) return(R_NC_TYPE_TEXT); else if( nct == NC_SHORT ) return(R_NC_TYPE_SHORT); else if( nct == NC_INT ) return(R_NC_TYPE_INT); else if( nct == NC_FLOAT ) return(R_NC_TYPE_FLOAT); else if( nct == NC_DOUBLE ) return(R_NC_TYPE_DOUBLE); else if( nct == NC_BYTE ) return(R_NC_TYPE_BYTE); else if( nct == NC_UBYTE ) return(R_NC_TYPE_UBYTE); else if( nct == NC_USHORT ) return(R_NC_TYPE_USHORT); else if( nct == NC_UINT ) return(R_NC_TYPE_UINT); else if( nct == NC_INT64 ) return(R_NC_TYPE_INT64); else if( nct == NC_UINT64 ) return(R_NC_TYPE_UINT64); else if( nct == NC_STRING ) return(R_NC_TYPE_STRING); else return(-1); } /*********************************************************************/ /* Returns a vector of dim sizes for the variable. * 'retval' is 0 for no error, or -1 for an error. */ void R_nc4_varsize( int *ncid, int *varid, int *ndims, int *varsize, int *retval ) { int i, err, dimid[NC_MAX_DIMS]; size_t dimlen; *retval = 0; /* Get ndims */ err = nc_inq_varndims( *ncid, *varid, ndims ); if( err != NC_NOERR ) { Rprintf( "Error in R_nc4_varsize on nc_inq_varndims call: %s\n", nc_strerror(err) ); *retval = -1; return; } /* Get dimids */ err = nc_inq_vardimid( *ncid, *varid, dimid ); if( err != NC_NOERR ) { Rprintf( "Error in R_nc4_varsize on nc_inq_vardimid call: %s\n", nc_strerror(err) ); *retval = -1; return; } /* Get size of each dim */ for( i=0; i<(*ndims); i++ ) { err = nc_inq_dimlen( *ncid, dimid[i], &dimlen ); if( err != NC_NOERR ) { Rprintf( "Error in R_nc4_varsize on nc_inq_dimlen call: %s\n", nc_strerror(err) ); *retval = -1; return; } varsize[i] = (int)dimlen; } } /*********************************************************************/ /* Returns 1 if this var has an unlimited dimension, 0 otherwise */ void R_nc4_inq_varunlim( int *ncid, int *varid, int *isunlim, int *retval ) { int i, ndims, unlimdimid, dimids[MAX_NC_DIMS]; /* Get the unlimited dim id */ *retval = nc_inq_unlimdim( *ncid, &unlimdimid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_varunlim while getting unlimdimid: %s\n", nc_strerror(*retval) ); return; } /* Get this var's ndims */ *retval = nc_inq_varndims( *ncid, *varid, &ndims ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_varunlim while getting ndims: %s\n", nc_strerror(*retval) ); Rprintf( "Using ncid=%d and varid=%d\n", *ncid, *varid ); return; } /* Get this var's dims */ *retval = nc_inq_vardimid( *ncid, *varid, dimids ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_varunlim while getting dimids: %s\n", nc_strerror(*retval) ); return; } *isunlim = 0; for( i=0; i= 1\n" ); INTEGER(sx_ierr_returned)[0] = -1; return( R_NilValue ); } /* Make space in C to hold array of pointers to strings */ strings = (char **)R_alloc( attlen, sizeof(char *) ); /* Read the strings from the netcdf file. Note that the netcdf library * call allocates space for the strings themselves */ if( (ierr = nc_get_att_string( ncid, varid, attname, strings )) != NC_NOERR ) { Rf_error( "Error, in call to R_nc4_get_att_string, failed to get the strings:\n" ); Rf_error( "%s\n", nc_strerror( ierr ) ); INTEGER(sx_ierr_returned)[0] = -1; return( R_NilValue ); } /* Initialize our return value */ sx_ret_str_array = PROTECT( NEW_CHARACTER( attlen )); /* make array with "attlen" strings */ /* Copy from our C array to an R array that we make. We do this so * that we can free the C netcdf-library allocated space, which * otherwise would never be freed */ for( i=0; i%s<\n", data[stridx] ); */ *retval = nc_put_vara_text(*ncid, *varid, s_start, s_count, data[stridx++] ); if( *retval != NC_NOERR ) { Rprintf( "Error (loc #4) in R_nc_put_vara_text: %s\n", nc_strerror(*retval) ); Rprintf( "Here was C-style start I tried: %lu %lu %lu\n", (unsigned long)s_start[0], (unsigned long)s_start[1], (unsigned long)s_start[2] ); Rprintf( "Here was C-style count I tried: %lu %lu %lu\n", (unsigned long)s_count[0], (unsigned long)s_count[1], (unsigned long)s_count[2] ); return; } } } else if( ndims == 4 ) { idx_k = 0; idx_j = 1; idx_string = 2; idx_char = 3; nk = s_count[idx_k]; nj = s_count[idx_j]; nstrings = s_count[idx_string]; /* number of character strings PER j,k */ /* Rprintf( "nstrings=%lu nj=%lu nk=%lu\n", (unsigned long)nstrings, (unsigned long)nj, (unsigned long)nk ); */ stridx = 0L; for( k=0L; k%s<\n", data[stridx] ); */ *retval = nc_put_vara_text(*ncid, *varid, s_start, s_count, data[stridx++] ); if( *retval != NC_NOERR ) { Rprintf( "Error (loc #5) in R_nc_put_vara_text: %s\n", nc_strerror(*retval) ); Rprintf( "Here was C-style start I tried: %lu %lu %lu %lu\n", (unsigned long)s_start[0], (unsigned long)s_start[1], (unsigned long)s_start[2], (unsigned long)s_start[3] ); Rprintf( "Here was C-style count I tried: %lu %lu %lu %lu\n", (unsigned long)s_count[0], (unsigned long)s_count[1], (unsigned long)s_count[2], (unsigned long)s_count[3] ); return; } } } else { *retval = -1; Rprintf("Error in R_nc_put_vara_text: unhandled case. I only handle char dims with # of dims up to 4. Was passed # dims = %d\n", ndims ); return; } } /*********************************************************************/ void R_nc4_def_var_byte( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_BYTE, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_byte: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_var_int( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_INT, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_int: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_var_short( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_SHORT, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_short: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_var_float( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_FLOAT, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_float: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_var_double( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_DOUBLE, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_double: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_var_char( int *ncid, char **varname, int *ndims, int *dimids, int *varid, int *retval ) { *retval = nc_def_var(*ncid, varname[0], NC_CHAR, *ndims, dimids, varid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_char: %s\n", nc_strerror(*retval) ); Rprintf( "Name of variable that the error occurred on: \"%s\"\n", varname[0] ); if( *retval == NC_ENAMEINUSE ) Rprintf( "I.e., you are trying to add a variable with that name to the file, but it ALREADY has a variable with that name!\n"); } } /*********************************************************************/ void R_nc4_def_dim( int *ncid, char **dimname, int *size, int *dimid, int *retval ) { *retval = nc_def_dim(*ncid, dimname[0], *size, dimid ); if( *retval != NC_NOERR ) Rprintf( "Error in R_nc4_def_dim: %s\n", nc_strerror(*retval) ); } /*********************************************************************/ void R_nc4_redef( int *ncid ) { int err; err = nc_redef(*ncid); if( err != NC_NOERR ) Rprintf( "Error in R_nc4_redef: %s\n", nc_strerror(err) ); } /*********************************************************************/ void R_nc4_rename_var( int *ncid, int *varid, char **newname, int *retval ) { *retval = nc_rename_var( *ncid, *varid, newname[0] ); if( *retval != NC_NOERR ) Rprintf( "Error in R_nc4_rename_var: %s\n", nc_strerror(*retval) ); } /*********************************************************************/ void R_nc4_inq_attname( int *ncid, int *varid, int *attnum, char **attname, int *retval ) { *retval = nc_inq_attname( *ncid, *varid, *attnum, attname[0] ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_attname: %s\n", nc_strerror(*retval) ); } } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group varid: var ID to set the deflate params for ndims: number of dims in the variable storage: either 1 for NC_CONTIGUOUS or 2 for NC_CHUNKED chunksizesp: pointer to array indicating chunk sizes along each dimension Outputs: ierr: 0 on success, otherwise an error was encountered */ void R_nc4_def_var_chunking( int *root_id, int *varid, int *ndims, int *storage, int *chunksizesp, int *ierr ) { int stor_param, i; size_t sizet_chunkparam[MAX_NC_DIMS]; if( (*storage != 1) && (*storage != 2)) { Rprintf( "R_nc4_def_var_chunking: bad value of storage parameter passed: %d. Must be 1 (NC_CONTIGUOUS) or 2 (NC_CHUNKED).\n", *storage ); *ierr = -1; return; } if( *storage == 1 ) stor_param = NC_CONTIGUOUS; else stor_param = NC_CHUNKED; if( *ndims > MAX_NC_DIMS ) { Rprintf( "R_nc4_def_var_chunking: Error: ndims too large, max is %d but passed value is %d\n", MAX_NC_DIMS, *ndims ); *ierr = -1; return; } for( i=0; i<(*ndims); i++ ) sizet_chunkparam[i] = (size_t)(*(chunksizesp+i)); *ierr = nc_def_var_chunking( *root_id, *varid, stor_param, sizet_chunkparam ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_chunking: %s\n", nc_strerror(*ierr) ); } } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group varid: var ID to set the deflate params for ndims: number of dims in the variable Outputs: storage: either 1 for NC_CONTIGUOUS or 2 for NC_CHUNKED chunksizesp: pointer to array indicating chunk sizes along each dimension. NOTE: THIS MUST BE ALLOCATED BEFORE CALLING THIS ROUTINE!! Returned values are in C order (which is opposite R order) ierr: 0 on success, otherwise an error was encountered */ void R_nc4_inq_var_chunking( int *root_id, int *varid, int *ndims, int *storage, int *chunksizesp, int *ierr ) { int stor_param, i; size_t sizet_chunkparam[MAX_NC_DIMS]; *ierr = nc_inq_var_chunking( *root_id, *varid, &stor_param, sizet_chunkparam ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_var_chunking: %s\n", nc_strerror(*ierr) ); return; } if( stor_param == NC_CONTIGUOUS ) *storage = 1; else if( stor_param == NC_CHUNKED ) *storage = 2; else { Rprintf( "Error in R_nc4_inq_var_chunking: obtained value of storage is neither NC_CONTIGUOUS nor NC_CHUNKED! Value=%d\n", stor_param ); *ierr = -1; return; } for( i=0; i<(*ndims); i++ ) chunksizesp[i] = (int)(sizet_chunkparam[i]); } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group varid: var ID to inquire about the deflate params for Outputs: shuffle: if 1, shuffle filter is turned on for this var; otherwise, this is set to 0 deflate: if 1, deflate (compression) filter is turned on for this var; otherwise, this is set to 0 deflate_level: If deflate == 1, this is set to the deflate level for this var (0-9) ierr: 0 on success, otherwise an error was encountered */ void R_nc4_inq_var_deflate( int *root_id, int *varid, int *shuffle, int *deflate, int *deflate_level, int *ierr ) { *ierr = nc_inq_var_deflate( *root_id, *varid, shuffle, deflate, deflate_level ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_var_deflate: %s\n", nc_strerror(*ierr) ); } } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group varid: var ID to set the deflate params for shuffle: if 1, turn on shuffle filter; otherwise, must be 0 deflate: if 1, turn on deflate (compression) filter; otherwise, must be 0 deflate_level: must be bewteen 0 and 9. If deflate != 0, set deflate to this level. Outputs: ierr: 0 on success, otherwise an error was encountered */ void R_nc4_def_var_deflate( int *root_id, int *varid, int *shuffle, int *deflate, int *deflate_level, int *ierr ) { if( (*shuffle != 0) && (*shuffle != 1)) { Rprintf( "R_nc4_def_var_deflate: bad value of shuffle parameter passed: %d. Must be 0 or 1.\n", *shuffle ); *ierr = -1; return; } if( (*deflate != 0) && (*deflate != 1)) { Rprintf( "R_nc4_def_var_deflate: bad value of deflate parameter passed: %d. Must be 0 or 1.\n", *deflate ); *ierr = -1; return; } if( (*deflate_level < 0) || (*deflate_level > 9)) { Rprintf( "R_nc4_def_var_deflate: bad value of deflate_level parameter passed: %d. Must be between 0 and 9, inclusive.\n", *deflate_level ); *ierr = -1; return; } *ierr = nc_def_var_deflate( *root_id, *varid, *shuffle, *deflate, *deflate_level ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_def_var_deflate: %s\n", nc_strerror(*ierr) ); } } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group Outputs: ngroups: How many groups are BELOW the specified root group ierr: 0 on success, otherwise an error was encountered */ void R_nc4_inq_ngroups( int *root_id, int *ngroups, int *ierr ) { *ierr = nc_inq_grps( *root_id, ngroups, NULL ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_ngroups: %s\n", nc_strerror(*ierr) ); } } /*********************************************************************/ /* Inputs: root_id: netcdfID of the root group Outputs: gids: IDs of the groups below the root group, must already be allocated! ierr: 0 on success, otherwise an error was encountered */ void R_nc4_inq_groupids( int *root_id, int *gids, int *ierr ) { *ierr = nc_inq_grps( *root_id, NULL, gids ); if( *ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_inq_groupids: %s\n", nc_strerror(*ierr) ); } } /*********************************************************************/ /* Code kindly donated by Martin Morgan of the Fred Hutchinson * Cancer Research Center */ SEXP R_nc4_blankstring(SEXP size) { int i, len; char *str; SEXP blank, string; if (!IS_INTEGER(size) || LENGTH(size)!=1) Rf_error("'size' must be 'integer(1)'"); len = INTEGER(size)[0]; if (len < 0) Rf_error("'size' must be >= 0"); str = R_alloc(len + 1, sizeof(char)); for (i = 0; i < len; ++i) str[i] = ' '; str[len] = '\0'; blank = PROTECT(NEW_CHARACTER(1)); string = PROTECT(mkChar(str)); SET_STRING_ELT(blank, 0, string); UNPROTECT(2); return(blank); } /*********************************************************************/ /* Input: sx_root_id: integer group id Outputs: sx_ierr: set to 0 on success, -1 on failure returned value: a string witht he group name */ SEXP R_nc4_grpname(SEXP sx_root_id, SEXP sx_ierr_retval) { int root_id, ierr; size_t nchar; char *str; SEXP sx_retval, sx_string; INTEGER(sx_ierr_retval)[0] = 0; /* start with 'no error' condition */ /* Make sure our passed args are the right type and size */ if (!IS_INTEGER(sx_root_id) || LENGTH(sx_root_id)!=1) Rf_error("Passed argument sx_root_id must be 'integer(1)'"); if (!IS_INTEGER(sx_ierr_retval) || LENGTH(sx_ierr_retval)!=1) Rf_error("Passed argument sx_ierr_retval must be 'integer(1)'"); /* Turn R sx_value into ordinary integer */ root_id = INTEGER(sx_root_id)[0]; /* Get # of chars in group name */ ierr = nc_inq_grpname_len( root_id, &nchar ); if( ierr != 0 ) { Rprintf( "Error in R_nc_grpname: on call to nc_inq_grpname_len: %s\n", nc_strerror(ierr) ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } /* Make space for C string to be returned */ str = R_alloc(nchar + 1, sizeof(char)); ierr = nc_inq_grpname( root_id, str ); if( ierr != 0 ) { Rprintf( "Error in R_nc_grpname: on call to nc_inq_grpname: %s\n", nc_strerror(ierr) ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } str[nchar] = '\0'; sx_retval = PROTECT(NEW_CHARACTER(1)); sx_string = PROTECT(mkChar(str)); SET_STRING_ELT(sx_retval, 0, sx_string); UNPROTECT(2); return(sx_retval); } /*********************************************************************/ /* Input: sx_root_id: integer group id Outputs: sx_ierr: set to 0 on success, -1 on failure returned value: an integer as follows: NC_FORMAT_CLASSIC: 1 NC_FORMAT_64BIT: 2 NC_FORMAT_NETCDF4: 3 NC_FORMAT_NETCDF4_CLASSIC: 4 */ SEXP R_nc4_inq_format(SEXP sx_root_id, SEXP sx_ierr_retval) { int root_id, ierr; int iformat, iretval; SEXP sx_retval; INTEGER(sx_ierr_retval)[0] = 0; /* start with 'no error' condition */ /* Make sure our passed args are the right type and size */ if (!IS_INTEGER(sx_root_id) || LENGTH(sx_root_id)!=1) Rf_error("Passed argument sx_root_id must be 'integer(1)'"); if (!IS_INTEGER(sx_ierr_retval) || LENGTH(sx_ierr_retval)!=1) Rf_error("Passed argument sx_ierr_retval must be 'integer(1)'"); /* Turn R sx_value into ordinary integer */ root_id = INTEGER(sx_root_id)[0]; /* Get format */ ierr = nc_inq_format( root_id, &iformat ); if( ierr != 0 ) { Rprintf( "Error in R_nc4_inq_format: on call to nc_inq_format: %s\n", nc_strerror(ierr) ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } switch(iformat) { case NC_FORMAT_CLASSIC: iretval = 1; break; case NC_FORMAT_64BIT: iretval = 2; break; case NC_FORMAT_NETCDF4: iretval = 3; break; case NC_FORMAT_NETCDF4_CLASSIC: iretval = 4; break; case NC_FORMAT_CDF5: iretval = 5; break; default: Rprintf( "Error in R_nc4_inq_format: unrecognized format integer returned: %d\n", iformat ); INTEGER(sx_ierr_retval)[0] = -1; /* Indicate error condition */ return( NULL ); } PROTECT( sx_retval = allocVector(INTSXP, 1)); INTEGER(sx_retval)[0] = iretval; UNPROTECT(1); return(sx_retval); } /*********************************************************************/ /* This goes through an input array, and replaces all NA's in that array * with the passed value. */ SEXP R_nc4_set_NA_to_val_double(SEXP sx_dat, SEXP sx_val ) { int nels; size_t i; double val = REAL(sx_val)[0]; nels = GET_LENGTH( sx_dat ); for( i=0L; i%s<\n", varname ); */ /* Passed var name must not start with a slash */ if( varname[0] == '/' ) { Rprintf( "Error in R_nc4_varid_hier: passed varname must not start with a slash!\n" ); *returned_varid = -1; *returned_grpid = -1; return; } /* If there are no forward slashes in the name, then it is a simple var name */ nslashes = R_nc4_util_nslashes( varname, &idx_first_slash ); /* Rprintf("R_nc4_inq_varid_hier_inner: varname >%s< has nslashes=%d and idx first slash=%d\n", varname, nslashes, idx_first_slash ); */ if( nslashes == 0 ) { *returned_grpid = *ncid; ierr = nc_inq_varid(*ncid, varname, returned_varid ); if( ierr != NC_NOERR ) { *returned_varid = -1; *returned_grpid = -1; } /* Rprintf("R_nc4_inq_varid_hier_inner: Found id for var >%s< varid:%d gid:%d\n", varname, *returned_varid, *returned_grpid ); */ return; } /* If we get here then the varname must have at least one slash, which indicates * a group name under the current group name. Get the ID of that group */ strncpy( gname, varname, idx_first_slash ); gname[ idx_first_slash ] = '\0'; ierr = nc_inq_grp_ncid( *ncid, gname, &gid ); if( ierr != NC_NOERR ) { Rprintf( "Error in R_nc4_varid_hier: extracted groupname not found: >%s< (coding error?)\n", gname ); *returned_varid = -1; *returned_grpid = -1; return; } /* Call ourselves recursively with the subgroup id and the varname stripped * of its leading group name */ /* Rprintf("R_nc4_inq_varid_hier_inner: calling myself recursively with varname=>%s<\n", varname+idx_first_slash+1 ); */ R_nc4_inq_varid_hier_inner( &gid, varname+idx_first_slash+1, returned_grpid, returned_varid ); } /****************************************************************************************/ /* This version of inq_varid works with hierarchial var names such as "model1/TS" and * returns both the group ID and the var ID in that group, given the root group id * (netcdf file ID). * * If the passed var is not found in the file, then -1 is returned. * * The passed slash-ful varname must not start or end with a slash. */ void R_nc4_inq_varid_hier( int *ncid, char **varname, int *returned_grpid, int *returned_varid ) { /* Rprintf("R_nc4_inq_varid_hier: entering for var >%s<\n", varname[0] ); */ R_nc4_inq_varid_hier_inner( ncid, varname[0], returned_grpid, returned_varid ); } /*********************************************************************/ void R_nc4_enddef( int *ncid, int *retval ) { int err; err = nc_enddef(*ncid); if( err != NC_NOERR ) Rprintf( "Error in R_nc4_enddef: %s\n", nc_strerror(err) ); *retval = err; } /*********************************************************************/ void R_nc4_sync( int *ncid ) { int err; err = nc_sync(*ncid); if( err != NC_NOERR ) Rprintf( "Error in R_nc4_sync: %s\n", nc_strerror(err) ); } /*********************************************************************/ void R_nc4_close( int *ncid ) { int err; err = nc_close(*ncid); if( err != NC_NOERR ) Rprintf( "Error in R_nc4_close: %s\n", nc_strerror(err) ); } /*********************************************************************/ void R_nc4_def_grp( int *parent_ncid, char **grpname, int *new_ncid, int *retval ) { *retval = nc_def_grp(*parent_ncid, grpname[0], new_ncid ); if( *retval != NC_NOERR ) { Rprintf( "Error in R_nc4_def_grp: %s\n", nc_strerror(*retval) ); Rprintf( "Name of group that the error occurred on: \"%s\"\n", grpname[0] ); } } /*========================================================================================================*/ /*========================================================================================================*/ /*========================================================================================================*/ /********************************************************************************* * Return the varid of the only var in the file, or -1 if more than one. */ int R_ncu4_varid_onlyvar( int ncid ) { int ierr, nvars, varid, i, dimid; char varname[MAX_NC_NAME]; varid = -1; ierr = nc_inq_nvars( ncid, &nvars ); if( ierr != NC_NOERR ) error("Error reading from netcdf file!"); for( i=0; i1). To figure * this out we need to get the vector of dimlengths for this var. *-------------------------------------------------------------*/ if( R_ncu4_get_varsize( ncid, varid, ndims, varsize ) == -1 ) error("read of netcdf file failed when getting variable size"); n_nondegen_dims = 0; for( i=0; i 1 ) n_nondegen_dims++; if( len_start != n_nondegen_dims ) { error( "Error, passed argument 'start' has length %d, but must either have a length equal to the number of dimensions (%d) OR the number of non-degenerate dimensions (%d)\n", len_start, ndims, n_nondegen_dims ); } /*----------------------------------------------------------------- * If we get here, user has specified non-degen dimensions only ... * translate this to a start string we can use. *----------------------------------------------------------------*/ j = 0; for( i=0; i1). To figure * this out we need to get the vector of dimlengths for this var. *-------------------------------------------------------------*/ n_nondegen_dims = 0; for( i=0; i 1 ) n_nondegen_dims++; if( len_count != n_nondegen_dims ) { error( "Error, passed argument 'count' has length %d, but must either have a length equal to the number of dimensions (%d) OR the number of non-degenerate dimensions (%d)\n", len_count, ndims, n_nondegen_dims ); } /*----------------------------------------------------------------- * If we get here, user has specified non-degen dimensions only ... * translate this to a count string we can use. *----------------------------------------------------------------*/ j = 0; for( i=0; i 1 ) ndims_cgt1++; if( ndims_cgt1 == 0 ) { PROTECT( sx_dim = allocVector( INTSXP, 1 )); INTEGER(sx_dim)[0] = 1; } else { PROTECT( sx_dim = allocVector( INTSXP, ndims_cgt1 )); j = 0; for( i=0; i 1 ) { INTEGER(sx_dim)[ndims_cgt1-j-1] = count[i]; j++; } } setAttrib( rv_data, R_DimSymbol, sx_dim ); UNPROTECT(2); return(rv_data); } /******************************************************************************* * Internal utility function to get the vector of the variable's dim sizes. * Returns 0 on success, -1 if an error is encountered. */ int R_ncu4_get_varsize( int ncid, int varid, int ndims, size_t *varsize ) { int ierr, i, dimids[MAX_NC_DIMS]; size_t len; ierr = nc_inq_vardimid( ncid, varid, dimids ); if( ierr != NC_NOERR ) { error( "Internal error in ncdf package, routine R_ncu4_get_varsize: error while reading file to get var's dimids!\n" ); return(-1); } for( i=0; i=0) && (varid$id<=100000) && (varid$group_id >= 0)) if( is.na(varidOK) || (!varidOK)) { print("vobjtovarid4: I was passed a ncvar object, BUT this object does NOT refer to any valid var in the netcdf file!") print(paste("This happened for netCDF filename:",nc$filename)) print("Here are the vars in the netCDF file:") for( ii in 1:nc$nvars ) print(paste(ii,": ",nc$var[[ii]]$name, sep='' )) print(paste("The passed varid object (which does NOT exist in that file) is:")) print(origvarid) print(paste("Hint: make SURE the variable was not only defined with a call to ncvar_def(), but also included in the list of variables passed to nc_create()")) stop("stopping") } if( verbose ) print(paste("vobjtovarid4: returning with varid deduced from a passed ncvar object; varid=", varid$group_id, varid$id)) return(varid) # an object of class 'ncid4' } #------------------------------------------------------------- # Handle case where we are given an ncdim object to begin with #------------------------------------------------------------- #if( class(varid) == "ncdim4" ) { if( isc_ncdim4 ) { if( ! allowdimvar ) stop(paste("Error, I was NOT allowed to check dimvars, but the second argument passed was an object of class ncdim4! Name=", varid$name)) if(verbose) print(paste("vobjtovarid4: passed a ncdim class, name=",varid$name)) #----------------------------------------------------------- # Go through and find if there is a dim in the file that has # the same name as this dim. We do not immediately use # this dim's dimvarid in case the dim is from a different # file but has the same name. #----------------------------------------------------------- name2find = varid$name foundit = FALSE for( idim in 1:nc$ndims ) { if( nc$dim[[idim]]$name == name2find ) { #------------------------------------------- # Remember we return the DIMVAR, not the dim #------------------------------------------- retval = nc$dim[[idim]]$dimvarid # an object of type 'ncid' foundit = TRUE break } } if( ! foundit ) #----------------------------------------------------------- # Return an ncid that indicates this is a dimvar but it does # not exist in the file #----------------------------------------------------------- retval = ncdf4_make_id( id=-1, group_index=-1, group_id=-1, list_index=-1, isdimvar=TRUE ) #if( class(retval) != 'ncid4' ) if( ! inherits( retval, 'ncid4' )) stop(paste("Internal error #C, returned varid is not a object of class ncid4. Case with ncdim object passed; ncdim name=", varid$name)) if( verbose ) print(paste("vobjtovarid4: returning with varid deduced from a passed ncvar object; retval=", retval$group_id, retval$id)) return(retval) # an object of class 'ncid4' } #---------------------------------------------------------- # If we get here, 'varid' can be a NA or a character string #---------------------------------------------------------- #--------------------------------------------------------------------------- # If varid is NA, then return the only var in the file (if there IS only one # var in the file). If there is more than one var in the file, return the # one with the most dimensions, IF that highest-dimensionality var has more # dimensions than any other var in the file. Otherwise, generate an error. #--------------------------------------------------------------------------- if( (length(varid)==1) && is.na(varid)) { if( nc$nvars == 1 ) { varToUse <- 1 } else { #------------------------------------------------------------ # Choose the most complicated var, if there is one, otherwise # halt with an error #------------------------------------------------------------ varToUse <- -1 ndimsItHas <- -1 for( ii in 1:nc$nvars ) { if( nc$var[[ii]]$ndims > ndimsItHas ) { varToUse <- ii ndimsItHas <- nc$var[[ii]]$ndims } } for( ii in 1:nc$nvars ) { if( (ii != varToUse) && (nc$var[[ii]]$ndims == ndimsItHas)) { stop(paste("File",nc$filename,"has more than one variable, so you must explicitly specify which one you want")) } } } varid <- nc$var[[varToUse]]$id # remember, an object of class 'ncid4', not a simple int #if( class(varid) != 'ncid4' ) if( ! inherits( varid, 'ncid4' )) stop(paste("internal error #B, returned varid is not of class ncid4")) if( verbose ) print(paste("vobjtovarid4: returning with only var in file; id=", nc$var[[varToUse]]$id$group_id, nc$var[[varToUse]]$id$id)) return( varid ) # an object of class 'ncid4' } #--------------------------------------------------- # If we get here, 'varid' must be a character string #--------------------------------------------------- if( ! is.character(varid)) stop("internal error: location #M: varid is not a character string!") origvarid <- varid #------------------------------------------- # Make sure var name follows our conventions #------------------------------------------- if( substr(varid,1,1) == '/' ) stop(paste("Error, I was given a name that starts with a slash; fully qualified names NEVER start with a slash (this is required for backwards compatability). Leave off the leading slash!")) #-------------------------------------------- # See if any vars in this file have this name #-------------------------------------------- varToUse <- -1 if( nc$nvars > 0 ) { for( kk in 1:nc$nvars ) { if( origvarid == nc$var[[kk]]$name ) # check to see if fully qualified name matches varToUse <- kk } } #--------------------------------- # Found a var with the right name, # return its ncid object #--------------------------------- if( varToUse != -1 ) { if(verbose) print(paste("Variable named",origvarid,"found in file with varid=", nc$var[[varToUse]]$id$group_id, nc$var[[varToUse]]$id$id)) varid <- nc$var[[varToUse]]$id # remember, an object of class 'ncid4', not a simple int #if( class(varid) != 'ncid4' ) { if( ! inherits( varid, 'ncid4' )) { print('---- varid:') print(varid) stop(paste("internal error #A, returned varid is not of class ncid4")) } return( varid ) # an object of class 'ncid4' } #--------------------------------------------------------------- # A var with this name was NOT found in the file. But, it could # be the name of a dimvar in the file. Check to see if we are # allowed to return dimvars in this case. #--------------------------------------------------------------- if( ! allowdimvar ) { print("vobjtovarid4: error #G: I could not find the requested var in the file!") print(paste("requested var name:",origvarid)) print(paste("file name:",nc$filename)) print("Note: I was NOT allowed to check to see if this was a dimvar name") stop("Variable not found") } if(verbose) print(paste("Variable named",origvarid,"NOT found in file; looking for a dimvar with this name")) #----------------------------------------------- # Check to see if passed name matches a dim name #----------------------------------------------- for( i in 1:nc$ndims ) { if( origvarid == nc$dim[[i]]$name ) { #--------------------- # Yes, it IS a dimvar! #--------------------- varid <- nc$dim[[i]]$dimvarid # note: an object of class 'ncid4'. $id will be -1 if there is no dimvar #if( class(varid) != 'ncid4' ) if( ! inherits( varid, 'ncid4' )) stop(paste("Internal error #D, returned varid is not a object of class ncid4")) if( verbose ) print(paste("vobjtovarid4: returning with DIMvarid deduced from name; varid$group_id=", varid$group_id, 'varid$id=', varid$id)) if( varid$id == -1 ) print(paste("vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named", origvarid, "BUT this dimension HAS NO DIMVAR! Code will probably fail at this point")) return(varid) # an object of class 'ncid4' } } #------------------------------------------------------------ # If we get here, no dimvar with the requested name was found #------------------------------------------------------------ print("vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!") print(paste("var (or dimvar) name:",origvarid)) print(paste("file name:",nc$filename)) stop("Variable not found") } #=============================================================== # Internal use only. Passed IDs must be C-style (0-based counting) # simple integers, with the ncid being a group ID if appropriate. # ncvar_inq <- function( ncid, varid ) { if( ! is.numeric(ncid)) stop("Error: the first argument to ncvar_inq (ncid) is not an integer") if( ! is.numeric(varid)) stop("Error: the second argument to ncvar_inq (varid) is not an integer") #------------------------------------------------------ # This is a string NC_MAX_LEN long, to provide storage. # I'm not sure if this is needed or not.... #------------------------------------------------------ str.nc.max.name <- "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" rv <- list() rv$name <- str.nc.max.name rv$varlen <- -1 rv$error <- -1 rv$type <- -1 rv$ndims <- -1 rv$natts <- -1 rv$precint <- -1 # INTEGER (not character) form of precision. 1=SHORT, 2=INT, 3=FLOAT, 4=DOUBLE, 5=CHAR 6=BYTE, 7=UBYTE, 8=USHORT, 9=UINT, 10=INT64, 11=UINT64, 12=STRING. Must match C code values defined in the top of file ncdf.c rv$dimids <- integer(ncvar_ndims( ncid, varid )) rv <- .C("R_nc4_inq_var", as.integer(ncid), as.integer(varid), name=as.character(rv$name), type=as.integer(rv$type), ndims=as.integer(rv$ndims), dimids=as.integer(rv$dimids), natts=as.integer(rv$natts), precint=as.integer(rv$precint), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("call to C function R_nc4_inq_var failed") var <- list() var$id <- ncdf4_make_id( id=varid, group_index=-1, group_id=ncid, list_index=-1, isdimvar=FALSE ) var$name <- rv$name var$ndims <- rv$ndims var$natts <- rv$natts var$size <- ncvar_size( ncid, varid ) var$dimids <- rv$dimids var$prec <- ncvar_type_to_string( rv$precint ) #--------------------------------------------------- # Convert ordering of dimids from C to R conventions #--------------------------------------------------- var$dimids <- var$dimids[ var$ndims:1 ] #-------------------------- # Get this var's attributes #-------------------------- attu <- ncatt_get_inner( ncid, varid, "units" ) if( attu$hasatt ) var$units <- attu$value else var$units <- "" attu <- ncatt_get_inner( ncid, varid, "long_name" ) if( attu$hasatt ) var$longname <- attu$value else var$longname <- var$name return(var) } #=============================================================== # Returns a vector of the size of the variable, in # R order (XYZT). # # Internal use only. Use v$varsize (where v is an object of # class "ncvar4") if you want this info. # # BOTH inputs MUST be simple integers, class objects are not allowed! # The integers are raw C-style (0-based counting), with the ncid # actually being the group ID if necessary. # # A scalar variable (one with no dims) always returns a # varsize of 1. # ncvar_size <- function( ncid, varid ) { if( mode(ncid) != 'numeric' ) stop(paste("error, must be passed a numeric first arg: ncid2use, not an arg of mode", mode(ncid))) if( mode(varid) != 'numeric' ) stop("Error, must be passed a numeric second arg: varid2use" ) ndims <- ncvar_ndims( ncid, varid ) if( ndims == 0 ) #return(vector()) changed DWP 2012-09-20 return(1) # indicates a scalar var rv <- list() rv$error <- -1 rv$varsize <- integer(ndims) rv$ndims <- -1 rv <- .C("R_nc4_varsize", as.integer(ncid), as.integer(varid), ndims=as.integer(rv$ndims), varsize=as.integer(rv$varsize), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("error returned from C routine R_nc4_varsize") #------------------------------------- # Switch order from C-style to R-style #------------------------------------- rv$varsize <- rv$varsize[ ndims:1 ] return(rv$varsize) } #=============================================================== # Internal use only. # # Input: integer ncid and varid. # # Output: one of the # integer R type codes (1=short, 2=int, 3=float, 4=double, # 5=char, 6=byte, 7=ubyte, 8=ushort, 9=uint, 10=int64, 11=uint64, 12=string). # These are defined at the top of file ncdf.c # ncvar_type <- function( ncid, varid, output_string=FALSE ) { if( mode(ncid) != 'numeric' ) stop("error, must be passed a numeric first arg: ncid2use") if( mode(varid) != 'numeric' ) stop("Error, must be passed a numeric second arg: varid2use" ) rv <- list() rv$error <- -1 rv$precint <- -1 rv <- .C("R_nc4_inq_vartype", as.integer(ncid), as.integer(varid), precint=as.integer(rv$precint), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("error returned from C call") return( rv$precint ) } #====================================================================== # Internal use only. Takes an integer precision type, converts it # to a string. Valus are defined at the top of file ncdf.c, and are # not the same as in any netcdf header, since I don't want my code # to depend on values in any netcdf library headers # ncvar_type_to_string = function( precint ) { if( precint == 1 ) prec <- "short" else if( precint == 2 ) prec <- "int" else if( precint == 3 ) prec <- "float" else if( precint == 4 ) prec <- "double" else if( precint == 5 ) prec <- "char" else if( precint == 6 ) prec <- "byte" else if( precint == 7 ) prec <- "unsigned byte" else if( precint == 8 ) prec <- "unsigned short" else if( precint == 9 ) prec <- "unsigned int" else if( precint == 10 ) prec <- "8 byte int" else if( precint == 11 ) prec <- "unsinged 8 byte int" else if( precint == 12 ) prec <- "string" else stop(paste("Error, unrecognized type code of variable supplied:", precint )) return( prec ) } #=============================================================== # Internal use only. Use v.ndims if you want this info. # # Inputs are both integers # Output is integer number of dims in the var # ncvar_ndims <- function( ncid, varid ) { if( mode(ncid) != 'numeric' ) stop(paste("error, ncvar_ndims must be passed a numeric first arg; mode of val passed=", mode(ncid))) if( mode(varid) != 'numeric' ) stop("Error, ncvar_ndims must be passed a numeric second arg: varid2use" ) rv <- list() rv$error <- -1 rv$ndims <- -1 rv <- .C("R_nc4_inq_varndims", as.integer(ncid), as.integer(varid), ndims=as.integer(rv$ndims), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("error returned from C call") return( rv$ndims ) } #=============================================================== # Internal use only # # Inputs: ncid = integer # varname = character. Should NOT be fully qualified # var name; instead the ncid should be for the proper # group where this var is thought to live. # # Returns -1 if the var is NOT found in the file, and the # raw C-style integer varid of the var otherwise. # ncvar_id <- function( ncid, varname ) { if( mode(ncid) != 'numeric' ) stop("error, must be passed a numeric first arg: ncid2use") if( mode(varname) != 'character' ) stop("Error, must be passed a character second arg: varname" ) if( nslashes_ncdf4(varname) > 0 ) stop(paste("Error, var name should NOT be fully qualifed var name!! Name=", varname)) rv <- list() rv$varid <- -1 rv <- .C("R_nc4_inq_varid", as.integer(ncid), as.character(varname), varid=as.integer(rv$varid), PACKAGE="ncdf4") return(rv$varid) } #=============================================================== # Internal use only # # Inputs: ncid = integer # varname = character. Can be a varname with slashes # in it representing groups. # # Returns -1 if the var is NOT found in the file, and the # raw C-style integer varid of the var otherwise. # ncvar_id_hier <- function( ncid, varname ) { if( mode(ncid) != 'numeric' ) stop("error, must be passed a numeric first arg: ncid2use") if( mode(varname) != 'character' ) stop("Error, must be passed a character second arg: varname" ) rv <- list() rv$varid <- -1 rv$groupid <- -1 rv <- .C("R_nc4_inq_varid_hier", as.integer(ncid), as.character(varname), groupid=as.integer(rv$groupid), varid=as.integer(rv$varid), PACKAGE="ncdf4") retval = c( rv$varid, rv$groupid ) return( retval ) } #=========================================================================================== # This differs from the 'standard' (non-'inner') version by # taking ONLY the raw, C-standard correct integers for ncid # and varid. Note that if the variable is in a group, then # the passed ncid must actually be the correct group ID, despite # its name. # # 'missval' is the value of the variable's missing value attribute # (or NA if the variable does not have such an attribute). Any # read-in values that are equal to missval are set to NA. # # if raw_datavals==TRUE, then the actual raw data values from the # file are returned with no conversion to NA (if missing) or # scale/offset applied # ncvar_get_inner <- function( ncid, varid, missval, addOffset=0., scaleFact=1.0, start=NA, count=NA, verbose=FALSE, signedbyte=TRUE, collapse_degen=TRUE, raw_datavals=FALSE ) { if( ! is.numeric(ncid)) stop("Error, first arg passed to ncvar_get_inner (ncid) must be a simple C-style integer that is passed directly to the C api") if( ! is.numeric(varid)) stop("Error, second arg passed to ncvar_get_inner (varid) must be a simple C-style integer that is passed directly to the C api") if( verbose ) { print(paste("ncvar_get_inner: entering with (C-STYLE INTEGER ONLY) ncid=", ncid, "varid=", varid )) print(paste("ncvar_get_inner: following line is collapse_degen:")) print(collapse_degen) } tmp_typename = c('short', 'int', 'float', 'double', 'char', 'byte' ) have_start = (length(start)>1) || ((length(start)==1) && (!is.na(start))) have_count = (length(count)>1) || ((length(count)==1) && (!is.na(count))) sm <- storage.mode(start) if( (sm != "double") && (sm != "integer") && (sm != "logical")) stop(paste("passed a start argument of storage mode",sm,"; can only handle double or integer")) sm <- storage.mode(count) if( (sm != "double") && (sm != "integer") && (sm != "logical")) stop(paste("passed a 'count' argument with storage mode '",sm,"'; can only handle double or integer", sep='')) if( signedbyte ) byte_style = 1 # 1=signed else byte_style = 2 # 2=unsigned varsize <- ncvar_size ( ncid, varid ) ndims <- ncvar_ndims( ncid, varid ) if( verbose ) { print(paste("ndims:",ndims)) print("ncvar_get: varsize:") print(varsize) } #------------------------------ # Fix up start and count to use #------------------------------ if( ndims == 0 ) { start <- 1 count <- 1 } else { if( ! have_start ) start <- rep(1,ndims) # Note: use R convention for now if( ! have_count ) count <- varsize - start + 1 else { #------------------ # Take care of -1's #------------------ count <- ifelse( (count == -1), varsize-start+1, count) } } if( verbose ) { print("ncvar_get_inner: start:") print(start) print("ncvar_get_inner: count:") print(count) } if( ndims > 0 ) { if( length(start) != ndims ) stop(paste("Error: variable has",ndims,"dims, but start has",length(start),"entries. They must match!")) if( length(count) != ndims ) stop(paste("Error: variable has",ndims,"dims, but count has",length(count),"entries. They must match!")) } #---------------------------------------- # Need to know how much space to allocate #---------------------------------------- totvarsize <- prod(count) if( verbose ) print(paste("ncvar_get: totvarsize:",totvarsize)) #-------------------------------------------------- # Switch from R to C convention for start and count #-------------------------------------------------- c.start <- start[ ndims:1 ] - 1 c.count <- count[ ndims:1 ] rv <- list() rv$error <- -1 #--------------------------------- # Get the correct type of variable #--------------------------------- precint <- ncvar_type( ncid, varid ) # 1=short, 2=int, 3=float, 4=double, 5=char, 6=byte, 7=ubyte, 8=ushort, 9=uint, 10=int64, 11=uint64, 12=string if( verbose ) print(paste("ncvar_get_inner: getting var of type",tmp_typename[precint], 'id=', precint)) if( (precint == 1) || (precint == 2) || (precint == 6) || (precint == 7) || (precint == 8)) { #-------------------------------- # Short, Int, Byte, UByte, UShort #-------------------------------- rv <- .Call("Rsx_nc4_get_vara_int", as.integer(ncid), as.integer(varid), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... as.integer(byte_style), # 1=signed, 2=unsigned PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function Rsx_nc4_get_var_int returned error") data = rv$data } else if( (precint == 3) || (precint == 4)) { #----------------------------------------------------------------- # Float, double where we have the C routine fix the missing value. # 'imvstate' is: 0 if we do not have a missing value (it is NULL), # 1 if the missing value is NA, 2 if the missing value is present # and not NULL and not NA. These codes are used by the C routine. #----------------------------------------------------------------- if( is.null( missval )) { passed_missval = 0.0 imvstate = as.integer(0) } else if( is.na(missval)) { passed_missval = 0.0 imvstate = as.integer(1) } else { passed_missval = missval imvstate = as.integer(2) } if( raw_datavals ) fixmiss = as.integer(0) # setting 'raw_datavalues' to TRUE gives the actual raw numbers from the file, not processed at all else fixmiss = as.integer(1) if( verbose ) print('about to call Rsx_nc4_get_vara_double...') rv <- .Call("Rsx_nc4_get_vara_double", as.integer(ncid), as.integer(varid), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... fixmiss, imvstate, as.double(passed_missval), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_get_vara_double returned error") if( verbose ) print('back from call to Rsx_nc4_get_vara_double...') data = rv$data } else if( (precint == 9) || (precint == 10) || (precint == 11)) { #--------------------------------------------- # uint, int64, uint64 # Thanks to Tom Hilinski of Colorado State for # fix to uint here #--------------------------------------------- rv$data <- double(totvarsize) fixmiss = as.integer(0) rv <- .Call("Rsx_nc4_get_vara_double", as.integer(ncid), as.integer(varid), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... fixmiss, as.integer(-1), # The 'imvstate' arg is unused in this call since no fixmiss as.double(0.0), # the passed missing value is not used in this call since no fixmiss PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_get_vara_double returned error") data = rv$data } else if( precint == 5 ) { #----- # Char #----- strndims <- ndims - 1 strlen <- count[1] + 1 strdim <- 1 if( strndims >= 1 ) { strdim <- count[2:ndims] nstr <- prod(strdim) } else nstr <- 1 if(verbose) print(paste("ndims:",ndims,"strndims:",strndims,"strlen:",strlen,"nstr:",nstr)) #---------------------------------------------- # Make a character string of the specified size #---------------------------------------------- stor <- blankstring_ncdf4( totvarsize ) stordata <- blankstring_ncdf4(strlen) if( verbose ) print(paste("length of stor string:",nchar(stor))) rv$tempstore <- stor rv$data <- array(stordata, dim=strdim) rv <- .C("R_nc4_get_vara_text", as.integer(ncid), as.integer(varid), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... tempstore=as.character(rv$tempstore), data=as.character(rv$data), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_get_var_text returned error") if( verbose ) print(paste("Orig dim of rv$data: ", paste0(dim(rv$data), collapse=' '), " now setting dim of string to strdim=", strdim )) dim(rv$data) <- strdim } else if( precint == 12 ) { #----------------------------- # netcdf version 4 String type #----------------------------- rv <- .Call( "R_nc4_get_vara_string", as.integer(ncid), as.integer(varid), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... PACKAGE="ncdf4" ) } else { stop(paste("Trying to get variable of an unhandled type code: ",precint, "(", ncvar_type_to_string(precint), ")")) } if( verbose ) { print(paste("ncvar_get_inner: C call returned",rv$error)) print(paste("ncvar_get_inner: dim of directly returned array:")) print(dim(rv$data)) } #-------------------------------------------------------- # Set our dims...but collapse degenerate dimensions first #-------------------------------------------------------- if( verbose ) print(paste("ncvar_get_inner: will collapse degen dims if ndims > 0. ndims=", ndims, ' collapse_degen=', collapse_degen, ' precint=', precint )) if( (ndims > 0) && (length(rv$data) > 0)) { if( collapse_degen ) { count.nodegen <- vector() foundone <- 0 for( i in 1:ndims ) if( count[i] > 1 ) { count.nodegen <- append(count.nodegen, count[i]) foundone <- 1 } if( foundone == 0 ) dim(rv$data) <- (1) else { if( verbose ) print(paste("count.nodegen:",count.nodegen," Length of data:",length(rv$data))) if( precint != 5 ) dim(rv$data) <- count.nodegen } } else if( precint != 5 ) dim(rv$data) = count if( verbose ) { print("ncvar_get: final dims of returned array:") print(dim(rv$data)) } } #---------------------------------------------------------- # Change missing values to "NA"s. Note that 'varid2Rindex' # is NOT filled out for dimvars, so skip this if a dimvar # 1=short, 2=int, 3=float, 4=double, 5=char, 6=byte # NOTE: if type is 3 or 4 (float or double), the missing # value was already set by the C routine. #---------------------------------------------------------- if( verbose ) print(paste("ncvar_get_inner: will now consider changing missing values to NA...")) if( (!raw_datavals) && (precint != 5) && (precint != 3) && (precint != 4) ) { # not char, float, or double if( verbose ) print("ncvar_get: setting missing values to NA") if( (precint==1) || (precint==2) || (precint==6) || (precint==7) || (precint==8) || (precint==9)) { #-------------------------------------- # Short, Int, Byte, UByte, UShort, UInt #-------------------------------------- if( verbose ) print(paste("ncvar_get_inner: setting ", tmp_typename[precint],"-type missing value of ", missval, " to NA", sep='')) if( ! is.na(missval) ) rv$data[rv$data==missval] <- NA } else if( (precint==10) || (precint==11)) { #-------------------------------- # 8-byte int, unsigned 8-byte int #-------------------------------- if( ! is.na(missval) ) { tol <- abs(missval*1.e-5) if( verbose ) print(paste("ncvar_get_inner: setting ", tmp_typename[precint],"-type missing value of ", missval, " (w/tolerance ", tol,") to NA", sep='')) rv$data[abs(rv$data-missval) 9)) stop("deflate_level must be between 0 and 9, inclusive") rv <- list() rv$root_id <- root_id rv$varid <- varid rv$shuffle <- shuffle rv$deflate <- deflate rv$deflate_level <- deflate_level rv$error <- -1 rv <- .C("R_nc4_def_var_deflate", as.integer(rv$root_id), as.integer(rv$varid), as.integer(rv$shuffle), as.integer(rv$deflate), as.integer(rv$deflate_level), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_def_var_deflate returned error") } #======================================================================================================= # Returns a list with: # $shuffle: ==1 if shuffle is turned on for this var, ==0 otherwise # $deflate: ==1 if deflate (compression) filter is turned on for this var, ==0 otherwise # $deflate_level: if $deflate==1, then this integer (0-9) indicates the deflate (compression) level # # Note that this routine must ONLY be called for variables in a NETCDF-4 format file! # ncvar_inq_deflate = function( root_id, varid ) { if( !is.numeric(root_id)) stop("must be passed a numeric root_id") if( !is.numeric(varid)) stop("must be passed a numeric varid") rv <- list() rv$root_id <- root_id rv$varid <- varid rv$shuffle <- 0 rv$deflate <- 0 rv$deflate_level <- 0 rv$error <- -1 rv <- .C("R_nc4_inq_var_deflate", as.integer(rv$root_id), as.integer(rv$varid), shuffle=as.integer(rv$shuffle), deflate=as.integer(rv$deflate), deflate_level=as.integer(rv$deflate_level), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_inq_var_deflate returned error") retval = list( shuffle=rv$shuffle, deflate=rv$deflate, deflate_level=rv$deflate_level ) return( retval ) } #======================================================================================================= # NOTE: on entry, length(chunksizes) MUST EQUAL ndims in the var. This routine assumes # this is true and will crash otherwise. So check this before calling this routine! # # 'chunksizes' array is in R order upon entry. In this routine we convert it to C order. # ncvar_def_chunking = function( root_id, varid, storage, chunksizes ) { if( !is.numeric(root_id)) stop("must be passed a numeric root_id") if( !is.numeric(varid)) stop("must be passed a numeric varid") if( !is.numeric(storage)) stop("must be passed a numeric storage") if( !is.numeric(chunksizes)) stop("must be passed a numeric chunksizes") chunksizes = as.integer(chunksizes) chunksizes = chunksizes[length(chunksizes):1] # Switch from R order to C order storage = as.integer(storage) if( (storage != 1) && (storage != 2)) stop("storage must be either 1 (for NC_CONTIGUOUS) or 2 (for NC_CHUNKED)") rv <- list() rv$root_id <- root_id rv$varid <- varid rv$ndims <- length(chunksizes) rv$storage <- storage rv$chunksizes <- chunksizes rv$error <- -1 rv <- .C("R_nc4_def_var_chunking", as.integer(rv$root_id), as.integer(rv$varid), as.integer(rv$ndims), as.integer(rv$storage), as.integer(rv$chunksizes), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_def_var_chunking returned error") } #======================================================================================================= # Returns a list with $storage and $chunksizes. # $storage is 1 for contiguous storage and 2 for chunked storage. # $chunksizes is an array of length ndims, in R order. # ncvar_inq_chunking = function( root_id, varid, ndims ) { if( !is.numeric(root_id)) stop("must be passed a numeric root_id") if( !is.numeric(varid)) stop("must be passed a numeric varid") if( !is.numeric(ndims)) stop("must be passed a numeric storage") chunksizes = array( as.integer(0), ndims ) rv <- list() rv$root_id <- root_id rv$varid <- varid rv$ndims <- ndims rv$storage <- 0 rv$chunksizes <- array(as.integer(0), ndims) rv$error <- -1 rv <- .C("R_nc4_inq_var_chunking", as.integer(rv$root_id), as.integer(rv$varid), as.integer(rv$ndims), storage=as.integer(rv$storage), chunksizes=as.integer(rv$chunksizes), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_inq_var_chunking returned error") #------------------------------------------------------------- # NOTE we switch chunksizes from C ordering to R ordering here # (i.e., we reverse it) #------------------------------------------------------------- retval = list( storage=rv$storage, chunksizes=rv$chunksizes[ndims:1] ) return( retval ) } ncdf4/R/ncdf4_priv_att.R0000644000176200001440000004137614377671533014535 0ustar liggesusers #=============================================================== # FOR INTERNAL USE ONLY. # ASSUMES nc and varid are simple C-style integers. # Set varid to -1 to get the global # of atts. # ncatt_get_n <- function( nc, varid ) { verbose = FALSE if( verbose ) print(paste("ncatt_get_n: entering with integer (ONLY) nc=", nc, "and integer (ONLY) varid=",varid)) if( ! is.numeric(nc)) stop(paste("error, first arg must be of class ncdf4!")) if( ! is.numeric(varid)) stop(paste("Error, second arg must be an integer!")) if( varid == -1 ) { if( verbose ) print ("ncatt_get_n: varid == -1, so getting number of global attributes") rv <- list() rv$ndims <- -1 rv$nvars <- -1 rv$natts <- -1 rv$error <- -1 rv <- .C("R_nc4_inq", as.integer(nc), ndims=as.integer(rv$ndims), nvars=as.integer(rv$nvars), natts=as.integer(rv$natts), ## REMOVE unlimdimid=as.integer(rv$unlimdimid), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("R_nc4_inq returned error on file",nc$filename,"!")) } else { if( verbose ) print ("ncatt_get_n: varid != -1, so getting number of attributes for a specific var") str.nc.max.name <- "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" rv <- list() rv$name <- str.nc.max.name rv$varlen <- -1 rv$error <- -1 rv$type <- -1 rv$ndims <- -1 rv$natts <- -1 rv$precint <- -1 rv$dimids <- integer(ncvar_ndims( nc, varid )) rv <- .C("R_nc4_inq_var", as.integer(nc), as.integer(varid), name=as.character(rv$name), type=as.integer(rv$type), ndims=as.integer(rv$ndims), dimids=as.integer(rv$dimids), natts=as.integer(rv$natts), precint=as.integer(rv$precint), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("R_nc4_inq_var returned error on file",nc$filename,"!")) } return( rv$natts ) } #====================================================================================================== # Args ncid and varid passed to this routine must be simple integers that can be directly # passed to the C API. I.e., 0-based counting, and a global attribute is flagged by -1. # NOTE: putting a global attribute is flagged by varid == -1 (NOT zero, since args passed to this # function must be the C API values, not the R values!) # ncatt_put_inner = function( ncid, varid, attname, attval, prec=NA, verbose=FALSE, definemode=FALSE ) { if( verbose ) print(paste('ncatt_put_inner: entering with ncid=', ncid, 'varid=', varid, 'attname=', attname, 'attval=', attval, 'prec=', prec, 'storage.mode(attval)=', storage.mode(attval) )) if( ! is.numeric(ncid)) stop("Can only be called with a simple C-style (0-based counting) integer ncid") if( ! is.numeric(varid)) stop("Can only be called with a simple C-style (0-based counting) integer varid") if( is.null(attval)) { print(paste("Warning: ncatt_put passed a NULL attribute; name=", attname )) return() } #------------------------------------------------------------- # Note there are TWO types here. One is the storage mode # of the passed attval. The netCDF routine to call is based # on this stoarge mode. The second type is the type of # attribute to create. This is passed as the 'prec' parameter # to this netcDF routine. If the passed prec is NA, then # the storage mode of the attval is used as the type of the # attribute to create. #------------------------------------------------------------- #------------------------------------------------------------- # Get the type of attribute to create. This follows the var's # type, in general, but can be manually overridden. #------------------------------------------------------------- atttypeShort <- 1 # These MUST match the values in the C code atttypeInt <- 2 atttypeFloat <- 3 atttypeDbl <- 4 atttypeText <- 5 atttypeByte <- 6 typetocreate <- -1 if( (length(prec)==1) && is.na(prec) ) { if( verbose ) print(paste("ncatt_put_inner: no user-specified att type was given, figuring it out...")) #--------------------------------------------------------------------------- # The logic of this code is as follows. In general, given no additional # information, it would be nice for the attribute to be the same type as # the original variable IF POSSIBLE. Now, if we are given a global # attribute, there is no "original variable", so we just take the precision # (type) of the attribute as it is. If there IS a variable, we would like # to make the att the same type if they are "compatible" types. For example, # if the var is an int and the passed att is 52.0, it would be nice to # store it as an int rather than as a float. This code attempts to # make that decision. In general, this only applies if we are trying to # cast near-integer floats or doubles to int in the case of an int var. #--------------------------------------------------------------------------- if( varid == -1 ) # A global attribute prec <- storage.mode(attval) else if( storage.mode(attval) == "character" ) { prec <- "character" # This always works, but MAY be inconvenient. However the user passed a char, so honor that request! } else { prec = storage.mode(attval) # our default choice #---------------------------------------------------------------- # Get the prec (type) of the VARIABLE this att is associated with #---------------------------------------------------------------- var_precint = ncvar_type( ncid, varid ) var_prec = ncvar_type_to_string( var_precint ) if( var_prec == "int" ) { att_is_int = (is.numeric(attval) && (floor(attval) == attval)) if( att_is_int ) prec = 'int' } } if( verbose ) print(paste("ncatt_put_inner: using deduced attribute prec of", prec)) } else if( verbose ) print(paste("ncatt_put_inner: using specified attribute prec of", prec)) if( verbose ) print(paste("ncatt_put_inner: prec to create:",prec)) if( (prec == "single") || (prec == "float")) typetocreate <- atttypeFloat else if( prec == "short" ) typetocreate <- atttypeShort else if( prec == "byte" ) typetocreate <- atttypeByte else if( prec == "double" ) typetocreate <- atttypeDbl else if( (prec == "integer" ) || (prec == "int")) typetocreate <- atttypeInt else if( (prec == "text") || (prec == "character") || (prec == "char")) typetocreate <- atttypeText else stop(paste("Error in ncatt_put: unknown prec type specified:",prec,". Known values: short integer float double character")) if( ! definemode ) nc_redef(ncid) #--------------------------------------------------------- # Get the netCDF function to call ... this always depends # exclusively on the storage mode of the attval #--------------------------------------------------------- rv <- list() rv$error <- -1 if( storage.mode(attval) == "integer" ) { rv <- .C("R_nc4_put_att_int", as.integer(ncid), as.integer(varid), as.character(attname), as.integer(typetocreate), as.integer(length(attval)), attval, error=as.integer(rv$error), PACKAGE="ncdf4", NAOK=TRUE ) if( rv$error != 0 ) { print(paste("Error in ncatt_put, while writing attribute", attname,"with value",attval)) stop(paste("Error return from C call R_nc4_put_att_int for attribute",attname)) } } else if( storage.mode(attval) == "double" ) { rv <- .C("R_nc4_put_att_double", as.integer(ncid), as.integer(varid), as.character(attname), as.integer(typetocreate), as.integer(length(attval)), attval, error=as.integer(rv$error), PACKAGE="ncdf4", NAOK=TRUE ) if( rv$error != 0 ) { print(paste("Error in ncatt_put, while writing attribute", attname,"with value",attval)) stop(paste("Error return from C call R_nc4_put_att_double for attribute",attname)) } } else if( storage.mode(attval) == "character") { if( verbose ) print(paste0("Calling R_nc4_put_att_text with name >", attname, "< att_len: ", as.integer(length(attval)), ' value: >', attval, '<' )) rv <- .C("R_nc4_put_att_text", as.integer(ncid), as.integer(varid), as.character(attname), as.integer(typetocreate), as.integer(length(attval)), attval, error=as.integer(rv$error), PACKAGE="ncdf4", NAOK=TRUE ) if( rv$error != 0 ) { print(paste("Error in ncatt_put, while writing attribute", attname,"with value",attval)) stop(paste("Error return from C call R_nc4_put_att_text for attribute",attname)) } } else if( storage.mode(attval) == "logical") { rv <- .C("R_nc4_put_att_logical", as.integer(ncid), as.integer(varid), as.character(attname), as.integer(typetocreate), as.integer(length(attval)), attval, error=as.integer(rv$error), PACKAGE="ncdf4", NAOK=TRUE ) if( rv$error != 0 ) { print(paste("Error in ncatt_put, while writing attribute", attname,"with value",attval)) stop(paste("Error return from C call R_nc4_put_att_logical for attribute",attname)) } } else stop(paste("ncatt_put: error, passed an attribute with a storage mode not handled. Att name:",attname,"Att value:",attval,"Storage mode passed:",storage.mode(attval),". Handled types: integer double character")) if( ! definemode ) { if( nc_enddef( ncid ) != 0 ) stop(paste("Error, nc_enddef returned an error!")) } } #=================================================================================================== # The difference between the "inner" version and the "regular" version is that the inner # version is passed only simple C-style integer ID's to operate on. # Inputs: # ncid, varid: C-style (0-based counting) integers. ncid must actually be a group # ID if appropriate. # # SPECIAL NOTE:: Ordinarily, the C interface uses a varid == -1 to indicate global attributes. # while the R code visible to the user indicates global attributes using a varid == 0. Since this # routine takes as its input the actual C-style numbers, the passed varid must equal -1 to access # global attributes. # ncatt_get_inner <- function( ncid, varid, attname=NA, verbose=FALSE ) { if( verbose ) print(paste("ncatt_get_inner: entering with ncid=", ncid, "varid=", varid, "attname=", attname )) if( ! is.numeric(ncid)) stop(paste("ncatt_get_inner must be passed a simple C-style (0-based counting) integer as the first argument (ncid)")) if( ! is.numeric(varid)) stop(paste("ncatt_get_inner must be passed a simple C-style (0-based counting) integer as the first argument (ncid)")) retval <- list() #--------------------------------------------------------------------------- # If no attname is specified, return a list with attribute name/value pairs #--------------------------------------------------------------------------- if( is.na(attname)) { if( verbose ) print(paste("ncatt_get_inner: no attname specified, returning a list with name/value pairs *******")) na <- ncatt_get_n( ncid, varid ) if( verbose ) print(paste("ncatt_get_inner: number of atts for this var [or file, if global]:", na)) if( na == 0 ) { if( verbose ) print(paste("ncatt_get_inner: no attributes for this var/file, returning empty list")) return( retval ) } if( verbose ) print(paste("ncatt_get_inner: Looping over",na,"attributes ******")) for( iatt in 0:(na-1) ) { # NOTE C-style 0-based counting here #--------------------- # Get attribute's name #--------------------- str.nc.max.name <- "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" rv0 <- list() rv0$error <- -1 rv0$attname <- str.nc.max.name rv0 <- .C("R_nc4_inq_attname", as.integer(ncid), as.integer(varid), as.integer(iatt), attname=as.character(rv0$attname), error=as.integer(rv0$error), PACKAGE="ncdf4") if( rv0$error != 0 ) { stop("error on call to R_nc4_inq_attname") } if( verbose ) print(paste("ncatt_get_inner: Attribute", iatt, "(in 0-based counting) has name \"", rv0$attname, "\"" )) #------------------------------------------------------------------------------- # Get attribute's value by recursively calling myself with the name now supplied #------------------------------------------------------------------------------- if( verbose ) print(paste("ncatt_get_inner: recursively calling myself to value for attribute \"", rv0$attname, "\"" )) tt <- ncatt_get_inner( ncid, varid, rv0$attname ) if( ! tt$hasatt ) stop(paste("internal error: could not get attribute value for att named ", rv0$attname )) retval[[rv0$attname]] <- tt$value } if( verbose ) print(paste("ncatt_get_inner: done, returning a list with name/value pairs *******")) return( retval ) } #---------------------------------------------------- # Find out if the attribute exists for this variable, # and, if so, what type and length it is. #---------------------------------------------------- rv0 <- list() rv0$error <- -1 rv0$attlen <- -1 rv0$type <- -1 if( verbose ) print("ncatt_get_inner: about to call R_nc4_inq_att") rv0 <- .C("R_nc4_inq_att", as.integer(ncid), as.integer(varid), as.character(attname), type=as.integer(rv0$type), # 1=short 2=int 3=float 4=double 5=text 6=byte 7=ubyte 8=ushort 9=uint 10=int64 11=uint64 12=string attlen=as.integer(rv0$attlen), error=as.integer(rv0$error), PACKAGE="ncdf4") if( verbose ) print(paste("ncatt_get_inner: R_nc4_inq_att returned with error=", rv0$error, "type=", rv0$type)) if( rv0$error != 0 ) { #--------------------------------------------------------- # This variable did NOT have an attribute named 'attname', # or it is of a type not handled. #--------------------------------------------------------- retval$hasatt <- FALSE retval$value <- 0 return(retval) } retval$hasatt <- TRUE rv <- list() rv$error <- -1 if ( rv0$type %in% c( 1, 2, 6, 7, 8 ) ) { #-------------------------------- # Short, Int, Byte, UByte, UShort #-------------------------------- rv$attribute <- rep(as.integer(0),rv0$attlen) if( verbose ) print(paste("ncatt_get_inner: calling R_nc4_get_att_int")) rv <- .C("R_nc4_get_att_int", as.integer(ncid), as.integer(varid), as.character(attname), attribute=as.integer(rv$attribute), error=as.integer(rv$error), PACKAGE="ncdf4") } else if ( rv0$type %in% c( 3, 4, 9, 10, 11 ) ) { if( (rv0$type == 10) || (rv0$type == 11)) { print(paste(">>>> WARNING <<< attribute", attname, "is an 8-byte value, but R")) print(paste("does not support this data type. I am returning a double precision")) print(paste("floating point, but you must be aware that this could lose precision!")) } #------------------------------------------------------ # Single, Double, 8-byte int, unsigned 8-byte int, UInt # Thanks to Tom Hilinski at Colorado State for fix to # uint in earlier versions. #------------------------------------------------------ rv$attribute <- rep(0.0,rv0$attlen) if( verbose ) print(paste("ncatt_get_inner: calling R_nc4_get_att_double")) rv <- .C("R_nc4_get_att_double", as.integer(ncid), as.integer(varid), as.character(attname), attribute=as.double(rv$attribute), error=as.integer(rv$error), PACKAGE="ncdf4") } else if( rv0$type == 5 ) { #------------------------------------------------- # "Text" ... note we allocate storage for it first #------------------------------------------------- rv$attribute <- blankstring_ncdf4( rv0$attlen ) if( verbose ) print(paste("ncatt_get_inner: calling R_nc4_get_att_text")) rv <- .C("R_nc4_get_att_text", as.integer(ncid), as.integer(varid), as.character(attname), attribute=as.character(rv$attribute), error=as.integer(rv$error), PACKAGE="ncdf4") } else if( rv0$type == 12 ) { #---------------------------------------------------- # "String" ... strings are very different from "text" # because the reported "attlen" will be the number # of strings, rather than the length of any string. #---------------------------------------------------- error = as.integer(0) if( verbose ) print(paste("ncatt_get_inner: calling R_nc4_get_att_string")) attribute <- .Call("R_nc4_get_att_string", as.integer(ncid), as.integer(varid), as.character(attname), as.integer(rv0$attlen), # number of strings to return error, PACKAGE="ncdf4") rv = list( error=error, attribute=attribute ) } else stop(paste("error, unhandled attribute type:", rv0$type)) if( verbose ) print(paste("ncatt_get_inner: return value from that call:", rv$error)) if( rv$error != 0 ) { #--------------------------------------------- # ? Got some strange error -- return as if the # attribute did not exist #--------------------------------------------- retval$hasatt <- FALSE retval$value <- 0 return(retval) } retval$value <- rv$attribute if( verbose ) print(paste("ncatt_get_inner: done for a single attribute, value= >",retval$value,"<")) return(retval) } ncdf4/R/ncdf4_priv_group.R0000644000176200001440000004641314377671533015076 0ustar liggesusers #=============================================================== # Given the integer root_id, returns the integer IDs of the # groups BELOW this node. It is entirely possible that the # return value will be an array of length 0, if there are no # nodes below this one. # nc_grpids <- function( root_id ) { if( ! is.integer(root_id)) root_id <- as.integer( root_id + 0.1 ) rv <- list() rv$root_id <- root_id rv$ngrps <- -1 rv$error <- -1 rv <- .C("R_nc4_inq_ngroups", as.integer(rv$root_id), ngrps=as.integer(rv$ngrps), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("Error in nc_grpids trying to get number of groups; C function R_nc4_inq_ngroups returned error")) ngrps <- rv$ngrps if( ngrps == 0 ) return() # if NO groups, return nothing #----------------------------------------------------- # Now that we have the number of groups, get their IDs #----------------------------------------------------- rv <- list() rv$root_id <- root_id rv$gids <- integer(ngrps) rv$error <- -1 rv <- .C("R_nc4_inq_groupids", as.integer(rv$root_id), gids=as.integer(rv$gids), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_inq_groupids returned error") return( rv$gids ) } #=============================================================== # Given the ID of a group, returns that group's name # nc_grpname <- function( root_id ) { if( ! is.integer(root_id)) root_id <- as.integer( root_id + 0.1 ) ierr <- as.integer(-1) rv <- .Call( "R_nc4_grpname", as.integer(root_id), ierr, PACKAGE="ncdf4" ) if( ierr != 0 ) { stop(paste("Error in nc_grpname, encountered when root_id=",root_id)) } return( rv ) } #=================================================================================================== # Fill out information for a group, given its id (which can be the ID of the root group, # of course!). Note that the fqgn of the ROOT group is just the empty string, "". # # This sets: # $name: group name, or "" for the root group. Example: "run1" # $fqgn: fully qualified group name, or "" for the root group. Example: "model1/run1" # $id: the group id (equal to the ncid for the root group) # $nvars: number of variables in this group # $ndims: number of dimensions in this group (note: vars can use dimensions # in this group OR ANY PARENT GROUP) # $dimid: Dimids of the dims that are visible to this group # $natts: number of attributes in this group # nc_get_grp_info <- function( gid, parent_fqgn, format ) { # sets $name, $fqgn, $id, $nvars, $ndims, $natts retval <- list( id=gid ) if( format == 'NC_FORMAT_NETCDF4' ) retval$name <- nc_grpname( gid ) else retval$name = "" #---------------------------------------- # Get standard stuff: ndims, nvars, natts #---------------------------------------- rv <- list() rv$ndims <- -1 rv$nvars <- -1 rv$natts <- -1 rv$error <- -1 rv <- .C("R_nc4_inq", as.integer(gid), ndims=as.integer(rv$ndims), nvars=as.integer(rv$nvars), natts=as.integer(rv$natts), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("nc_get_grp_info: R_nc4_inq returned error on group id", gid )) retval$ndims <- rv$ndims retval$nvars <- rv$nvars retval$natts <- rv$natts #---------------------------------------- # Get the dim IDs that this group uses. # In v4, it's no longer simply 0..ndims-1 #---------------------------------------- rv <- list() rv$group_dimids <- array( as.integer(-1), retval$ndims ) rv$error <- -1 rv <- .C("R_nc4_inq_dimids", as.integer(gid), group_dimids=rv$group_dimids, error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("nc_get_grp_info: R_nc4_inq_dimids returned error on group id", gid )) retval$dimid <- rv$group_dimids if( sum( is.na(retval$dimid) ) > 0 ) { print(paste("Error getting group info for group", retval$name,":")) print(paste("got some NA's as the dimids. There are ", retval$ndims, " dims in this group,")) print("and here are the IDs:") print(retval$dimid) stop("cannot have NA's as dimids!") } #-------------------------------------------------------- # Get the fully qualified group name (fqgn). This is "" # for the root group, something like "model1" for a # group one level down, for 2 levels "model1/run1", etc. #-------------------------------------------------------- if( retval$name == "/" ) { retval$name <- "" retval$fqgn <- "" } else { if( parent_fqgn == "" ) retval$fqgn <- retval$name else retval$fqgn <- paste( parent_fqgn, "/", retval$name, sep='' ) } class( retval ) <- "ncgroup4" return( retval ) } #=============================================================== # Given a "group" (list with components $name, $fqgn, and $id), this returns the group list # of all the groups BELOW this group. # Return val is a list (possibly of length 0!) with entries $name, $fqgn, $id, $nvars, $ndims, $natts # nc_groups_below <- function( root_group, format ) { #if( class(root_group) != "ncgroup4" ) if( ! inherits( root_group, "ncgroup4" )) stop(paste("error, nc_groups_below must be called with a ncgroup-class object")) root_id <- root_group$id retval <- list() nret <- 0 #----------------------------------- # Get IDs of groups below this group #----------------------------------- gids <- nc_grpids( root_id ) # returns array of integers (possibly length 0!) of IDs of groups BELOW this group n_below <- length( gids ) if( n_below == 0 ) return( retval ) # returns an empty list for( ib in 1:n_below ) { newgroup <- nc_get_grp_info( gids[ib], root_group$fqgn, format ) nret <- nret + 1 retval[[nret]] <- newgroup gg <- nc_groups_below( retval[[nret]], format ) nn <- length(gg) for( ii in nc4_loop(1,nn) ) { nret <- nret + 1 retval[[nret]] <- gg[[ii]] } } return( retval ) } #=============================================================== # This returns a list of unique groups. Each group has the following # elements: # $name (group name. Has NO slashes. Note: may be duplicated, since group names are not necessarily unique!) # $fqgn (fully qualified group name. Does NOT start or end with a slash. This is unique across a file. "names(list)" is also set to this, for convenience) # $fqpn (fully qualified parent group name. Does NOT end with a slash.) # $var[[]] (list of ncvar objects) # $dim[[]] (list of ncdim objects) # # The alg guarantees that the order of the groups in the returned # list goes from the root outward; i.e., by the time some group # is encountered on the list, it is guaranteed that all of that # group's ancestors will already have been encountered on the list. # nc_parse_group_structure <- function( vars, verbose=FALSE ) { debug <- verbose if( debug ) print('nc_parse_group_structure: entering') group <- list() root_grp <- list( name='', fqgn='', fqpn='', var=list(), dim=list() ) # Note: fqgn is a fully qualified group name, i.e., /group1/model1 etc. group[[1]] <- root_grp names(group)[1] <- '' # set 'names' array to fqgn #---------------------------------------------------------------------------------- # Go through each variable. See if it lives in a specified group. If it does NOT, # then add this var to the root group. If it DOES, then make sure that group is # on the group list, and add this var to that group. #---------------------------------------------------------------------------------- nv <- length(vars) for(iv in 1:nv) { vv <- vars[[iv]] if( debug ) print(paste('------------- nc_parse_group_structure: working on var', vv$name)) if( nslashes_ncdf4( vv$name ) == 0 ) { # look at FULLY QUALIFIED var name, which should have exacty zero leading forward slashes if at root group #--------------------------------------------------- # This var has no group, so put it in the root group #--------------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: var', vv$name, 'is in root group')) #---------------------------------------------------------------------- # Make sure there is not already a var with this name in the root group #---------------------------------------------------------------------- nv <- length(group[[1]]$var) for( iv in nc4_loop(1,nv) ) { if( vv$name == group[[1]]$var[[iv]]$name ) { stop(paste("Error, trying to add var named", vv$name, " to the root group, but there is already ", "a var named ", group[[1]]$var[[iv]]$name, "in the root group. Have you mistakenly added ", "the same var twice? Have you correctly specifed ", "the groups of any variables with duplicated names?", "Syntax for indicating group is a var named, for example, /groupname/varname")) } } group[[1]]$var[[nv+1]] <- vv } else { #--------------------------------------------------------------------------------------- # This var has a group, see if its group and parent groups are already on the group list # Many thanks to Georg Schnabel for contributing code that handles multiple levels of # groups in the following code. #--------------------------------------------------------------------------------------- my_fqgn <- nc4_basename( vv$name, dir=TRUE ) if( debug ) print(paste('nc_parse_group_structure: var', vv$name, 'is in group', my_fqgn)) my_grpnames <- unlist(strsplit(my_fqgn,"/",fixed=TRUE)) for (isubgrp in seq_along(my_grpnames)) { my_subgrp <- paste(my_grpnames[1:isubgrp],collapse="/") ng <- length(group) gidx <- -1 for( ig in 1:ng ) { if( my_subgrp == group[[ig]]$fqgn ) { gidx <- ig break } } if( gidx == -1 ) { #--------------------------------------------- # This group is not on the list yet, so add it #--------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: adding group', my_subgrp, ' to group list as a new entry')) ng <- length(group) my_fqpn <- nc4_basename(my_subgrp,dir=TRUE) group[[ng+1]] <- list( name=nc4_basename(my_subgrp), fqgn=my_subgrp, fqpn=my_fqpn, var=list(), dim=list() ) names(group)[ng+1] <- my_subgrp # set 'names' array to fqgn gidx <- ng+1 } } #------------------------------------------------- # Add the var to its associated group on the list #------------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: group', my_fqgn, ' is on the group list, so just adding var', vv$name,' to that group on the list')) #----------------------------------------------------------------- # Make sure there is not already a var with this name in the group #----------------------------------------------------------------- nv <- length( group[[gidx]]$var ) for( iv in nc4_loop(1,nv) ) { if( vv$name == group[[gidx]]$var[[iv]]$name ) { stop(paste("Error, trying to add var named", vv$name, " to group", group[[gidx]]$name, "but there is already ", "a var named ", group[[gidx]]$var[[iv]]$name, "in that group. Have you mistakenly added ", "the same var twice? Have you correctly specifed ", "the groups of any variables with duplicated names?")) } } group[[gidx]]$var[[nv+1]] <- vv } #------------------------------------------------------------ # Now go through this var's dims and see where they will live #------------------------------------------------------------ nd <- vv$ndims for( idim in nc4_loop(1,nd) ) { dd <- vv$dim[[idim]] if(debug) print(paste("working on var",vv$name,"'s dim",idim,"named",dd$name)) if( nslashes_ncdf4( dd$name ) == 0 ) { # look at FULLY QUALIFIED dim name, which should have exacty zero leading forward slashes if at root group #--------------------------------------------------- # This dim has no group, so put it in the root group #--------------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: dim', dd$name, 'has no specified group (and so is in root group)')) #------------------------------------------------------- # If there is already a dim with this name in the group, # make sure it's the SAME dim. #------------------------------------------------------- nd <- length(group[[1]]$dim) found_dim_already <- FALSE for( id in nc4_loop(1,nd) ) { if( dd$name == group[[1]]$dim[[id]]$name) { #----------------------------------------------- # HAVE seen this dim; ensure it's the same dim!! #----------------------------------------------- if(! ncdim_same( dd, group[[1]]$dim[[id]])) { stop(paste("Error, trying to add dim named", dd$name, " to the root group, but there is already ", "a dim named ", group[[1]]$dim[[id]]$name, "in the root group, with different length. Have you mistakenly resued ", "a dimension name for two different dims? Have you correctly specifed ", "the groups of any dims with duplicated names?")) } found_dim_already <- TRUE if( debug ) print(paste("dim",dd$name,"is already in root group dim list, entry number", id)) } } if( ! found_dim_already ) { #----------------------------------------------- # Only add this dim if it's not been seen before #----------------------------------------------- if( debug ) print(paste("adding dim",dd$name,"to root group dim list, entry number", nd+1)) group[[1]]$dim[[nd+1]] <- dd } } else { #-------------------------------------------------------------------- # This dim has a group, see if its group is already on the group list #-------------------------------------------------------------------- ng <- length(group) my_fqgn <- nc4_basename( dd$name, dir=TRUE ) if( debug ) print(paste('nc_parse_group_structure: dim', dd$name, 'is in fully qualified group', my_fqgn)) gidx <- -1 for( ig in 1:ng ) { if( my_fqgn == group[[ig]]$fqgn ) { gidx <- ig break } } if( gidx == -1 ) { #--------------------------------------------- # This group is not on the list yet, so add it #--------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: adding (dim) group', my_fqgn, ' to group list as a new entry')) ng <- length(group) my_fqpn <- nc4_basename(my_fqgn,dir=TRUE) group[[ng+1]] <- list( name=nc4_basename(my_fqgn), fqgn=my_fqgn, fqpn=my_fqpn, var=list(), dim=list(dd) ) names(group)[ng+1] <- my_fqgn # set 'names' array to fqgn } else { #------------------------------------------------- # This group is already on the list at index gidx; # add this dim to that list #------------------------------------------------- if( debug ) print(paste('nc_parse_group_structure: (dim"s) group', my_fqgn, ' is on the group list, so just adding dim', dd$name,' to that group on the list')) #--------------------------------------------------------------------------- # Make sure there is not already a different dim with this name in the group #--------------------------------------------------------------------------- nd <- length( group[[gidx]]$dim ) found_dim_already <- FALSE for( id in nc4_loop(1,nd) ) { if( dd$name == group[[gidx]]$dim[[id]]$name ) { if( ! ncdim_same( dd, group[[gidx]]$dim[[id]] )) stop(paste("Error, trying to add dim named", dd$name, " to group", group[[gidx]]$name, "but there is already ", "a dim named ", group[[gidx]]$dim[[id]]$name, "in that group. Have you mistakenly reused ", "the same dim name with different dims? Have you correctly specifed ", "the groups of any dims with duplicated names?")) found_dim_already <- TRUE } } if( ! found_dim_already ) { if( debug ) print(paste("adding dim",dd$name,"to group", group[[gidx]]$name, "dim list, entry number", nd+1)) group[[gidx]]$dim[[nd+1]] <- dd } } } } } #------------------------------------------------------------------------- # Now calculate the level (directory depth) of each group. The root group # is always at level 1. Any groups under the root group are at level # 2. Groups under that are level 3. Etc. # Note that this code assumes: # 1) root group is named "" # 2) the names of groups under the root group neither start nor # end with a slash. Examples: "model1", "model1/run1", etc. #------------------------------------------------------------------------- ng <- length( group ) maxlevel <- -1 for( ig in 1:ng ) { nam <- group[[ig]]$fqgn if( nam == "" ) # root group group[[ig]]$level <- 1 else group[[ig]]$level <- nslashes_ncdf4( nam ) + 1 if( group[[ig]]$level > maxlevel ) maxlevel <- group[[ig]]$level } #----------------------------------------------------------------------- # Rearrange the group list so that levels go from least to greatest #----------------------------------------------------------------------- tlist <- list() idx_out <- 0 for( ilev in 1:maxlevel ) { for( ii in 1:ng ) { if( group[[ii]]$level == ilev ) { idx_out <- idx_out + 1 tlist[[idx_out]] <- group[[ii]] } } } group <- tlist if( debug ) { print("----------- group list: ----------" ) ng <- length(group) for( ig in 1:ng ) { print(paste("Group ", ig, ", named ", group[[ig]]$fqgn, ", is at level ", group[[ig]]$level, " and has full qual parent named ", group[[ig]]$fqpn, ":", sep='' )) nd <- length( group[[ig]]$dim ) for( id in nc4_loop(1,nd) ) print(paste( ".... dim ", id, ": ", group[[ig]]$dim[[id]]$name, ' (length=', group[[ig]]$dim[[id]]$len, ')', sep='' )) nv <- length( group[[ig]]$var ) for( iv in nc4_loop(1,nv) ) print(paste( ".... var ", iv, ": ", group[[ig]]$var[[iv]]$name, sep='' )) } } return( group ) } #=================================================================== # Inputs: # parentid: simple integer ID of parent of the group to be created # group_name: name of the group to be created # # Return value: # simple integer group ID of the new group # # Routine halts on error # nc_make_group_inner <- function( parentid, group_name ) { if( ! is.numeric(parentid)) stop(paste("Error, first input (parentid) must be a simple integer")) if( ! is.character(group_name)) stop(paste("Error, second input (group_name) must be a character string")) newgroup <- list( gid=-1, error=-1 ) newgroup <-.C("R_nc4_def_grp", as.integer(parentid), as.character(group_name), gid=as.integer(newgroup$gid), error=as.integer(newgroup$error), PACKAGE="ncdf4") if( newgroup$error != 0 ) stop(paste("Error in R_nc4_def_grp trying to make group named", group_name)) return( newgroup$gid ) } #=================================================================== # Inputs: # ss : string. Possibly the fully qualified group name (fqgn) # of a group in a netcdf file # ncid : the ncdf4 object for a netcdf file # # Return value: # the INDEX in the ncid$group[[]] list if ss IS a FQGN # in file ncid, and # -1 otherwise. # nc_is_a_fqgn <- function( ss, ncid ) { if( storage.mode(ss) != 'character') return(-1) ng = length( ncid$group ) if( ng < 1 ) return( -1 ) # no groups in file, so ss cannot be the FQGN of a group in the file for( ig in 1:ng ) { if( ss == ncid$group[[ig]]$fqgn ) return( ig ) } return( -1 ) } ncdf4/R/ncdf4.R0000644000176200001440000031711014531205606012577 0ustar liggesusers# This provides an interface to netCDF-4 functions. As a general # comment, awkwardness arises from two things: # 1. R starts counting at 1, and netCDF counting # starts at 0. # 2. R array subscripts go in Fortran order (XYZT), # while netCDF subscripts go in C order (TZYX). # We take care of these problems EXCLUSIVELY in the R code, # NOT in the C interface code!!! This means that it is # always the responsibility of the R program to take these # differences into account. From the point of view of an # R program that calls any of these functions, they are # strictly R compliant (Fortran order, counting starts at 1). # # David W. Pierce # Climate Research Division # Scripps Institution of Oceanography # dpierce@ucsd.edu # 15-January-2010 # #----------------------------------------------------------------- # Netcdf-version 4 notes. # Not much needs to be changed in the interface to make it work # for netcdf version 4. Basically, if you have a slash in the # variable or dim name, such as "models/Temperature", then "models" # is a group that will be auto-created as necessary. Same goes # for dims. NOTE that this is fundamentally a different way # of doing things than the raw netcdf C interface does. The # C interface uses DIFFERENT ncid's, corresponding to each group. # THIS interface always uses the ncdf object, but the name of # the dim or var must be fully qualified if there is an # ambiguity about which one it refers to. # # Once change I did make was that becuase ID's are now more of # an abstract concept, and ID numbering can be arbitrary, the # USER interface will ONLY take the netcdf objects, not integers. # For example, varid's used to be numbered, in C convention, # from 0 to N-1. Now they can be arbitrary. As a result, # all the "ids" stored in the ncdf object are the actual C # values themselves. We no longer need to, or try to, adjust # between "R" values and "C" values. # # varid's have been changed to reflect this. Now, varids are # an object of type 'ncid'. That object holds the "raw" varid, # plus the netcdf group id needed to access the variable. # # dimid's, on the other hand, are still simple integers. This # seems to be a characteristic of netcdf files, possibly because # dims can be seen if they exist in the group OR ANY PARENT GROUP. # Obviously enforcing that would be a headache, which is made # easier if you simply have dims numbered sequentially across # the whole file (as opposed to vars, which are numbered # sequentially, starting at 0, in EACH GROUP). # # In netcdf-4, there can be multiple unlimited dims. In order to # avoid breaking existing code, nc$unlimdimid is set to the FIRST # unlimited dim in the file. Technically, unlimdimid is not set # to an ID, it's set to an index into the global nc$dim[[]] list. #----------------------------------------------------------------- # # Here are the relevant objects: # # class: ncdf4 is a list with the following fields: # filename: name of the file, or "IN-MEMORY" # id : netcdf file id # ndims : integer # of dims in the file # nvars : integer # of vars in the file that are **NOT** dimvars # natts : integer # of global attributes # group : list of groups in the file. group[[1]] is always the root group # ngroups : integer # of groups; will always be at least 1, indicating the root group; # this is just length(group) # dim : a list of ncdim objects # var : a list of ncvar objects # writable: TRUE or FALSE # is_GMT : TRUE if is a "GMT-style" netcdf file, FALSE otherwise # safemode : TRUE if safe mode is on, in which case files will only # be opened before they are used, and will be closed # immediately afterwards. This is currently needed for the # Windows-64 port. # # class: ncdim4 (returned by ncdim_def, which creates a NEW # netCDF dimension in memory, and part of the list of dims # in a ncdf object. NOTE that this is NOT what is returned # by ncdim_inq, which is the low-level netCDF dim, not # the user-level R version of a netCDF dim. # * name : character dim name # units : character units in udunits format. # vals : a vector of dimension values # * len : size of this dimension # calendar : if the dimvar has a 'calendar' attribute, this holds its value # id : NEW IN VERION 4: this is an opaque object of type 'ncdimid' # dimvarid: IFF this dim corresponds to a netCDF dim in an existing file, # then this field will hold the dimvarid, or -1 if no dimvar. # * unlim : boolean, T or F to indicated unlimited or not # create_dimvar : usually TRUE; if FALSE, then no dimvar will be created, # AND the units string must be empty, AND the values must # be simple integers from 1 to the length of the dim. # longname : the 'long_name' attribute for the DIMVAR, or defaults to # name if there is no dimvar, OR the long_name attribute # is not set. # # *=Indicates element is filled out by the low-level routine 'ncdim_inq'. # Other elements are filled out in 'open.ncdf'. # # # class: ncvar4 (returned by ncvar_def, which creates a NEW # netCDF variable in memory, and part of the list of vars # in a ncdf object. NOTE that this is NOT what is # returned by ncvar_inq, which is the low-level netCDF # var, NOT the user-level R version of a netCDF var. # name : character var name # units : character units in udunits format # missval : the 'missing_value' attribute, or defaults to default_missval_ncdf4(). NOTE: # if the var has no missing value then this is 'NA'. This does not mean # that the missing value is NA -- the missing value cannot be NA. It means # the variable has no missing value. For instance, character variables have # no default missing value. # longname: the 'long_name' attribute, or defaults to name # id : the varid of this variable, IFF it is in a file already # ndims : number of dims this variable has # dim : a list of type ncdim, which is this variable's dims # unlim : boolean, T if this var has an unlimited dim, F otherwise # varsize : a convenience array that gives the (X,Y,Z,T) size of # the variable. # prec : The precision of the ON-DISK representation of the # variable. Can be "byte", "short", "float", "double", # "integer", or "char". # natts : integer # of this variable's attributes # #====================================================================================================== nc_version <- function() { ncdf_lib_vers <- .Call("R_nc4_inq_libvers", PACKAGE="ncdf4") return(paste("ncdf4_1.22_20231127 | underlying netcdf library version", ncdf_lib_vers )) } #==================================================================================================== # This is the public interface for making a netCDF dimension # class. It makes it in memory, not in a file! Returns a # "ncdim" object. The dimvar will have the same precision # as the passed values. Therefore, it will always have double # precision unless the vals are passed like this: as.integer(vals), # in which case they will be integer. # # Example useage: # lon <- ncdim_def("Lon", "degreesE", 0:359) # lat <- ncdim_def("Lat", "degreesN", -90:90) # time <- ncdim_def("time", "days since 1900-01-01", 0, unlim=T) # # Netcdf-4 useage: # lon <- ncdim_def( "models/pcm/Lon", ... ) # where groups are indicated by things before the slashes. # # NOTE that fully qualified dim names NEVER start with a slash! This # is required for backward compatability with old code. # ncdim_def <- function( name, units, vals, unlim=FALSE, create_dimvar=TRUE, calendar=NA, longname=name ) { #--------------- # Validate input #--------------- if( (! is.character(name)) || (nchar(name) < 1)) stop("Passed a dim name that is NOT a string of characters!") if( ! is.character(units) ) stop("Passed a dim units that is NOT a string of characters!") if( ! is.numeric(vals)) stop("Only numeric dimension values are supported") if( ! is.na(calendar)) { if( (! is.character(calendar)) || (nchar(calendar)<1)) stop("Passed a calendar that is NOT a string of characters!") } if( substr(name,1,1) == '/' ) stop(paste("Error: passed dim name", name, "starts with a slash. Fully qualified dim names can NEVER start with a slash (this is required for backwards compatability). Leave off any leading slash!")) len <- length(vals) if( ! create_dimvar ) { if( (units != '') || (storage.mode(vals) != "integer" ) || (vals[1] != 1) || (vals[len] != len)) stop(paste("Error trying to create dimension named",name,": create_dimvar was specified", "to be FALSE, which indicates that NO dimensional variable is to be created;", "in this case, the unit string MUST be empty ('') and the dimension values MUST", "be simple integers from 1 to the length of the dimension (e.g., 1:len)", 'So, in summary, this units string must be blank: "', units, '" ', "This storage mode of the vals must be integer:", storage.mode(vals) , "This first value of the dim vals must be 1:", vals[1], "This last value of the dim vals must be the length:", vals[len] )) } dim <- list() dim$name <- name # Note this is a fully qualified dim name and NEVER starts with a slash dim$longname <- longname dim$units <- units dim$vals <- vals dim$len <- len #--------------------------------------------------------------------------- # In netcdf v4, there can be multiple vars with the same name and same ID, # if they are in different groups. So we have to have a more complex object # for the dimvar ID than just a simple integer. This does not seem to be # true for dims, which still appear to have unique ID's across all groups # in the file. # # Elements of the dimvar's 'ncid' object: # id: the integer to use to access this dim when calling the # C routines to access the dim WITH THE CORRECT GROUP ID # group_id: the group ID to use when accessing the C routines to # manipulate this dim # group_index: the index in to the nc$group list for the group where # this dim lives # list_index: index into the global nc$var[[]] list for this var. # NOTE that dimvars are not on this list. # isdimvar: is TRUE if the var is a dimvar, FALSE otherwise. # Note that none of these is valid until the dim is actually created on disk #--------------------------------------------------------------------------- dim$id <- -1 dim$dimvarid <- ncdf4_make_id( isdimvar=TRUE ) # make an EMPTY ncid object dim$unlim <- unlim if( !is.na(calendar)) { if( ! create_dimvar ) { print(paste("Error in ncdim_def while trying to define dimension",name,":")) print(paste("This dimension was specified to have a calendar (",calendar,") BUT")) print(paste("also it was specified that no dimvar would be created, via create_dimvar=FALSE!")) print(paste("This is a contradiction since the calendar attribute must be stored")) print(paste("on the dimvar. Either get rid of the calendar, or allow a dimvar")) print(paste("to be created.")) stop("Halting.") } dim$calendar <- calendar } dim$create_dimvar <- create_dimvar attr(dim,"class") <- "ncdim4" return(dim) } #==================================================================================================== # Produce a more useful listing of the netcdf file than # just a dump of the object. # print.ncdf4 <- function( x, ... ) { nc <- x is_netcdf_v4 = ((nc$format == 'NC_FORMAT_NETCDF4') || (nc$format == 'NC_FORMAT_NETCDF4_CLASSIC' )) is_GMT = ifelse( nc$is_GMT, ' (GMT format)', '' ) is_safemode = ifelse( nc$safemode, ' (SAFE MODE ON)', '' ) cat(paste0("File ", nc$filename, " (", nc$format, ")", is_GMT, is_safemode, ":\n\n")) cat(" ", nc$nvars, "variables (excluding dimension variables):\n") if( nc$nvars > 0 ) { for( i in 1:nc$nvars ) { nd <- nc$var[[i]]$ndims dimstring <- '[' if( nd > 0 ) { for( j in 1:nd ) { dimstring <- paste(dimstring,nc$var[[i]]$dim[[j]]$name,sep='') if( j < nd ) dimstring <- paste(dimstring,',',sep='') } } dimstring <- paste(dimstring,'] ',sep='') chunk_tag = '' compress_tag = '' if( is_netcdf_v4 ) { #---------------------------- # Handle chunking information #---------------------------- if( is.null(nc$var[[i]]$storage) || nc$var[[i]]$storage == 1 ) chunk_tag = " (Contiguous storage)" else { chunk_tag = " (Chunking: [" for( j in 1:nd ) { chunk_tag = paste( chunk_tag, nc$var[[i]]$chunksizes[j], sep='' ) if( j < nd ) chunk_tag = paste( chunk_tag, ",", sep='' ) } chunk_tag = paste( chunk_tag, "])", sep='' ) } #--------------------------------------- # Handle shuffle/compression information #--------------------------------------- is_shuffle = (nc$var[[i]]$shuffle == 1) is_compress = (!is.na(nc$var[[i]]$compression)) if( (!is_shuffle) && (!is_compress)) compress_tag = "" else if( is_shuffle && (!is_compress)) compress_tag = "(Compression: shuffle)" else if( (!is_shuffle) && is_compress ) compress_tag = paste("(Compression: level ", nc$var[[i]]$compression, ")", sep='' ) else compress_tag = paste("(Compression: shuffle,level ", nc$var[[i]]$compression, ")", sep='' ) } cat(paste0(" ", nc$var[[i]]$prec, ' ', nc$var[[i]]$name, dimstring, chunk_tag, " ", compress_tag, '\n' )) atts <- ncatt_get( nc, nc$var[[i]]$name ) natts <- length(atts) if( natts > 0 ) { nms <- names( atts ) for( ia in 1:natts ) cat(paste0(" ", nms[ia], ": ", atts[[ia]], '\n' )) } } } cat("\n ",nc$ndims,"dimensions:\n") if( nc$ndims > 0 ) for( i in 1:nc$ndims ) { has_dimvar = ( nc$dim[[i]]$dimvarid$id != -1 ) tag <- '' if( nc$dim[[i]]$unlim ) tag <- ' *** is unlimited ***' tag2 = '' if( ! has_dimvar ) tag2 = '(no dimvar)' cat(paste0(" ", nc$dim[[i]]$name, " Size:", nc$dim[[i]]$len, tag, ' ', tag2, '\n' )) #---------------- # Get dimvar atts #---------------- if( has_dimvar ) { atts <- ncatt_get( nc, nc$dim[[i]]$name ) natts <- length(atts) if( natts > 0 ) { nms <- names( atts ) for( ia in 1:natts ) cat(paste0(" ", nms[ia], ": ", atts[[ia]], '\n' )) } } } #-------------------------- # Now get global attributes #-------------------------- atts <- ncatt_get( nc, 0 ) natts <- length(atts) if( natts > 0 ) { cat(paste0('\n ', natts, ' global attributes:\n')) nms <- names( atts ) for( ia in 1:natts ) cat(paste0(" ", nms[ia], ": ", atts[[ia]], '\n' )) } } #========================================================================================================== # This is the public interface for making a netCDF variable # class. It makes it in memory, not in a file! Returns # a "ncvar" object. # # Example useage, where "lon" and "lat" are objects of class "ncdim": # # ncvar <- ncvar_def( "temp", "degC", list(lon,lat), 1.e30, "Temperature" ) # or # ncvar <- ncvar_def( "temp", "degC", lon, 1.e30, "Temperature" ) # # Example useage for netcdf library version 4: # # ncvar <- ncvar_def( "models/pcm/Temperature", ... ) # # NOTE that the passed dimentions (in this example, "lon" and "lat" # should have been made by "ncdim_def", and so are of class # "ncdim". Argument "prec" will indicate what precision the variable # is made on the disk. Allowed values are "short", "integer", "float", # "double", "byte", and "char". # 'missval' is the value to be assigned to the 'missing_value' attribute # for the variable. It should be a number representable in the precision-type # of the variable. So, for example, for single precision, a floating point # number with magnitude less than 1.e36 should be used. As a special value, # if missval is set to NA, then *no* missing value will be created for the # variable. # # To make a var with no dims, pass an empty list: "list()" ncvar_def <- function( name, units, dim, missval=NULL, longname=name, prec="float", shuffle=FALSE, compression=NA, chunksizes=NA, verbose=FALSE ) { if( verbose ) print('ncvar_def: entering') #----------------------------------- # Check inputs for reasonable values #----------------------------------- if( (! is.character(name)) || (nchar(name) < 1)) stop("Passed a var name that is NOT a string of characters!") if( ! is.character(units)) # Note: an empty string is OK stop("Passed a var units that is NOT a string of characters!") if( (! is.character(prec)) || (nchar(prec) < 1)) stop("Passed a var precision (prec) that is NOT a string of characters!") if( prec == 'single' ) prec = 'float' # Not sure if this is really needed or not. It breaks package efts ... maybe having # this check is too restrictive. # DWP 2021/11/25 #if( (prec == 'char') && (nchar(missval) == 0)) # stop(paste("Error, when defining a character variable, the supplied missing value cannot be zero length! Error occurred when trying to define variable", name )) if( verbose ) print(paste('ncvar_def: prec=', prec)) if( !is.na(compression)) { if(!is.numeric(compression)) stop("Compression parameter, if supplied, must be an integer between 1 (least compression) and 9 (most compression)") compression = as.integer(compression) if((compression < 1) || (compression > 9)) stop("Compression parameter, if supplied, must be an integer between 1 (least compression) and 9 (most compression)") } if( (length(chunksizes)>1) || (!is.na(chunksizes))) { if( (! is.numeric(chunksizes)) || (length(chunksizes) != length(dim))) stop("Chunksizes parameter, if supplied, must be a vector of integers with length equal to the dimension of the variable") } if( shuffle ) { if( (prec == "float") || (prec == "double") || (prec == "single") ) print(paste("Warning: shuffle is turned on for variable", name, "but that var is of precision", prec, "and shuffle ONLY has an effect for integer variables.")) if( is.na(compression)) print(paste("Warning: shuffle is turned on for variable", name, "but compression is NOT turned on. Quoting from the netCDF docs: 'There is no benefit from using the shuffle filter without also using compression.'")) } if( substr(name,1,1) == '/' ) stop(paste("Error: passed var name", name, "starts with a slash. Fully qualified var names can NEVER start with a slash (this is required for backwards compatability). Leave off any leading slash!")) #---------------------- # Make our ncvar object #---------------------- if( verbose ) print(paste('ncvar_def: making ncvar object for var', name )) var <- list() var$name <- name # Note this is a fully qualifed var name and never starts with a slash var$units <- units var$longname <- longname var$shuffle <- shuffle var$compression <- compression var$chunksizes <- chunksizes # a vector of integers; the length of the vector == ndims #---------------------------------------------------------------------------------- # New: in 1.1, you can specify NOT to have a missing value by NOT passing a missing # value argument at all. Also, you can now specify a missing value of NA by passing # a NA. #---------------------------------------------------------------------------------- zero_len_char = FALSE if (prec == 'char') { if( is.null( missval )) zero_len_char = TRUE else if( is.na( missval )) zero_len_char = TRUE else if( nchar(missval) == 0 ) zero_len_char = TRUE } if( missing(missval) || is.null(missval) || zero_len_char ) var$make_missing_value = FALSE else { var$make_missing_value = TRUE var$missval <- missval if( storage.mode(missval) == "character" ) prec <- 'char' } #--------------------------------------------------------------------------- # In netcdf v4, there can be multiple vars with the same name and same ID, # if they are in different groups. So we have to have a more complex object # for the "ID" than just a simple integer. # Elements: # id: the integer to use routines to access this vars when calling the # C routines to access the dim WITH THE CORRECT GROUP ID # group_id: the group ID to use when accessing the C routines to # manipulate this vars # group_index: the index in to the nc$group list for the group where # this vars lives # list_index: index into the glocal nc$var[[]] list that corresponds # to this var # isdimvar: TRUE if this is a dimvar, FALSE otherwise # Note that none of these is valid until the vars is actually created on disk #--------------------------------------------------------------------------- var$id <- ncdf4_make_id() # make an EMPTY ncid object attr(var,"class") <- "ncvar4" if( (prec != "short") && (prec != "float") && (prec != "double") && (prec != "integer") && (prec != "char") && (prec != "byte")) stop(paste("ncvar_def: error: unknown precision specified:",prec,". Known values: short float double integer char byte")) var$prec <- prec #----------------------------------------------------- # Have to figure out if 'dim' is a ncdim object or # a LIST of ncdim objects. #----------------------------------------------------- if( inherits( dim, 'ncdim4' )) dim <- list(dim) var$dim <- dim var$ndims <- length(var$dim) if( var$ndims > 0 ) { for( i in 1:var$ndims ) { if( ! inherits( var$dim[[i]], "ncdim4" )) { print(paste("Error, passed variable has a dim that is NOT of class ncdim4!")) print(paste("Error occurred when processing dim number",i,"of variable",var$name)) stop(paste("This dim has class:", class(var$dim[[i]]))) } } } #------------------------------------------------- # A variable is unlimited if any of its dimensions # is unlimited #------------------------------------------------- varunlimited <- FALSE if( var$ndims != 0 ) { for( i in 1:var$ndims ) { if( var$dim[[i]]$unlim ) varunlimited <- TRUE if( i == 1 ) var$varsize = var$dim[[i]]$len else var$varsize = append( var$varsize, var$dim[[i]]$len ) } } var$unlim <- varunlimited return(var) } #=============================================================================================== # This is the public interface for opening an already-existing # netCDF file. If you want to create a NEW netCDF file, use # nc_create instead. This returns an object of class 'ncdf', # used to access netCDF functions. If you want to modify an # already-existing netCDF file, use this function and set write=TRUE. # By default, this will read in the values of the unlimited dimension(s) # along with the values of all the other dimensions. Since this # can be time comsuming, there is the option of setting 'readunlim' # to 'FALSE', which will avoid this behavor. Then you must read # in the values yourself with a 'ncvar_get' call, instead of # accessing the ncid$dim[[DIMNAME]]$vals array. # # If 'safemode' is set, then safemode will be set to whatever # the supplied value of safemode is. # If 'safemode' is NOT set, then safemode will be OFF unless # we are on the Windows-64 platform, in which case it will be ON. # # If return_on_error is FALSE, this routine halts with an error # message if an error is encountered. If no error is encountered, # rv$error is set to FALSE. If return_on_error is TRUE, this routine # always returns, and rv$error is set to TRUE if there was an # error, and FALSE if there was no error. # nc_open <- function( filename, write=FALSE, readunlim=TRUE, verbose=FALSE, auto_GMT=TRUE, suppress_dimvals=FALSE, return_on_error=FALSE) { safemode = FALSE if( verbose ) print(paste("nc_open: entering, ncdf4 package version", nc_version() )) if( (! is.character(filename)) || (nchar(filename) < 1)) stop("Passed a filename that is NOT a string of characters!") rv <- list() if( write ) rv$cmode <- 1 else rv$cmode <- 0 rv$id <- -1 rv$error <- -1 rv <- .C("R_nc4_open", as.character(filename), as.integer(rv$cmode), # write mode=1, read only=0 id=as.integer(rv$id), # note: nc$id is the simple integer ncid of the base file (root group in the file) error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) { if( return_on_error ) { print(paste("Error in nc_open trying to open file",filename, '(setting rv$error TRUE and returning because return_on_error==TRUE)' )) rv$error = TRUE return( rv ) # Note this is not a full ncdf4 type object, just a little stub with error == TRUE } else stop(paste("Error in nc_open trying to open file",filename, '(return_on_error=', return_on_error, ')')) } rv$error = FALSE if( verbose ) print(paste("nc_open: back from call to R_nc4_open, ncid=",rv$id)) #------------------------------------------------- # Now we make our elaborate ncdf class object #------------------------------------------------- nc <- list( filename=filename, writable=write, id=rv$id, error=rv$error ) attr(nc,"class") <- "ncdf4" #--------------------------------------------------------- # This must be ON for Windows-7 64-bit, off for everything # else (as of Feb 2014) #--------------------------------------------------------- am_windows = (length(grep( 'windows', .Platform$OS.type, ignore.case=TRUE)) != 0) am_64 = (length(grep( 'x64', .Platform$r_arch, ignore.case=TRUE)) != 0) # nc$safemode <- (am_windows && am_64) # Buggy at the moment?? DWP 6 June 2014 nc$safemode = FALSE if( nc$safemode && (!is.na(safemode)) && (safemode == FALSE) ) { print(paste("***************** W A R N I N G *****************************")) print(paste("You are running on Windows-64 but have specified to force the")) print(paste("safemode OFF. Safemode protects from KNOWN BUGS of the netcdf")) print(paste("library on Windows-64. If you force safemode off YOU MUST NEVER")) print(paste("HAVE MORE THAN ONE NETCDF FILE OPEN AT THE SAME TIME, or you")) print(paste("may get errors of the type that the ncdf4 operators access the")) print(paste("WRONG FILE. You are proceeding at your own risk!!")) print(paste("***************************************************************")) } if( !is.na(safemode)) nc$safemode = safemode #------------------------------------------------------------- # See what format this file is. Possible (string) values are: # 'NC_FORMAT_CLASSIC', 'NC_FORMAT_64BIT', 'NC_FORMAT_NETCDF4', # and 'NC_FORMAT_NETCDF4_CLASSIC' #------------------------------------------------------------- nc$format = ncdf4_format( nc$id ) if( verbose ) print(paste("file", filename, "is format", nc$format )) #------------------------------------------------------------------------ # See if this is a GMT-style netcdf file. Distinguishing characteristics: # * has a dimension named "xysize" # * has a dimension named "side" with val of 2 # * Has a variable named dimension with dim of size # * Has a variable named spacing with dim of size # * Has a variable named z with dim of xysize #------------------------------------------------------------------------ nc$is_GMT = FALSE if( auto_GMT) { dimlen_xysize = ncdim_len( nc$id, 'xysize' ) dimlen_side = ncdim_len( nc$id, 'side' ) varid_dimension = ncvar_id( nc$id, 'dimension' ) varid_spacing = ncvar_id( nc$id, 'spacing' ) varid_z = ncvar_id( nc$id, 'z' ) if( (dimlen_xysize != -1 ) && (dimlen_side != -1 ) && (varid_dimension != -1 ) && (varid_spacing != -1 ) && (varid_z != -1 )) { #-------------------------------------- # Good so far ... see if sizes match up #-------------------------------------- varsize_dimension = ncvar_size( nc$id, varid_dimension ) if( (length(varsize_dimension) == 1) && (varsize_dimension[1] == dimlen_side) ) { varsize_spacing = ncvar_size( nc$id, varid_spacing ) if( (length(varsize_dimension) == 1) && (varsize_dimension[1] == dimlen_side) ) { varsize_z = ncvar_size( nc$id, varid_z ) if( (length(varsize_z) == 1) && (varsize_z[1] == dimlen_xysize) ) { #print('** nc_open: File automatically detected to be in GMT format (set auto_GMT=FALSE to disable) **') nc$is_GMT = TRUE # Note: functionality not used yet } } } } } #----------------------------------------------------- # Get all the groups in the file. Later we have to # remember that dims and vars can live in groups other # than the root group. #----------------------------------------------------- groups <- list() groups[[1]] <- nc_get_grp_info( nc$id, "", nc$format ) # sets $name, $fqgn, $id, $nvars, $ndims, $natts, $ngrps, etc if( nc$format == 'NC_FORMAT_NETCDF4' ) { gg <- nc_groups_below( groups[[1]], nc$format ) for( i in nc4_loop(1,length(gg))) groups[[1+i]] <- gg[[i]] } nc$groups <- groups #--------------------------- # Print groups for debugging #--------------------------- #for( ig in 1:length( nc$groups )) { # print(paste( ig, groups[[ig]]$id, ' : ', groups[[ig]]$name, ' ', groups[[ig]]$fqgn )) # } #-------------------------------------------------------------------------------------- # Construct mapping between fully qualified group name and R index into the groups list #-------------------------------------------------------------------------------------- nc$fqgn2Rindex <- list() # given fqgn, gives R index into nc$group list for( i in 1:length(groups)) nc$fqgn2Rindex[[ groups[[i]]$fqgn ]] = i if( verbose ) { print("Group info:") for( ig in 1:length(groups)) { print(paste("Group", ig, ": ", "name=", groups[[ig]]$name, "id=", groups[[ig]]$id, 'fqgn= "', groups[[ig]]$fqgn, '"', "nvars=", groups[[ig]]$nvars, "ndims=", groups[[ig]]$ndims, "dimid=")) print( groups[[ig]]$dimid ) } } #--------------------------------------------------------------------------- # Get general information about the file. ndims and natts is the sum across # all groups in the file. nvars is set below to only include non-dimvars, # but otherwise is also the sum across all groups. #--------------------------------------------------------------------------- nc$ndims <- 0 nc$natts <- 0 tot_nvars_inc_dimvars <- 0 # total number of vars INCLUDING dimvars; regular nc$nvars excludes dimvars for( ig in 1:length(groups)) { nc$ndims <- nc$ndims + nc$groups[[ig]]$ndims nc$natts <- nc$natts + nc$groups[[ig]]$natts tot_nvars_inc_dimvars <- tot_nvars_inc_dimvars + nc$groups[[ig]]$nvars } #-------------------------------------------- # Get all the dimensions that this file has. # Get their values as well (for caching). #-------------------------------------------- nc$dim <- list() nc$unlimdimid <- -1 # Will be set to the FIRST encountered unlim dim ID dimnames <- character() global_dim_counter <- 0 # counter of dims across ALL groups for( ig in 1:length(groups)) { for( idim in nc4_loop(1,groups[[ig]]$ndims)) { #----------------------------------------------- # New in v4: dimids don't go from 0..ndims, they # can be arbitrary #----------------------------------------------- dimid2use <- groups[[ig]]$dimid[idim] if( is.na(dimid2use)) { print(paste("Error, got a NA as a dimid2use ... group=", groups[[ig]]$name," which has ndims=", groups[[ig]]$ndims )) print("Here are the dimids from the ncgroup object:") print( groups[[ig]]$dimid ) if( return_on_error ) { print(paste("Error in nc_open trying to open file",filename, '(setting rv$error TRUE and returning because return_on_error==TRUE)' )) nc$error = TRUE return( nc ) } else stop("Error, cannot have NAs as dimids!") } if( verbose ) print(paste("nc_open: getting dim info for dim number",idim,"in group \"", groups[[ig]]$name, "\" dim ID=", dimid2use)) #----------------------------------------------------------- # As a general note, the function ncdim_inq does NOT return # a full-fledged "ncdim" object. It returns only a subset of # fields that directly correspond to a low-level, netCDF # dimension in a file. We now fill in the rest of the fields # to make it into a real ncdim object. #----------------------------------------------------------- d <- ncdim_inq(groups[[ig]]$id,dimid2use) # sets dim$name, $len, $unlim #--------------------------------------------------------------------- # Routine ncdim_inq sets only the simple name, not the fully qualified # dim name. Fix that now #--------------------------------------------------------------------- if( groups[[ig]]$name != "" ) # this comparison is FALSE if this is the root group d$name <- paste( groups[[ig]]$fqgn, "/", d$name, sep='' ) # example: "model1/run1/longitude". NO leading slash! d$group_index <- ig d$group_id <- groups[[ig]]$id d$id <- dimid2use # note: dim$id is the raw C-style integer ID to use WITHIN THE CORRECT GROUP #------------------ # Handle the dimvar #------------------ tt <- ncvar_id(groups[[ig]]$id, nc4_basename(d$name)) # note: dimvarid must be used with correct group. This is -1 if there is no dimvar d$dimvarid = ncdf4_make_id( id=tt, group_index=ig, group_id=groups[[ig]]$id, list_index=-1, isdimvar=TRUE ) # NOTE: dimvars are not on the global var list, so list_index == -1 if( verbose ) print(paste(".....dim name is",d$name," id=", d$id, " len=",d$len," dimvarid=",d$dimvarid$id)) if( d$dimvarid$id == -1 ) { # No dimvar for this dim if( ! suppress_dimvals ) d$vals <- 1:d$len d$units <- "" d$create_dimvar <- FALSE # in case this dim is passed to nc_create() } else { # This dim has a dimvar -- get its properties if( verbose ) print(paste("nc_open: getting dimvar info for dim ",d$name)) attv <- ncatt_get_inner( d$dimvarid$group_id, d$dimvarid$id, "units" ) if( attv$hasatt ) d$units <- attv$value else d$units <- "" attv <- ncatt_get_inner( d$dimvarid$group_id, d$dimvarid$id, "calendar" ) if( attv$hasatt ) d$calendar <- attv$value #else # since nothing else is defined here, is.null(d$calendar) will return TRUE if( ! suppress_dimvals ) { if( d$unlim && (! readunlim)) # Is unlimited, don't read vals, too slow d$vals <- rep(NA,d$len) else # Otherwise, read vals d$vals <- ncvar_get_inner( d$dimvarid$group_id, d$dimvarid$id, default_missval_ncdf4(), verbose=verbose ) } d$create_dimvar <- TRUE # in case this dim is passed to nc_create() } attr(d,"class") <- "ncdim4" # Is a complete ncdim object now global_dim_counter <- global_dim_counter + 1 # global is for ALL groups if( verbose ) { print("------------------------------") print("Here is new dim:") print(paste("Global index=", global_dim_counter, "name=",d$name,"len=",d$len,"unlim=",d$unlim, "id=",d$id,"dimvarid=",d$dimvarid$id,"units=",d$units)) print("------------------------------") } if( d$unlim && (nc$unlimdimid == -1)) nc$unlimdimid = global_dim_counter # NOTE: technically, this is not an ID, it's an index into the nc$dim[[]] list nc$dim[[global_dim_counter]] <- d # NOTE: nc$dim[[]] list is across ALL dims in file, regardless of group dimnames[global_dim_counter] <- d$name # NOTE: in ncdf4, dim[[]] is indexed by FULLY QUALIFIED dim name if( verbose ) print(paste(".......nc_open: done processing dim ",d$name)) } } attr(nc$dim,"names") <- dimnames if(verbose) { print("nc_open: setting dim$ to:") print(dimnames) } #------------------------------------------- # Get all the vars that this file has. Note # that dimvars are NOT included in the count # of vars!! #------------------------------------------- if( verbose ) print(paste("nc_open: getting var info. Number of vars (INCLUDING dimvars)=",tot_nvars_inc_dimvars)) nc$nvars <- 0 # NOTE this is a GLOBAL list, i.e., it includes vars from ALL groups nc$var <- list() varnames <- character() have_warned_noncompliant <- FALSE for( ig in 1:length(groups)) { for( ivar in nc4_loop(1,groups[[ig]]$nvars)) { #----------------------------------------------------------------- # Note this is the 'simple' name, NOT the fully qualified var name #----------------------------------------------------------------- name <- ncvar_name( groups[[ig]]$id, ivar-1 ) # ivar-1 because ncvar_name takes input in C standard, which starts at 0 if( verbose ) print(paste("Working on group",ig,"(of",length(groups),"), var", ivar, "(of", groups[[ig]]$nvars,"), name=", name)) if( ncdim_id( groups[[ig]]$id, name ) == -1 ) { # Only process if NOT a dimvar #-------------------------------------- # No dim with same name as this var, so # this var must NOT be a dimvar. #-------------------------------------- if( verbose ) print(paste("nc_open var loop: will process with group id=", groups[[ig]]$id, " varid=",ivar," var name=",name)) #--------------------------------------------------------------------------------------------------- # ncvar_inq sets the following: # $id: an object of class 'ncid', with $id, $group_id, $group_index(==-1), and list_index(==-1) # $name # $ndims # $natts # $size # $dimids: raw integer C-style (0-based counting) dimids but in R order # $prec: one of "short', "int", "float", "double", "byte" # $units: units string, or "" # $longname: longname attribute, or "" #--------------------------------------------------------------------------------------------------- v <- ncvar_inq( groups[[ig]]$id, ivar-1 ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 attr(v,"class") <- "ncvar4" nc$nvars <- nc$nvars + 1 v$group_index = ig v$id$list_index = nc$nvars #-------------------------------------------------------------------------------- # Routine ncvar_inq sets the var's name to the SIMPLE (not-fully qualified) name. # Fix that now. #-------------------------------------------------------------------------------- if( groups[[ig]]$name != "" ) # this comparison is FALSE if this is the root group v$name <- paste( groups[[ig]]$fqgn, "/", v$name, sep='' ) # example: "model1/run1/Temperature". NO leading slash! #--------------------------------------------------- # Get netcdf-4 specific information for the variable #--------------------------------------------------- if( (nc$format == 'NC_FORMAT_NETCDF4') || (nc$format == 'NC_FORMAT_NETCDF4_CLASSIC')) { #----------------------- # Inquire about chunking #----------------------- chunkrv = ncvar_inq_chunking( groups[[ig]]$id, ivar-1, v$ndims ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 v$chunksizes = chunkrv$chunksizes v$storage = chunkrv$storage # 1 for NC_CONTIGUOUS and 2 for NC_CHUNKED #-------------------------- # Inquire about compression #-------------------------- comprv = ncvar_inq_deflate( groups[[ig]]$id, ivar-1 ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 v$shuffle = comprv$shuffle if( comprv$deflate == 0 ) v$compression = NA else v$compression = as.integer( comprv$deflate_level ) } else { v$chunksizes = NA v$storage = 1 # 1 for NC_CONTIGUOUS and 2 for NC_CHUNKED v$shuffle = FALSE v$compression = NA } #----------------------------------------------------------------------------------- # Get this var's dims. Special netcdf-4 note: it seems that the way the netcdf-4 # library works is that variables are numbered starting at 0 for each group, but # that dims are numbered consecutively across all groups. I guess this is mandated # by the way that a var's dims can be in either the var's group or ANY PARENT GROUP, # which implies that dimids cannot ever be repeated in a file, even if the file has # multiple groups. #----------------------------------------------------------------------------------- v$dims <- list() varunlim <- FALSE if( v$ndims > 0 ) { for( j in 1:v$ndims ) { dimid2find = v$dimids[j] matchidx = -1 for( iidim in 1:nc$ndims ) { if( nc$dim[[iidim]]$id == dimid2find ) { matchidx = iidim break } } if( matchidx == -1 ) stop(paste("internal error, did not find dim with id=",dimid2find,"in dim list!")) v$dim[[j]] = nc$dim[[matchidx]] if( v$dim[[j]]$unlim ) varunlim <- TRUE v$varsize <- append(v$varsize, v$dim[[j]]$len) } } v$unlim <- varunlim #------------------------------------------------------------ # Fix for classic files that are unlimited -- they are stored # in chunked format, as far as I know #------------------------------------------------------------ if( (nc$format != 'NC_FORMAT_NETCDF4') && varunlim) v$storage = 2 # 1 for NC_CONTIGUOUS and 2 for NC_CHUNKED #---------------------------------------- # Get this var's missing value, or set to # a default value if it does not have one #---------------------------------------- found_mv <- FALSE v$make_missing_value <- FALSE mv <- ncatt_get_inner( groups[[ig]]$id, ivar-1, "missing_value" ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 if( mv$hasatt ) { found_mv <- TRUE v$missval <- mv$value v$make_missing_value <- TRUE } else { mv <- ncatt_get_inner( groups[[ig]]$id, ivar-1, "_FillValue" ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 if( mv$hasatt ) { found_mv <- TRUE v$missval <- mv$value v$make_missing_value <- TRUE } } if( ! found_mv ) { if( (v$prec=="float") || (v$prec=="double")) v$missval <- default_missval_ncdf4() else v$missval <- NA } #-------------------------------------------- # Special check for noncompliant netCDF files #-------------------------------------------- if( (v$prec=="float") || (v$prec=="double")) { if( storage.mode(v$missval) == "character" ) { v$missval <- as.double( v$missval ) if(! have_warned_noncompliant ) { warning(paste("WARNING file",filename,"is not compliant netCDF; variable",name," is numeric but has a character-type missing value! This is an error! Compensating, but you should fix the file!")) have_warned_noncompliant <- TRUE } } } #------------------------------------------- # Get add_offset and scale_factor attributes #------------------------------------------- ao <- ncatt_get_inner( groups[[ig]]$id, ivar-1, "add_offset" ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 if( ao$hasatt ) { v$hasAddOffset <- TRUE v$addOffset <- ao$value } else v$hasAddOffset <- FALSE sf <- ncatt_get_inner( groups[[ig]]$id, ivar-1, "scale_factor" ) # ivar-1 because ncvar_inq takes input in C standard, which starts at 0 if( sf$hasatt ) { v$hasScaleFact <- TRUE v$scaleFact <- sf$value } else v$hasScaleFact <- FALSE nc$var[[nc$nvars]] <- v varnames <- append(varnames,v$name) # NOTE: fully qualified var name, not simple name if( verbose ) { print("-----------------------") print("Here is new var:") print(paste("name=",v$name," group_id=",v$id$group_id, " id=",v$id$id," ndims=",v$ndims," prec=",v$prec)) print("size=") print(v$size) print("dimids=") print(v$dimids) } } # end of "if NOT dimvar" clause } # end of loop over vars in this group } # end of loop over all groups #--------------------------------------------------------------------------- # Handle GMT style files by manipulating them so that they seem like regular # netcdf files #--------------------------------------------------------------------------- if( (nc$nvars == 1) && nc$is_GMT ) { # Not implmented yet } attr(nc$var,"names") <- varnames #---------------------------------------------------------------------------- # If we are running in safe mode, CLOSE THE FILE before exiting. Note that # this invalidates ncid, so anytime subsequent to this when we want to # access a file in safe mode, we cannot use the stored ncid, which is invalid #---------------------------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } if( verbose ) print(paste("nc_open: leaving for ncid=",nc$id)) return(nc) } #========================================================================================================= # This is used to change a missing value to a desired value. It # is used when a file has not been created on disk yet, or when # an existing disk file has been opened to be writable. # 'varid' may be a character string with the var's name, # or a ncvar class. # ncvar_change_missval <- function( nc, varid, missval ) { #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("ncvar_change_missval: passed nc NOT of class ncdf4!") #------------------------------------------------------ # Can't do this if the file is on disk and not writable #------------------------------------------------------ if( (nc$filename != "IN-MEMORY") && (! nc$writable)) stop("ncvar_change_missval: the netcdf file was NOT opened in write mode!") idobj <- vobjtovarid4( nc, varid ) # object of type 'ncid', NOT just a simple integer if( idobj$id == -1 ) stop(paste("error: could not find passed variable in the specified netcdf file. Are you sure it's actually in that file?")) idx <- idobj$list_index if( idx < 1 ) stop(paste("Error, did not specify enough information to identify where var is on the global var list. Are you trying to change the missing value for a dimvar? That operation is not supported")) nc$var[[idx]]$missval <- missval if( nc$filename != "IN-MEMORY" ) { if( nc$safemode ) nc$id = ncdf4_inner_open( nc ) ncatt_put( nc, varid, "missing_value", missval ) if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } } } #========================================================================================================= # This is the public interface for creating a netCDF file # on disk. It takes arguments of class ncvar to put in the file. # It creates the file on disk and returns an object of class "ncdf4" # that can be used to access that file. # # Example usage, where "temp" and "salin" are objects of class ncvar4: # # nc <- ncdf.create( "test.nc", list(temp,salin)) # or # nc <- ncdf.create( "test.nc", salin ) # # If safemode is set, then that will determine whether or not safemode is off # according to its value. Otherwise, safemode will be set to TRUE iff we are on the # Windows-64 platform. # nc_create <- function( filename, vars, force_v4=FALSE, verbose=FALSE ) { if( verbose ) print(paste('nc_create: entering, package version', nc_version() )) safemode = FALSE if( (! is.character(filename)) || (nchar(filename)<1)) stop("input filename must be a character string") #---------------------------------------------------- # Have to tell if the input vars is a single var or a # list of vars. Do it by examining vars$class. If # vars is a single var, then this will equal "ncvar"; # if vars orig is a list of vars, this will be NULL. #---------------------------------------------------- #if( is.character(class(vars)) && (class(vars) == "ncvar4") ) { if( inherits( vars, 'ncvar4' )) { vars <- list(vars) if( verbose ) print("nc_create: input was a single var") } #else if(is.character(class(vars)) && (class(vars) == "list") ) { else if( inherits( vars, 'list' )) { if( length(vars) < 1 ) stop("Error, at least one ncvar object must be supplied in the vars list") #if( (! is.character(class(vars[[1]]))) || (class(vars[[1]]) != "ncvar4")) if( ! inherits( vars[[1]], 'ncvar4' )) stop("Error, second arg must either be a ncvar object (created by a call to ncvar_def()) or a list of ncvar objects") #------------------------------------------------------- # Make sure ALL elements in the list are of class ncvar4 #------------------------------------------------------- for( ilist in nc4_loop(2,length(vars)) ) #if( (! is.character(class(vars[[ilist]]))) || (class(vars[[ilist]]) != "ncvar4")) if( ! inherits( vars[[ilist]], 'ncvar4' )) stop(paste("Error, found an element of the vars list that is NOT an object created by a call to ncvar_def...element #",ilist,sep='')) if( verbose ) print("nc_create: input was a list of vars") } else stop("Error, second arg must either be a ncvar object (created by a call to ncvar_def()) or a list of ncvar objects") #------------------------------------------------------------ # Figure out the list of all groups that we will be creating. #------------------------------------------------------------ if( verbose ) print('nc_create: parsing group structure') group <- nc_parse_group_structure( vars, verbose=verbose ) if( length(group) > 1 ) { if( verbose ) print("Forcing netcdf version 4 format file since there is more than 1 group") force_v4 <- TRUE } #----------------------------------------------------------------------- # If any variables use compression or chunking, we must create a V4 file #----------------------------------------------------------------------- if( verbose ) print('nc_create: checking to see if we MUST produce a netcdf-version 4 file') for( ivar in 1:length(vars)) { use_shuffle = vars[[ivar]]$shuffle use_compression = (! is.na(vars[[ivar]]$compression)) use_chunking = ((length(vars[[ivar]]$chunksizes)>1) || (! is.na(vars[[ivar]]$chunksizes))) if( verbose ) print(paste("var: >", vars[[ivar]]$name,"< Use shuffle: >",use_shuffle, "< use_compression: >",use_compression, "< use_chunking: >",use_chunking,"<", sep='' )) if( use_shuffle || use_compression || use_chunking ) { if( verbose ) print("Forcing netcdf version 4 format file since a var using compression or chunking") force_v4 = TRUE } else { if( verbose ) print("Not forcing netcdf version 4 format file since no var is using compression or chunking") } } #--------------------------------------------------------------------- # If there are multiple unlimited dimensions, we must create a V4 file #--------------------------------------------------------------------- if( verbose ) print('nc_create: checking to see if there are multiple unlimited dims (which would force V4 file)') unlim_dimname = '' multi_unlim_dims = FALSE for( ivar in 1:length(vars)) { ndims = vars[[ivar]]$ndims if( ndims > 0 ) { for( idim in 1:ndims ) { if( vars[[ivar]]$dim[[idim]]$unlim ) { if( nchar(unlim_dimname) == 0 ) unlim_dimname = vars[[ivar]]$dim[[idim]]$name else if( vars[[ivar]]$dim[[idim]]$name != unlim_dimname ) { if( verbose ) print(paste("Forcing netcdf version 4 format file", "since there is more than 1 unlimited dim")) force_v4 = TRUE multi_unlim_dims = TRUE break } } } } } if( verbose ) { if( multi_unlim_dims ) print('nc_create: Yes, there ARE multiple unlimited dims in this file, forcing V4') else print('nc_create: No, there are not any multiple unlimited dims in this file') } nc <- list() #----------------------------------------------------------- # These values MUST MATCH the values in the source code file # ncdf.c, routine R_nc4_create! #----------------------------------------------------------- flag_NC_NOCLOBBER <- 1 flag_NC_SHARE <- 2 flag_NC_64BIT_OFFSET <- 4 flag_NC_NETCDF4 <- 8 #---------------- # Create the file #---------------- nc$cmode <- 0 if( force_v4 ) nc$cmode <- nc$cmode + flag_NC_NETCDF4 nc$error <- -1 nc$id <- -1 if( verbose ) print(paste("Calling R_nc4_create for file ",filename)) nc<-.C("R_nc4_create", filename, as.integer(nc$cmode), id=as.integer(nc$id), error=as.integer(nc$error), PACKAGE="ncdf4") if( nc$error != 0 ) stop("Error in nc_create!") if( verbose ) print(paste("back from R_nc4_create for file ",filename)) nc$nvars <- 0 attr(nc,"class") <- "ncdf4" nc$filename <- filename nc$writable <- TRUE nc$ndims <- 0 nc$dim <- list() nc$var <- list() #--------------------------------------------------------- # This must be ON for Windows-7 64-bit, off for everything # else (as of Feb 2014) #--------------------------------------------------------- am_windows = (length(grep( 'windows', .Platform$OS.type, ignore.case=TRUE)) != 0) am_64 = (length(grep( 'x64', .Platform$r_arch, ignore.case=TRUE)) != 0) nc$safemode <- (am_windows && am_64) nc$safemode = FALSE #if( nc$safemode && (!is.na(safemode)) && (safemode == FALSE) ) { # print(paste("***************** W A R N I N G *****************************")) # print(paste("You are running on Windows-64 but have specified to force the")) # print(paste("safemode OFF. Safemode protects from KNOWN BUGS of the netcdf")) # print(paste("library on Windows-64. If you force safemode off YOU MUST NEVER")) # print(paste("HAVE MORE THAN ONE NETCDF FILE OPEN AT THE SAME TIME, or you")) # print(paste("may get errors of the type that the ncdf4 operators access the")) # print(paste("WRONG FILE. You are proceeding at your own risk!!")) # print(paste("***************************************************************")) # } #if( !is.na(safemode)) # nc$safemode = safemode #-------------------------- # Create groups in the file #-------------------------- nc$group <- group nc$ngroups <- length( group ) # Note: will always be at least 1, since root group is in there nc$group[[1]]$id <- nc$id # id of group 1, which is the root group, is always exactly equal to ncid nc$fqgn2Rindex <- list() # given fqgn, gives R index into nc$group list nc$fqgn2Rindex[["/"]] <- 1 # the root group is always the first entry on the group list if( nc$ngroups > 1 ) { if( verbose ) print(paste("nc_create: about to create the",nc$ngroups-1,"non-root groups")) for( ig in 2:nc$ngroups ) { # Note: skip root group group_name <- nc$group[[ig]]$name fqgn <- nc$group[[ig]]$fqgn # fully qualified group name fqpn <- nc$group[[ig]]$fqpn # fully qualified parent group name if( fqpn == "" ) fqpn <- '/' pidx <- nc$fqgn2Rindex[[ fqpn ]] # index of parent group in group list if( verbose ) print(paste("Defining group", group_name, "(which has parent", fqpn,")" )) if( (pidx<1) || (pidx>nc$ngroups) || is.null(pidx)) { print(paste("error, did not find index for parent group", fqpn, "in fqgn2Rindex!")) print('Here are the entries in fqgn2Rindex:') nn <- length(nc$fqgn2Rindex) for( ii in 1:nn ) print(paste(names(nc$fqgn2Rindex)[ii], '-->', nc$fqgn2Rindex[[ii]] )) stop("internal error") } parentid <- nc$group[[pidx]]$id if( parentid < 1 ) stop(paste("error, apparently the parent group", fqpn, "has not been defined yet, but i need to reference it!")) #------------------------------------------- # This call actually makes the group on disk #------------------------------------------- gid <- nc_make_group_inner( parentid, group_name ) if( verbose ) print(paste("back from nc_make_group_inner call for file ",filename,"; just made group ", group_name," with new group id:", gid)) nc$group[[ig]]$id <- gid nc$fqgn2Rindex[[ fqgn ]] <- ig } } max_nc_dims <- 20 #--------------------------------------------------------------- # Add the vars to the file. NOTE that this also adds the unique # dims (and hence, dimvars) to the file as a side effect! # Note also that the returned 'nc' value is updated each time # this subroutine is called. #--------------------------------------------------------------- if( verbose ) print("nc_create: about to create the vars") for(ivar in 1:length(vars)) nc <- ncvar_add( nc, vars[[ivar]], verbose=verbose, indefine=TRUE ) #----------------------------------------------------------- # Set the names attribute on the $var and $dim lists so that # we can access them by FULLY QUALIFIED name instead of only # by position #----------------------------------------------------------- if( verbose ) print("nc_create: setting names attribute on $var and $dim lists") varnames <- array('',nc$nvars) for( ivar in nc4_loop(1,nc$nvars)) varnames[ivar] <- nc$var[[ivar]]$name attr(nc$var,"names") <- varnames dimnames <- array('',nc$ndims) for( idim in nc4_loop(1,nc$ndims) ) dimnames[idim] <- nc$dim[[idim]]$name attr(nc$dim,"names") <- dimnames #----------------- # Exit define mode #----------------- if( verbose ) print("nc_create: exiting define mode") #nc_enddef( nc, ignore_safemode=TRUE ) if( nc_enddef( nc ) != 0 ) { print(paste("Error, nc_enddef returned an error! Error happened with filename=", filename, "and vars:")) for( kk in 1:length(vars)) print(paste(kk, ':', vars[[kk]]$name )) stop('fatal error in nc_create') } #----------------------------------------------------------------------- # Have to set the format string of the ncdf4 object. We could calculate # this from first principles by analyzing the kind of file we just # created. However I'm thinking it's easier and less error prone simply # to read back in the format from the file that's now on disk. # Possible (string) values are: # 'NC_FORMAT_CLASSIC', 'NC_FORMAT_64BIT', 'NC_FORMAT_NETCDF4', # and 'NC_FORMAT_NETCDF4_CLASSIC' #----------------------------------------------------------------------- nc$format = ncdf4_format( nc$id ) if( verbose ) print(paste("file", filename, "is format", nc$format )) #-------------------------------------------------------- # If we are running in safe mode, must close the file now #-------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } return(nc) } #=============================================================== # This is a SPECIAL PURPOSE function ONLY to be used when adding # an already defined variable (accomplished via "ncvar_def") # to an ALREADY EXISTING netcdf file. Normally, when making # a new netcdf file from scratch, a list of vars to be created # would be passed to "nc_create"; this is the preferred method # of putting vars in a file. However, sometimes it's necessary # to add a var to an already-existing file; that's what this # routine is for. # # Inputs: # nc : object of class 'ncdf4' # v : object of class 'ncvar4' # ncvar_add <- function( nc, v, verbose=FALSE, indefine=FALSE ) { if( verbose ) print(paste("ncvar_add: entering with indefine=",indefine)) #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("ncvar_add: passed nc NOT of class ncdf4!") if( verbose ) print(paste("ncvar_add: ncid of file to add to=",nc$id, " filename=",nc$filename," writable=",nc$writable)) #if( class(v) != "ncvar4" ) if( ! inherits( v, 'ncvar4' )) stop("var.add.ncdf: passed var NOT of class ncvar4! The second arg to var.add.ncdf must be the return value from a call to ncvar_def") if( verbose ) print(paste("ncvar_add: varname to add=",v$name)) #---------------------------------------------------- # If we are running in safemode, must reopen the file #---------------------------------------------------- if( (! indefine) && nc$safemode ) nc$id = ncdf4_inner_open( nc ) if( ! indefine ) { if( verbose ) print(paste("ncvar_add: about to redef ncid=",nc$id)) #nc_redef( nc, ignore_safemode=TRUE ) # Go back into define mode nc_redef( nc ) # Go back into define mode } #----------------------------------------------------------------------- # If the variable lives in a group, then this must be a netcdf version 4 # file to work #----------------------------------------------------------------------- if( nslashes_ncdf4( v$name ) > 0 ) { if ( ncdf4_format( nc$id ) != 'NC_FORMAT_NETCDF4' ) { print(paste("Error, you specified adding a variable in a group to the netcdf file, but the file is NOT netcdf version 4 format -- this is impossible!")) print(paste("Here is the name of the variable that is trying to be added:", v$name )) print(paste("Here is the file that the variable is trying to be added to:", nc$filename )) stop('Error') } } #----------------------------------------------------- # Create the dims for this var. Harder than it sounds # because we must take care not to repeat making a dim # that occurs in more than one variable. #--------------------------------------------------- nd <- v$ndims dimvarids <- array(0,nd) if( verbose ) print(paste("ncvar_add: creating",nd,"dims for var",v$name)) for( idim in nc4_loop(1,nd) ) { d <- v$dim[[idim]] if( verbose ) print(paste("ncvar_add: working on dim >",d$name,"< (number",idim,") for var",v$name)) #----------------------------------------------- # See if we've already made a dim with this name # in this group #----------------------------------------------- place <- -1 for( ii in nc4_loop(1,length(nc$dim))) { if( nc$dim[[ii]]$name == d$name ) { #--------------------------------------------------------------- # Check to make sure this is REALLY the same dim, even though we # know it has the same name as an existing dim! #--------------------------------------------------------------- if( ! ncdim_same( nc$dim[[ii]], d )) { stop(paste("Error, when trying to add variable named", v$name, "to file",nc$filename,"I found this variable has a dim named",d$name, "However, the file ALREADY has a dim named",nc$dim[[ii]]$name, "with different characteristics than the new dim with the same name!", "This is not allowed.")) } if( verbose ) print(paste("ncvar_add: dim",d$name, "has been seen before")) place <- ii break } } if( place == -1 ) { #-------------------------------------------- # This dim has not been seen before -- create #-------------------------------------------- if( verbose ) print(paste("ncvar_add: creating dim",d$name, "(which has not been seen before)")) #-------------------------------------------------------------------------------- # Following call returns dim ID, divar ID, group ID used to access the first two, # and group INDEX used to access the first two #-------------------------------------------------------------------------------- ids <- ncdim_create(nc,d,verbose) # *** NOTE: makes the dimvar, too! *** dimid <- ids[1] dimvarid <- ids[2] group_id <- ids[3] group_index <- ids[4] newel <- list() attr(newel,"class") <- "ncdim4" newel$name <- d$name newel$units <- d$units newel$vals <- d$vals newel$len <- d$len newel$unlim <- d$unlim nc$ndims <- nc$ndims + 1 newel$id <- dimid # remember, dimids are just simple integers, varids are ncid objects newel$dimvarid <- ncdf4_make_id( id=dimvarid, group_index=group_index, group_id=group_id, list_index=nc$ndims, isdimvar=TRUE ) nc$dim[[nc$ndims]] <- newel } else dimid <- nc$dim[[place]]$id # simple C-style 0-counting based integer dimvarids[idim] <- dimid # OK that this is the simple integer, not a ncid object, # since by v4 spec dims must be visible to vars. } #---------------------------------------------------- # Reverse the dimvarids, because R uses Fortran-style # ordering and we are using the C netCDF interface #---------------------------------------------------- dimids <- dimvarids if( nd > 0 ) dimids <- dimids[length(dimids):1] newvar <- list() newvar$id <- -1 newvar$error <- -1 #----------------------------------------------------------------------- # Figure out the ncid to use. If this var is in the root group, it will # just be the ncid. Otherwise, it will be the group id #----------------------------------------------------------------------- if( verbose ) print('ncvar_add: figuring out ncid to use') if( nslashes_ncdf4( v$name ) == 0 ) gidx <- 1 else { vars_fqgn <- nc4_basename( v$name, dir=TRUE ) # this is the var's fully qualified GROUP name gidx <- nc$fqgn2Rindex[[ vars_fqgn ]] if( is.null(gidx)) { print(paste('internal error: did not find fully qualified group name "', vars_fqgn, '" in list of groups for file >', nc$filename, '<', sep='')) if( is.null( nc$fqgn2Rindex )) print('Reason: nc$fqgn2Rindex is empty (null)!') else { print(paste('Here is the nc$fqgn2Rindex list:')) print(nc$fqgn2Rindex) } stop('Error') } } ncid2use <- nc$group[[gidx]]$id name2use <- nc4_basename( v$name ) if( verbose ) print(paste('ncvar_add: ncid2use=', ncid2use, 'name2use=', name2use )) #-------------------------------------------------------------- # Now actually create the variable. Select the routine we will # be using to create the variable based on its precision #-------------------------------------------------------------- if( verbose ) print(paste("ncvar_add: creating",v$prec,"precision var",v$name)) if( (v$prec == "integer") || (v$prec == "int") ) newvar<-.C("R_nc4_def_var_int", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else if( v$prec == "short" ) newvar<-.C("R_nc4_def_var_short", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else if( (v$prec == "float")) newvar<-.C("R_nc4_def_var_float", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else if( v$prec == "double" ) newvar<-.C("R_nc4_def_var_double", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else if( v$prec == "char" ) newvar<-.C("R_nc4_def_var_char", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else if( v$prec == "byte" ) newvar<-.C("R_nc4_def_var_byte", as.integer(ncid2use), as.character(name2use), as.integer(v$ndims), as.integer(dimids), id=as.integer(newvar$id), error=as.integer(newvar$error), PACKAGE="ncdf4") else stop(paste("internal error in nc_create: var has unknown precision:",v$prec,". Known vals: short float double integer char byte")) if( verbose ) print(paste("nc_create: C call returned value",newvar$error)) if( newvar$error != 0 ) { print('----------------------') print(paste('Var: ', v$name)) print(paste('Ndims: ', v$ndims)) print('Dimids: ') print(dimids) stop(paste("Error in ncvar_add, defining var", v$name)) } nc$nvars <- nc$nvars + 1 v$id <- ncdf4_make_id( newvar$id, gidx, ncid2use, nc$nvars ) v$hasAddOffset <- FALSE v$hasScaleFact <- FALSE nc$var[[nc$nvars]] <- v #---------------------------------------- # Set compression parameters if requested #---------------------------------------- if( v$shuffle || (! is.na(v$compression))) { if( verbose ) print(paste("nc_var_add: setting compression params")) if( v$shuffle ) shuffle_param = 1 else shuffle_param = 0 if( is.na(v$compression) ) { d_param = 0 d_level = 0 } else { d_param = 1 d_level = v$compression } ncvar_def_deflate( ncid2use, newvar$id, shuffle_param, d_param, d_level ) } #------------------------------------- # Set chunking parameters if requested #------------------------------------- if( (length(v$chunksizes)>1) || (! is.na(v$chunksizes)) ) { if( verbose ) print(paste("nc_var_add: setting chunking params")) chunksizes = as.integer(v$chunksizes) #-------------------------------------------------------------- # Make sure no chunksize is larger than a fixed (non-unlim) dim #-------------------------------------------------------------- if( length(chunksizes) != v$ndims ) stop(paste("Error, for var",v$name,"ndims=",v$ndims,"but length of chunksizes array=", length(chunksizes),". They must be the same!")) for( ii in 1:v$ndims ) { if( (! v$dim[[ii]]$unlim) && (chunksizes[ii] > v$dim[[ii]]$len)) stop(paste("Error in supplied chunksizes: dim number",ii, ", named", v$dim[[ii]]$name,", is length", v$dim[[ii]]$len,"but chunksizes for this dim is ", chunksizes[ii],". Chunksizes must be <= dim length!")) if( chunksizes[ii] < 1 ) stop(paste("Error in supplied chunksizes: dim number",ii, ", named", v$dim[[ii]]$name,", is length", v$dim[[ii]]$len,"but chunksizes must be >= 1")) } storage = 2 # set flag to enable chunking ncvar_def_chunking( ncid2use, newvar$id, storage, chunksizes ) } #------------------------------------------------------ # Add the attributes -- units, missing_value, long_name #------------------------------------------------------ if( verbose ) print(paste("nc_var_add: adding attributes")) if( (! is.null( v$units )) && (! is.na(v$units)) && (nchar(v$units)>0)) ncatt_put_inner( ncid2use, newvar$id, "units", v$units, definemode=TRUE ) #------------------------------------ # Create a missing value if requested #------------------------------------ if( verbose ) print(paste("nc_var_add: creating missing value if requested")) if( v$make_missing_value ) { if( is.null( v$missval ) && ((v$prec=="float") || (v$prec=="double"))) { ncatt_put_inner( ncid2use, newvar$id, "_FillValue", default_missval_ncdf4(), definemode=TRUE ) } else { if( ! is.null(v$missval) ) { ncatt_put_inner( ncid2use, newvar$id, "_FillValue", v$missval, definemode=TRUE, verbose=verbose, prec=v$prec ) } } } #------------------------- # Make long name attribute #------------------------- if( verbose ) print(paste("nc_var_add: creating long name attribute")) if( (v$longname != v$name) && (nchar(v$longname)>0)) ncatt_put_inner( ncid2use, newvar$id, "long_name", v$longname, definemode=TRUE ) if( ! indefine ) { if( verbose ) print("ncvar_add: ending define mode") #nc_enddef( nc, ignore_safemode=TRUE ) # Exit define mode if( nc_enddef( nc ) != 0 ) stop(paste("Error, nc_enddef returned an error!")) } #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( (! indefine) && nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } if( verbose ) print(paste("nc_var_add: returning")) return(nc) } #=============================================================== # This has two modes, depending on the value of 'attname' that # is passed in. # # If an attname is specified, then # this returns a list; first element of list (named "hasatt") # is TRUE if the variable had an attribute with name "attname", and # is FALSE otherwise. Second element of the list (named "value") # holds the value IFF the variable had an attribute of that name. # # "varid" can be one of: # * a character string with a var's name # * an integer varid (R-type varid with counting starting at 1) # * an object of class ncvar4 # * the integer value 0 for a global att # * a fully qualified group name, in which case that group's # "global" atts will be accessed # # If the attribute type is short or integer, an integer value is # returned. If the attribute type is float or double, a double # value is returned. If the attribute type is text, a character # value is returned. # # If no attname is specified, then this returns a list, with the # name of the element set to the attribute name, and the value of # the element set to the attribute's value. If the varid is 0, # then global attributes are returned. If the indicated variable # (or file) has no attributes, then a list with 0 elements is # returned. # ncatt_get <- function( nc, varid, attname=NA, verbose=FALSE ) { if( verbose ) print('ncatt_get: entering') #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("Error, first passed argument must be an object of class ncdf4") #---------------------------------------------------- # If we are running in safemode, must reopen the file #---------------------------------------------------- if( nc$safemode ) nc$id = ncdf4_inner_open( nc ) #---------------------------------------- # Is varid a string? If so, is it a FQGN? #---------------------------------------- glist_index = -1 vid_sm = storage.mode( varid ) if( vid_sm == 'character' ) glist_index = nc_is_a_fqgn( varid, nc ) #---------------------------------------------------------------------------- # Atts have a special case where an integer 0 means to access the global atts #---------------------------------------------------------------------------- is_global = FALSE if( is.numeric(varid) && (varid == 0)) { is_global = TRUE if( verbose ) print('ncatt_get: is a global att') } #---------------------------------------------------------------------------------- # In netcdf-4, atts have another special case where the varid can refer exclusively # to a fully qualified group name (FQGN), *not* a variable name. In that event, # it is referring to "global-like" atts in that specified group #---------------------------------------------------------------------------------- else if( (vid_sm == "character") && ( glist_index > 0 ) ) { #---------------------------------------------------------------------------- # If we get here, the varid is specifing a group name, and we want a "global" # attribute from that group. glist_index is the INDEX into ncid$group[[]] # for the group in question (the one where varid is the FQGN) #---------------------------------------------------------------------------- group_id = nc$group[[ glist_index ]]$id return( ncatt_get_inner( group_id, -1, attname=attname, verbose=verbose )) # NOTE how we convert from varid=0 to varid=-1 here to match C API standard } else { #if( (class(varid) != "ncvar4") && (!is.character(varid))) is_class_ncvar4 = ( inherits( varid, 'ncvar4' )) if( ( ! is_class_ncvar4) && (!is.character(varid))) stop(paste("second arg (varid) must be one of: 0, an object of class ncvar4, or the character string name of a variable")) if( verbose ) print('ncatt_get: is NOT a global att') } if( is_global ) { if( verbose ) print('ncatt_get: calling ncatt_get_inner for a global att') return( ncatt_get_inner( nc$id, -1, attname=attname, verbose=verbose )) # NOTE how we convert from varid=0 to varid=-1 here to match C API standard } else { #if( (class(varid) != "ncvar4") && ( vid_sm != "character" )) is_class_ncvar4 = ( inherits( varid, 'ncvar4' )) if( (! is_class_ncvar4) && ( vid_sm != "character" )) stop("ncvar_change_missval: error, passed varid must be either 0 (for global attributes), the name of the variable to operate on, or an object of class ncvar4") if( verbose ) print('ncatt_get: getting object id') idobj <- vobjtovarid4( nc, varid, allowdimvar=TRUE, verbose=verbose ) # an object of class 'ncid4' if( idobj$id == -1 ) return( list() ) if( verbose ) print('ncatt_get: calling ncatt_get_inner for a non-global att') return( ncatt_get_inner( idobj$group_id, idobj$id, attname=attname, verbose=verbose )) } #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } } #================================================================================================= # Put an attribute into a netCDF file. This puts the file into # define mode, then takes it back out of define mode when done (unless # definemode=TRUE, in which case the file is ASSUMED to be in define # mode already, and is left in define mode as well). # # NOTE this does not work with IN-MEMORY ncdf files. # (Note: you could extend this to work with in-memory files by # having a list of variable (or file) attributes in the appropriate # R classes, but I haven't bothered to do this since it does not # come up very much for me.) # # "varid" can be an object of class ncvar4 or character string with a var's name. # As a special case, if varid==0, then a global attribute is set instead of a variable's # attribute. # # "nc" can be a ncdf4 class object # # Precision: ordinarily the precision (type) of the attribute will always # follow the precision (type) of the var that this is an attribute of. # However, you can explicitly override this by setting "prec" to the # desired precision, which can be one of: short float double text( or character) integer. # In the event of a global attribute, which of course has no associated # variable, the storage mode of the passed attval will be used to # determine the precision of the attribute, UNLESS "prec" is set. # If "prec" is set, it always determines the created attribute type. # ncatt_put <- function( nc, varid, attname, attval, prec=NA, verbose=FALSE, definemode=FALSE ) { if( verbose ) print('ncatt_put: entering' ) #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("Error, first passed argument must be an object of class ncdf4") #------------------------------------------------------- # Can't do this if the file is in memory or not writable #------------------------------------------------------- if( (nc$filename == "IN-MEMORY") || (! nc$writable)) stop("ncatt_put: the netcdf file has not been written to disk yet, or was not opened in write mode!") #---------------------------------------------------- # If we are running in safemode, must reopen the file #---------------------------------------------------- if( nc$safemode ) nc$id = ncdf4_inner_open( nc ) #---------------------------------------------------------------------------- # Atts have a special case where an integer 0 means to access the global atts #---------------------------------------------------------------------------- if( verbose ) print('ncatt_put: checking for a global att' ) if( is.numeric(varid) && (varid == 0)) is_global = TRUE else { #if( (class(varid) != "ncvar4") && (!is.character(varid))) is_class_ncvar4 = ( inherits( varid, 'ncvar4' )) if( (! is_class_ncvar4) && (!is.character(varid))) stop(paste("second arg (varid) must be one of: 0, an object of class ncvar4, or the character string name of a variable")) is_global = FALSE } if( is_global ) { if( verbose ) print('ncatt_put: IS a global att' ) ncatt_put_inner( nc$id, -1, attname, attval, prec=prec, verbose=verbose, definemode=definemode ) } else { if( verbose ) print('ncatt_put: is NOT a global att' ) idobj <- vobjtovarid4( nc, varid, allowdimvar=TRUE ) # an object of type "ncid", NOT just a simple integer if( verbose ) print(paste("Making attribute",attname,"with value",attval,"for ncid=",idobj$group_id, "and varid=",idobj$id)) #---------------------------------------------------------------------- # It is possible to identify a dimvar but not actually have that dimvar # present. This is signaled by $isdimvar && $id == -1. #---------------------------------------------------------------------- if( idobj$isdimvar && (idobj$id == -1)) stop(paste("dimension", varid$name, "in file", nc$filename, "does NOT have a dimvar, so you cannot call ncatt_put with the name of that dimension to try to put an attribute on the dimvar")) if( verbose ) print('ncatt_put: calling ncatt_put_inner') ncatt_put_inner( idobj$group_id, idobj$id, attname, attval, prec=prec, verbose=verbose, definemode=definemode ) if( verbose ) print('ncatt_put: back from ncatt_put_inner') } #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } if( verbose ) print('ncatt_put: exiting') } #=============================================================================================== # Writes a vector of values to a netCDF file. 'start' and 'count' # are given in R convention, i.e., starting at 1, and # in XYZT order. If they are omitted, the full array is written. # 'varid' can be the variable's name or an object of class ncvar4. # If varid is NA, then the "only" var in # the file is assumed to be the selected one. Values that are NA's # in the input data are converted to that variable's 'missing_value' # attribute before being written out to the file. # # Changs for netcdf-4: if varid is a ncvar object, then all is well. # Otherwise, if varid is a character string, it must be the fully # qualified var name. (Note that it could also be a DIMVAR name.) # ncvar_put <- function( nc, varid=NA, vals=NULL, start=NA, count=NA, verbose=FALSE, na_replace="fast" ) { if( verbose ) print('ncvar_put: entering') #if( class(nc) != 'ncdf4' ) if( ! inherits( nc, 'ncdf4' )) stop(paste("Error: first argument to ncvar_put must be an object of type ncdf,", "as returned by a call to nc_open(...,write=TRUE) or nc_create")) #--------------------------------------------- # Make sure the passed ncid is a writable file #--------------------------------------------- if( ! nc$writable ) stop(paste("Error: called with a nc object that is NOT a writable netcdf file! Passed nc file name:", nc$filename )) is_class_ncvar4 = ( inherits( varid, 'ncvar4' )) is_class_ncdim4 = ( inherits( varid, 'ncdim4' )) if( (mode(varid) != 'character') && ( ! is_class_ncvar4 ) && (! is_class_ncdim4 ) && (! is.na(varid))) stop(paste("Error: second argument to ncvar_put must be either an object of type ncvar,", "as returned by a call to ncvar_def, or the character-string name of a variable", "in the file. If there are multiple vars in the file with the same name (but", "in different groups), then the fully qualified var name must be given, for", "example, model1/run5/Temperature")) #----------------------------------------------------------------------------------- # Exactly why we do the following is obscure. Note that DIMVARS are not kept on # the 'variable' list for the file. So if we explicitly make a dimvar, then pass # that ncvar object to this routine, it will ordinarily fail because no 'var' # matching that dimvar will be found. This however works if we pass the NAME of # the dimvar, because that is matched on the dimvar list as well as the var list. # To avoid this error, we force all matches to be by name, rather than by var object #----------------------------------------------------------------------------------- #if( (class(varid) == 'ncvar4') || (class(varid) == 'ncdim4')) { if( is_class_ncvar4 || is_class_ncdim4 ) { varid = varid$name if( verbose ) print(paste("ncvar_put: converting passed ncvar4/ncdim4 object to the name:", varid)) } #---------------------------------------------------- # If we are running in safemode, must reopen the file # and renew the varid #---------------------------------------------------- if( nc$safemode ) { if(verbose) print(paste('ncvar_put: file is in safe mode, so reopening file', nc$filename)) nc$id = ncdf4_inner_open( nc ) c_varid_gid = ncvar_id_hier( nc$id, varid ) } if( is.null(vals)) stop("requires a vals argument to be set") if( verbose ) { if( mode(varid) == 'character') vname <- varid else vname <- varid$name print(paste("ncvar_put: entering, filename=", nc$filename, ' varname=', vname )) } #----------------------------------------------------------------- # Identify exactly what var (or dimvar) we will be putting data to #----------------------------------------------------------------- idobj = vobjtovarid4( nc, varid, allowdimvar=TRUE, verbose=verbose ) # NOTE: not a simple integer, but a ncid4 class object with $id, $group_index, $group_id, $list_index ncid2use = idobj$group_id varid2use = idobj$id varidx2use = idobj$list_index # this is the index into the nc$vars[[]] list that indictes this variable isdimvar = idobj$isdimvar if( nc$safemode ) { varid2use = c_varid_gid[1] ncid2use = c_varid_gid[2] } if( verbose ) print(paste('ncvar_put: writing to var (or dimvar) with id=',idobj$id, ' group_id=', idobj$group_id )) #----------------------------- # Check inputs for correctness #----------------------------- sm <- storage.mode(start) if( (sm != "double") && (sm != "integer") && (sm != "logical")) stop(paste("passed a start argument of storage mode",sm,"; can only handle double or integer")) sm <- storage.mode(count) if( (sm != "double") && (sm != "integer") && (sm != "logical")) stop(paste("passed a 'count' argument with storage mode '",sm,"'; can only handle double or integer", sep='')) #-------------------- # Prevent dumb errors #-------------------- if( ! nc$writable ) stop(paste("trying to write to file",nc$filename,"but it was not opened with write=TRUE")) varsize <- ncvar_size ( ncid2use, varid2use ) ndims <- ncvar_ndims( ncid2use, varid2use ) is_scalar = all(varsize == 1) && all(ndims == 0) if( verbose ) { print(paste("ncvar_put: varsize=")) print(varsize) print(paste("ncvar_put: ndims=", ndims)) print(paste("ncvar_put: is_scalar=", is_scalar )) } #-------------------------------------------------------- # Fix up start and count to use (in R convention for now) #-------------------------------------------------------- if( (length(start)==1) && is.na(start) ) { if( is_scalar ) start <- 1 else start <- rep(1,ndims) # Note: use R convention for now } else { if( length(start) != ndims ) stop(paste("'start' should specify",ndims, "dims but actually specifies",length(start))) } if( verbose ) { print("ncvar_put: using start=") print(start) } if( (length(count)==1) && is.na(count)) { count <- varsize - start + 1 } else { if( length(count) != ndims ) stop(paste("'count' should specify",ndims, "dims but actually specifies",length(count))) count <- ifelse( (count == -1), varsize-start+1, count) } if( verbose ) { print("ncvar_put: using count=") print(count) } #------------------------------ # Switch from R to C convention #------------------------------ c.start <- start[ ndims:1 ] - 1 c.count <- count[ ndims:1 ] #-------------------------------------------- # Change NA's to the variable's missing value #-------------------------------------------- if( verbose ) print("about to change NAs to variables missing value") if( isdimvar ) mv <- default_missval_ncdf4() else mv <- nc$var[[ varidx2use ]]$missval if( ! is.null(mv)) { ierr = 0 if( storage.mode( vals ) == "double" ) { if( na_replace == "safe" ) vals = vals + 0.0 # This triggers R to make a copy of vals, since vals is modified in the call below else if( na_replace != "fast" ) stop(paste("Error, argument na_replace must be either the string 'fast' or 'safe', but got:", na_replace )) rv <- .Call( "R_nc4_set_NA_to_val_double", vals, as.double(mv), PACKAGE="ncdf4" ) } else vals <- ifelse( is.na(vals), mv, vals) } #--------------------------------- # Get the correct type of variable #--------------------------------- precint <- ncvar_type( ncid2use, varid2use ) # 1=short, 2=int, 3=float, 4=double, 5=char, 6=byte, 7=ubyte, 8=ushort, 9=uint, 10=int64, 11=uint64, 12=string if( verbose ) print(paste("ncvar_put: Putting var of type",precint," (1=short, 2=int, 3=float, 4=double, 5=char, 6=byte, 7=ubyte, 8=ushort, 9=uint, 10=int64, 11=uint64, 12=string)")) #---------------------------------------------------------- # Sanity check to make sure we have at least as many values # in the data array as we are writing. Chars are a special # case because typically they are defined with an extra # "nchar" dim that is not included in the passed array. #---------------------------------------------------------- n2write <- prod(count) if( (precint != 5) && (length(vals) != n2write)) { if( length(vals) > n2write ) print(paste("ncvar_put: warning: you asked to write",n2write, "values, but the passed data array has",length(vals), "entries!")) else stop(paste("ncvar_put: error: you asked to write",n2write, "values, but the passed data array only has",length(vals), "entries!")) } rv <- list() rv$error <- -1 if( verbose ) { print("ncvar_put: calling C routines with C-style count=") print(c.count) print("and C-style start=") print(c.start) } if( (precint == 1) || (precint == 2) || (precint == 6) || (precint == 7) || (precint == 8) || (precint == 9)) { #-------------------------------------- # Short, Int, Byte, UByte, UShort, UInt #-------------------------------------- rv_error <- .Call("Rsx_nc4_put_vara_int", as.integer(ncid2use), as.integer(varid2use), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... as.integer(vals), PACKAGE="ncdf4") if( rv_error != 0 ) stop("C function Rsx_nc4_put_vara_int returned error") if( verbose ) print(paste("C function Rsx_nc4_put_vara_int returned", rv_error)) } else if( (precint == 3) || (precint == 4) || (precint == 10) || (precint == 11)) { #----------------------------------------------- # Float, double, 8-byte int, unsigned 8-byte int #----------------------------------------------- if( (precint == 10) || (precint == 11)) { print(paste(">>>> WARNING <<<< You are attempting to write data to a 8-byte integer,")) print(paste("but R does not have an 8-byte integer type. This is a bad idea! I will")) print(paste("TRY to write this by converting from double precision floating point, but")) print(paste("this could lose precision in your data!")) } rv_error <- .Call("Rsx_nc4_put_vara_double", as.integer(ncid2use), as.integer(varid2use), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... data=as.double(vals), PACKAGE="ncdf4") if( rv_error != 0 ) stop("C function Rsx_nc4_put_vara_double returned error") if( verbose ) print(paste("C function Rsx_nc4_put_vara_double returned", rv_error)) } else if( precint == 5 ) { #---------- # Character #---------- rv <- .C("R_nc4_put_vara_text", as.integer(ncid2use), as.integer(varid2use), as.integer(c.start), # Already switched to C convention... as.integer(c.count), # Already switched to C convention... data=as.character(vals), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("C function R_nc4_put_vara_text returned error") if( verbose ) print(paste("C function R_nc4_put_var_text returned", rv$error)) } else stop(paste("Internal error in ncvar_put: unhandled variable type=",precint,". Types I know: 1=short 2=int 3=float 4=double 5=char")) #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } if( verbose ) print('ncvar_put: exiting') } #=============================================================== # Returns data values from a netCDF file. 'start' and 'count' # are given in R convention, i.e., starting at 1, and # in XYZT order. If they are omitted, the full array is read in. # 'varid' can be the variable's name, an object of class ncvar4, # or the integer varid. 'varid' can also be omitted entirely, # in which case the only variable in the file is identified and # that one read in (if no such variable can be identified, an # error is generated). The 'count' array can have -1's, which # indicate that all the values in that dim are to be read (subject # to the start array). Missing values in the source file (i.e., # values that match that variable's 'missing_value' attribute) # are set to NA's. # Argument 'signedbyte' can be TRUE for bytes to be interpreted as # signed, or FALSE to be unsigned. # ncvar_get <- function( nc, varid=NA, start=NA, count=NA, verbose=FALSE, signedbyte=TRUE, collapse_degen=TRUE, raw_datavals=FALSE ) { #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("first argument (nc) is not of class ncdf4!") if( verbose ) print(paste("ncvar_get: entering for read from file", nc$filename)) is_class_ncvar4 = ( inherits( varid, 'ncvar4' )) is_class_ncdim4 = ( inherits( varid, 'ncdim4' )) if( (mode(varid) != 'character') && ( ! is_class_ncvar4) && ( ! is_class_ncdim4) && (! is.na(varid))) stop(paste("Error: second argument to ncvar_get must be an object of type ncvar or ncdim", "(both parts of the ncdf object returned by nc_open()), the character-string name of a variable or dimension", "or NA to get the default variable from the file. If the file is netcdf version 4", "format and uses groups, then the fully qualified var name must be given, for", "example, model1/run5/Temperature")) #---------------------------------------------------- # If we are running in safemode, must reopen the file #---------------------------------------------------- if( nc$safemode ) { if( verbose ) print(paste("ncvar_get: safemode opening file")) nc$id = ncdf4_inner_open( nc ) } idobj = vobjtovarid4( nc, varid, verbose=verbose, allowdimvar=TRUE ) have_start = (length(start)>1) || ((length(start)==1) && (!is.na(start))) have_count = (length(count)>1) || ((length(count)==1) && (!is.na(count))) #----------------------------------------------------------------- # If we have a start or count, they must not have any NA's in them #----------------------------------------------------------------- if( have_start ) { for( i in 1:length(start)) { if( is.na(start[i])) stop(paste("Error, passed a 'start' argument that has NA values:", paste(start,collapse=' ') )) } } if( have_count ) { for( i in 1:length(count)) { if( is.na(count[i])) stop(paste("Error, passed a 'count' argument that has NA values:", paste(count,collapse=' ') )) } } #--------------------------------------------------------------------- # Special check: if we are trying to get values from a dimvar, but the # dim does not have a dimvar, then just return 1:length(dim) #--------------------------------------------------------------------- if( idobj$isdimvar ) { if( verbose ) print(paste("ncvar_get: passed object is a dimvar")) if( idobj$id == -1 ) { # this happens if dim name was passed, but it has no dimvar #-------------------------------------------------------- # Here we return default integers for dims with no dimvar #-------------------------------------------------------- if( ! have_start ) start <- 1 if( ! have_count ) count <- nc$dim[[idobj$list_index]]$len if( count == 1 ) return( start ) else return( start:(start+count-1) ) } else { #----------------------------------------------------------- # Dimvars do not have list_index set, since dimvars do not # appear on the global var list. However, dimvars should # also not have missing values, addOffsets, or scaleFactors, # so this is easy #----------------------------------------------------------- return( ncvar_get_inner( idobj$group_id, idobj$id, default_missval_ncdf4(), start=start, count=count, verbose=verbose, signedbyte=signedbyte )) } } else { if( verbose ) print(paste("ncvar_get: passed object is NOT a dimvar")) } #-------------------------------------------- # Get var's missval, addOffset, and scaleFact #-------------------------------------------- if( verbose ) print(paste("ncvar_get: getting add offset and scale fact")) if( idobj$list_index == -1 ) { print("internal error: list_index for var is -1!") print("Here is passed varid:") print(varid) } li = idobj$list_index if( verbose ) { print(paste("ncvar_get: netcdf file index of var on list:", li)) print(paste("ncvar_get: here is var object:")) print(nc$var[[li]]) } if( nc$var[[li]]$hasAddOffset ) addOffset = nc$var[[li]]$addOffset else addOffset = 0; if( nc$var[[li]]$hasScaleFact ) scaleFact = nc$var[[li]]$scaleFact else scaleFact = 1.0; if( verbose ) print(paste("ncvar_get: addOffset=", addOffset, "scaleFact=", scaleFact )) ncid2use = idobj$group_id varid2use = idobj$id if( verbose ) print(paste("ncvar_get: ncid2use=", ncid2use, "varid2use=", varid2use, "missval=", nc$var[[li]]$missval )) #----------------------------------------------------------- # If we are in safe mode, must renew our group id and var id #----------------------------------------------------------- if( nc$safemode ) { if(verbose) print(paste('ncvar_get: file is in safe mode, so reopening file', nc$filename)) nc$id = ncdf4_inner_open( nc ) c_varid_gid = ncvar_id_hier( nc$id, nc$var[[li]]$name ) varid2use = c_varid_gid[1] ncid2use = c_varid_gid[2] if(verbose) print(paste('ncvar_get: safe mode renewed ncid, varid2use:', ncid2use, varid2use )) } rv = ncvar_get_inner( ncid2use, varid2use, nc$var[[li]]$missval, addOffset, scaleFact, start=start, count=count, verbose=verbose, signedbyte=signedbyte, collapse_degen=collapse_degen, raw_datavals=raw_datavals ) #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( nc$safemode ) { trv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } return( rv ) } #==================================================================================================== nc_sync <- function( nc ) { is_numeric = FALSE if( is.numeric(nc)) { ncid2use <- nc is_numeric = TRUE } else if( inherits( nc, 'ncdf4' )) ncid2use <- nc$id else stop("First argument must be a simple integer ID or an object of class ncdf4, as returned by nc_open() or nc_create()") #-------------------------------------------------------- # If we are running in safemode, this call is meaningless # since the file is closed every time anyway #-------------------------------------------------------- if( (! is_numeric) && nc$safemode ) return() rv = .C("R_nc4_sync", as.integer(ncid2use), PACKAGE="ncdf4") } #=============================================================== nc_redef <- function( nc ) { ignore_safemode = TRUE numeric_id = FALSE if( is.numeric(nc)) { numeric_id = TRUE ncid2use <- nc } else if( inherits( nc, 'ncdf4' )) ncid2use <- nc$id else stop("First argument must be a simple integer ID or an object of class ncdf4, as returned by nc_open() or nc_create()") #-------------------------------------------------------- # If we are running in safemode, this call is meaningless # since the file is closed every time anyway #-------------------------------------------------------- if( (! numeric_id) && nc$safemode && (! ignore_safemode)) { print('****** W A R N I N G *****') print('You have called nc_redef on a file that is in safemode. In safemode, which is') print('REQUIRED for Windows-64, the file is closed after every access. This is a workaround') print('for a bug in the netcdf library under Windows-64. Therefore, redef has no meaning.') return() } rv = .C("R_nc4_redef", as.integer(ncid2use), PACKAGE="ncdf4") } #=============================================================== nc_enddef <- function( nc ) { ignore_safemode = TRUE numeric_id = FALSE if( is.numeric(nc)) { ncid2use <- nc numeric_id = TRUE } else if( inherits( nc, 'ncdf4' )) ncid2use <- nc$id else stop("First argument must be a simple integer ID or an object of class ncdf4, as returned by nc_open() or nc_create()") #-------------------------------------------------------------------------------- # Has no meaning if we are in safemode since the file is closed every time anyway #-------------------------------------------------------------------------------- if( ! numeric_id ) { if( nc$safemode && (! ignore_safemode)) return() } rv = list( error=0 ) rv = .C("R_nc4_enddef", as.integer(ncid2use), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) return( -1 ) nc_sync( nc ) return( 0 ) } #=============================================================== nc_close <- function( nc ) { #-------------------------------------------------------------------------------- # Has no meaning if we are in safemode since the file is closed every time anyway #-------------------------------------------------------------------------------- if( nc$safemode ) { return() } if( inherits( nc, 'ncdf4' )) ncid2use <- nc$id else stop("First argument must be an object of class ncdf4, as returned by nc_open() or nc_create()") rv = .C("R_nc4_close", as.integer(ncid2use), PACKAGE="ncdf4") #---------------------------------------------------------------------------- # Following is taken from a posting by Simon Fear # to the R-help newslist on Thu, 19 Feb 2004 10:11:50 -0000 #---------------------------------------------------------------------------- #eval(eval(substitute(expression(nc$id <<- -1)))) # set id of CALLING object to -1 } #=========================================================================================== # Inputs old_varname and new_varname are character strings. If you are renaming a # var in a group, then they both must be fully qualified varnames with the same # number of forward slashes. # # Useage: # ncid <- ncvar_rename( ncid, 'oldname', 'newname' ) # ncvar_rename <- function( nc, old_varname, new_varname, verbose=FALSE ) { #-------------------------- # Check inputs for validity #-------------------------- if( ! inherits( nc, 'ncdf4' )) stop("Error, ncvar_rename passed something NOT of class ncdf4!") if( ! is.character(old_varname)) stop("Error, ncvar_rename must be passed the old varname as a character string") if( ! is.character(new_varname)) stop("Error, ncvar_rename must be passed the new varname as a character string") if( nslashes_ncdf4(old_varname) != nslashes_ncdf4(new_varname)) stop("Error, if fully qualified names are passed for the old and new varnames (to rename a variable in a group), then the number of worward slashes in the old and new varnames must be the same") vid <- vobjtovarid4( nc, old_varname, verbose=verbose ) # Remember, an object of class ncid4, not a simple integer if( vid$list_index == -1 ) stop("Sorry, there was an error trying to rename the variable. Are you trying to rename a dimvar? That is not currently supported.") oldname <- ncvar_name( vid$group_id, vid$id ) def_mode <- FALSE if( nchar(new_varname) > nchar(oldname)) { #nc_redef( nc, ignore_safemode=TRUE ) # Go back into define mode nc_redef( nc ) # Go back into define mode def_mode <- TRUE } bn_new_varname = nc4_basename( new_varname ) #---------------------------------------------------- # If we are running in safemode, must reopen the file #---------------------------------------------------- if( nc$safemode ) nc$id = ncdf4_inner_open( nc ) rv <- list() rv$error <- -1 rv <- .C("R_nc4_rename_var", as.integer(vid$group_id), as.integer(vid$id), bn_new_varname, error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop("error returned from C call") if( def_mode ) { #nc_enddef( nc, ignore_safemode=TRUE ) if( nc_enddef( nc ) != 0 ) { stop(paste("Error, nc_enddef returned an error! old, new varnames:", old_varname, new_varname )) } } #-------------------------------------------------------------- # Update our netcdf class structure to reflect the changed name #-------------------------------------------------------------- idx <- vid$list_index nc$var[[idx]]$name <- new_varname #---------------------------------------------------------------- # If we are running in safe mode, close the file before returning #---------------------------------------------------------------- if( nc$safemode ) { rv = .C("R_nc4_close", as.integer(nc$id), PACKAGE="ncdf4") nc$id = -1 # invalidate this ID since it's not valid any more (duh) } return(nc) } ncdf4/R/ncdf4_priv_dim.R0000644000176200001440000002427514377671533014515 0ustar liggesusers #=============================================================== ncdim_same <- function( d1, d2 ) { #if( class(d1) != "ncdim4" ) if( ! inherits( d1, 'ncdim4' )) stop("error, class of first passed argument is not ncdim!") #if( class(d2) != "ncdim4" ) if( ! inherits( d2, 'ncdim4' )) stop("error, class of first passed argument is not ncdim!") if( d1$name != d2$name ) return(FALSE) if( d1$len != d2$len ) return(FALSE) if( d1$unlim != d2$unlim ) return(FALSE) return(TRUE) } #==================================================================================================== # This is the private interface that actually does the # netCDF calls. User code should never go through this. # To make a ncdim object, use ncdim_def() instead. # This makes BOTH the dim AND the dimvar (and RETURNS # dimid AND dimvarid). # ncdim_create <- function( nc, d, verbose=FALSE ) { #if( class(nc) != "ncdf4" ) if( ! inherits( nc, 'ncdf4' )) stop("ncdim_create: passed nc NOT of class ncdf4!") if( verbose ) print(paste("ncdim_create: entering for ncid=",nc$id)) #if( class(d) != "ncdim4" ) if( ! inherits( d, 'ncdim4' )) stop("ncdim_create: passed d NOT of class ncdim4!") if( verbose ) print(paste("ncdim_create: entering for dim",d$name)) #----------------------------------------------------------------------- # Figure out the ncid to use. If this dim is in the root group, it will # just be the ncid. Otherwise, it will be the group id #----------------------------------------------------------------------- if( nslashes_ncdf4( d$name ) == 0 ) gidx <- 1 else { dims_fqgn <- nc4_basename( d$name, dir=TRUE ) gidx <- nc$fqgn2Rindex[[ dims_fqgn ]] if( is.null(gidx)) stop(paste("ncdim_create internal error: did not find dim's fully qualified group name '", dims_fqgn, "' in list of groups for file ", nc$filename, sep='')) } ncid2use <- nc$group[[gidx]]$id #------------------- # Make the dimension #------------------- ncdim <- list() ncdim$error <- -1 ncdim$id <- -1 # this is only briefly an integer, changed to ncid object below sizetouse <- d$len name2use <- nc4_basename( d$name ) if( d$unlim ) sizetouse <- 0 if( verbose ) print(paste("ncdim_create: about to call R_nc4_def_dim with ncid2use=", ncid2use, " NOT fully qualified dim name=",name2use)) ncdim<-.C("R_nc4_def_dim", as.integer(ncid2use), as.character(name2use), as.integer(sizetouse), id=as.integer(ncdim$id), error=as.integer(ncdim$error), PACKAGE="ncdf4") if( ncdim$error != 0 ) stop("Error in dim.create.ncdf!") #------------------------------------------------------ # NOTE that ncdim$id is just an ORDINARY INTEGER, not a # ncid object! The 'ncdim' structure is not returned, # it's just used locally in this routine. #------------------------------------------------------ #----------------------------- # Make the dimvar if requested #----------------------------- dimvar<-list() if( d$create_dimvar ) { if( verbose ) print(paste("ncdim_create: making dimvar for dim",d$name)) dimvar$id <- -1 # this is only briefly an integer, changed to ncid object below dimvar$error <- -1 if( storage.mode(d$vals) == "integer" ) { if( verbose ) print(paste("ncdim_create: about to call R_nc4_def_var_int for dimvar",name2use)) dimvar<-.C("R_nc4_def_var_int", as.integer(ncid2use), as.character(name2use), as.integer(c(1)), as.integer(ncdim$id), id=as.integer(dimvar$id), error=as.integer(dimvar$error), PACKAGE="ncdf4") } else { if( verbose ) print(paste("ncdim_create: about to call R_nc4_def_var_double for dimvar",name2use)) dimvar<-.C("R_nc4_def_var_double", as.integer(ncid2use), as.character(name2use), as.integer(c(1)), as.integer(ncdim$id), id=as.integer(dimvar$id), error=as.integer(dimvar$error), PACKAGE="ncdf4") } if( dimvar$error != 0 ) stop("Error defining dimvar in routine dim.create.ncdf") #------------------------------------------------------- # NOTE that dimvar$id is just an ORDINARY INTEGER, not a # ncid object! The 'dimvar' structure is not returned, # it's just used locally in this routine. #------------------------------------------------------- #--------------------------------- # Put in the dimvals as specified. #--------------------------------- #nc_enddef( nc, ignore_safemode=TRUE ) # Must exit define mode for this if( nc_enddef( nc ) != 0 ) { stop(paste("Error, nc_enddef returned an error when trying to ncdim_create dim named", d$name )) } rv <- list() rv$error <- -1 start <- 0 # Use C convention count <- length(d$vals) if( count > 0 ) { if( storage.mode(d$vals) == "integer" ) { if( verbose ) print(paste("ncdim_create: about to call R_nc4_put_vara_int dimvals for dimvar",d$name, ' ncid=', as.integer(ncid2use), ' dimvarid=', as.integer(dimvar$id), ' start=', paste(as.integer(start),collapse=' '), ' count=', paste(as.integer(count),collapse=' '))) rv_error <- .Call("Rsx_nc4_put_vara_int", as.integer(ncid2use), as.integer(dimvar$id), as.integer(start), as.integer(count), as.integer(d$vals), PACKAGE="ncdf4") } else if( storage.mode(d$vals) == "double" ) { if( verbose ) print(paste("ncdim_create: about to call Rsx_nc4_put_vara_double dimvals for dimvar",d$name)) rv_error <- .Call("Rsx_nc4_put_vara_double", as.integer(ncid2use), as.integer(dimvar$id), as.integer(start), as.integer(count), as.double(d$vals), PACKAGE="ncdf4") } else stop(paste("ncdim_create: unknown storage mode:",storage.mode(d$vals),"for dim",d$name)) if( rv_error != 0 ) { print("Error in ncdim_create, while writing dimvar values!") print("Here is the dim structure I was passed that triggered the error:") print(paste("name=", d$name )) print(paste("len=", d$len )) print(paste("unlim=", d$unlim )) stop('fatal error in ncdf4_priv_dim.R::ncdim_create') } } #nc_redef( nc, ignore_safemode=TRUE ) # Go back into define mode nc_redef( nc ) #---------------------------------------------------- # Set the dimension's (dimvar's, actually) attributes #---------------------------------------------------- if( (! is.null(d$units)) && (nchar(d$units)>0)) ncatt_put_inner( ncid2use, dimvar$id, "units", d$units, definemode=TRUE, verbose=verbose ) if( (! is.null(d$longname)) && (nchar(d$longname)>0)) ncatt_put_inner( ncid2use, dimvar$id, "long_name", d$longname, definemode=TRUE, verbose=verbose ) if( (! is.null( d$calendar )) && (nchar(d$calendar)>0)) ncatt_put_inner( ncid2use, dimvar$id, "calendar", d$calendar, definemode=TRUE, verbose=verbose ) } # end of "if(create_dimvar)" else { if( verbose ) print(paste("ncdim_create: NOT making dimvar for dim",d$name)) #---------------------------------------------------------- # if we were NOT asked to create the dimvar (via an empty # units string) than make sure NO dim values were specified # except simple integers from 1 to len! #---------------------------------------------------------- if( (storage.mode( d$vals ) != "integer" ) || (d$vals[1] != 1) || (d$vals[d$len] != d$len)) stop(paste("Error trying to create dimension named",d$name,": the passed units string", "was empty, which indicates that NO dimensional variable is to be created.", "In this case, the dimension values MUST be simple integers from 1 to the length", "of the dimension (e.g., 1:len)")) dimvar$id = -1 } if( verbose ) print(paste("ncdim_create: exiting for ncid=",nc$id," dim=",d$name)) #---------------------------------------------- # Return the dimvar ID of the newly created dim #---------------------------------------------- return(c(ncdim$id,dimvar$id,ncid2use,gidx)) } #=============================================================== # NOTE that this does NOT return a full-fledged "ncdim" object, # it is the lower-level interface and only returns the portions # of a ncdim object that directly correspond to a real netCDF # dimension. The ncdim object, by contrast, also has information # from the dimvar. # # Internal use only. # ncdim_inq <- function( ncid, dimid ) { #------------------------------------------------------ # This is a string NC_MAX_LEN long, to provide storage. # I'm not sure if this is needed or not.... #------------------------------------------------------ str.nc.max.name <- "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" rv <- list() rv$dimname <- str.nc.max.name rv$dimlen <- -1 rv$error <- -1 rv$unlim <- 0 rv <- .C("R_nc4_inq_dim", as.integer(ncid), as.integer(dimid), dimname=as.character(rv$dimname), dimlen=as.integer(rv$dimlen), unlim=as.integer(rv$unlim), error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) { stop(paste("using ncid ",ncid," dimid ",dimid)) } d <- list() d$name <- rv$dimname d$len <- rv$dimlen d$unlim <- (rv$unlim == 1) return(d) } #=============================================================== # Internal use only # # Returns -1 if the dim is NOT found in the file or group, and the # dimid of the dim otherwise. # ncdim_id <- function( nc, dimname ) { if( mode(nc) != 'numeric' ) stop("error, must be passed a numeric first arg: ncid2use") if( mode(dimname) != 'character' ) stop("Error, must be passed a character second arg: dimname" ) rv <- list() rv$dimid <- -1 rv <- .C("R_nc4_inq_dimid", as.integer(nc), as.character(dimname), dimid=as.integer(rv$dimid), PACKAGE="ncdf4") if( rv$dimid != -1 ) rv$dimid <- rv$dimid return(rv$dimid) } #=============================================================== # Internal use only # # Returns -1 if the dim is NOT found in the file or group, and the # length of the dim otherwise. # ncdim_len <- function( nc, dimname ) { if( mode(nc) != 'numeric' ) stop("error, must be passed a numeric first arg: ncid2use") if( mode(dimname) != 'character' ) stop("Error, must be passed a character second arg: dimname" ) rv <- list() rv$dimlen <- -1 rv <- .C("R_nc4_inq_dimlen", as.integer(nc), as.character(dimname), dimlen=as.integer(rv$dimlen), PACKAGE="ncdf4") return(rv$dimlen) } ncdf4/R/ncdf4_priv.R0000644000176200001440000002406014531204502013630 0ustar liggesusers# This provides an interface to netCDF-4 functions. As a general # comment, awkwardness arises from two things: # 1. R starts counting at 1, and netCDF counting # starts at 0. # 2. R array subscripts go in Fortran order (XYZT), # while netCDF subscripts go in C order (TZYX). # We take care of these problems EXCLUSIVELY in the R code, # NOT in the C interface code!!! This means that it is # always the responsibility of the R program to take these # differences into account. From the point of view of an # R program that calls any of these functions, they are # strictly R compliant (Fortran order, counting starts at 1). # # David W. Pierce # Climate Research Division # Scripps Institution of Oceanography # dpierce@ucsd.edu # 9-April-2001 # #----------------------------------------------------------------- # Netcdf-version 4 notes. # Not much needs to be changed in the interface to make it work # for netcdf version 4. Basically, if you have a slash in the # variable or dim name, such as "models/Temperature", then "models" # is a group that will be auto-created as necessary. Same goes # for dims. #----------------------------------------------------------------- # # Here are the relevant objects: # # class: ncdf4 is a list with the following fields: # filename: name of the file, or "IN-MEMORY" # id : netcdf file id # ndims : integer # of dims in the file # nvars : integer # of vars in the file that are **NOT** dimvars # natts : integer # of global attributes # group : list of groups in the file. group[[1]] is always the root group # ngroups : integer # of groups; will always be at least 1, indicating the root group; # this is just length(group) # dim : a list of ncdim objects # var : a list of ncvar objects # varid2Rindex : for internal use only; maps a numeric varid stright # from the netcdf file to which element in the list of vars this var is. # writable: TRUE or FALSE # # class: ncdim4 (returned by dim.def.ncdf, which creates a NEW # netCDF dimension in memory, and part of the list of dims # in a ncdf object. NOTE that this is NOT what is returned # by ncdim_inq, which is the low-level netCDF dim, not # the user-level R version of a netCDF dim. # * name : character dim name # units : character units in udunits format. # vals : a vector of dimension values # * len : size of this dimension # calendar : if the dimvar has a 'calendar' attribute, this holds its value # id : NEW IN VERION 4: this is an opaque object of type 'ncdimid' # dimvarid: IFF this dim corresponds to a netCDF dim in an existing file, # then this field will hold the dimvarid, or -1 if no dimvar. # * unlim : boolean, T or F to indicated unlimited or not # create_dimvar : usually TRUE; if FALSE, then no dimvar will be created, # AND the units string must be empty, AND the values must # be simple integers from 1 to the length of the dim. # longname : the 'long_name' attribute for the DIMVAR, or defaults to # name if there is no dimvar, OR the long_name attribute # is not set. # # *=Indicates element is filled out by the low-level routine 'ncdim_inq'. # Other elements are filled out in 'open.ncdf'. # # # class: ncvar4 (returned by var.def.ncdf, which creates a NEW # netCDF variable in memory, and part of the list of vars # in a ncdf object. NOTE that this is NOT what is # returned by ncvar_inq, which is the low-level netCDF # var, NOT the user-level R version of a netCDF var. # name : character var name # units : character units in udunits format # missval : the 'missing_value' attribute, or defaults to default_missval_ncdf4(). NOTE: # if the var has no missing value then this is 'NA'. This does not mean # that the missing value is NA -- the missing value cannot be NA. It means # the variable has no missing value. For instance, character variables have # no default missing value. # longname: the 'long_name' attribute, or defaults to name # id : the varid of this variable, IFF it is in a file already # ndims : number of dims this variable has # dim : a list of type ncdim, which is this variable's dims # unlim : boolean, T if this var has an unlimited dim, F otherwise # varsize : a convenience array that gives the (X,Y,Z,T) size of # the variable. # prec : The precision of the ON-DISK representation of the # variable. Can be "byte", "short", "float", "double", # "integer", or "char". # natts : integer # of this variable's attributes # # class: vals.ncdf (returned by ncvar_get) # xvals, yvals, zvals, tvals: the dimensional values, as appropriate # vals : the data values # #================================================================= # Needed because the simpler construction # # for( i in 1:n ) # # fails if n==0. Instead, use # # for( i in nc4_loop(1,n) ) # # if there is any possibility that n can be zero. # nc4_loop <- function( a, b ) { if( b < a ) return(NULL); return( a:b ); } #================================================================= # Given a name of the form "dir/dir/file", or # "/dir/dir/file", or "file", or "/file", this # returns the dirname (stuff before the file) or # basename (filename). This version does not # strip suffixes from filenames, as I don't need # that functionality. # # Input string dir=FALSE dir=TRUE # ------------ --------- --------- # /dir1/fname fname /dir1 # /dir1/dir2/fname fname /dir1/dir2 # dir1/fname fname dir1 # dir1/dir2/fname fname dir1/dir2 # /fname fname "" (empty string) # fname fname "" (empty string) # nc4_basename <- function( nam, dir=FALSE ) { if( ! dir ) { ss <- strsplit( nam, '/' ) ns <- length( ss[[1]] ) return( ss[[1]][ns] ) } #------------------------------ # If get here, doing 'dir=TRUE' #------------------------------ nmax <- nchar( nam ) nslash <- 0 slashloc <- array(0,nmax) for( i in 1:nchar(nam)) { if( substr( nam, i, i ) == '/' ) { nslash <- nslash + 1 slashloc[nslash] <- i } } if( nslash == 0 ) return( "" ) return( substr( nam, 1, slashloc[nslash]-1 )) } #================================================================= # Utility to return a streng of length 'n'; this is used for storage # blankstring_ncdf4 <- function( n ) { rv <- .Call("R_nc4_blankstring", as.integer(n), PACKAGE="ncdf4") return( rv ) } #================================================================= # This is where the default missing value for vars is set. # default_missval_ncdf4 <- function() { return(1.e30) } #================================================================= # Returns the number of forward slash characters ("/") in a name # nslashes_ncdf4 <- function( nam ) { nfs <- 0 # number of forward slashes for( ic in nc4_loop(1,nchar(nam)) ) if( substr(nam,ic,ic) == '/' ) nfs <- nfs + 1 return( nfs ) } #=============================================================== # In netcdf v4, there can be multiple vars with the # same name and same ID, if they are in different groups. So # we have to have a more complex object for the var "ID" than just # a simple integer. Note that this does not seem to be true for # dims, which, as far as I can tell, are numbered consecutively # throughout a netcdf file that has groups. # # Elements: # id: the integer varid or dimid to use when calling the # C routines to access the dim/var WITH THE CORRECT GROUP ID # group_id: the group ID to use when accessing the C routines to # manipulate this dim or var # group_index: the index in to the nc$group list for the group where # this dim or var lives # list_index: this is a number N, between 1 and nc$nvars (if for a # variable) or between 1 and nc$ndims (if for a dim) # that shows the entry of this dim/var on the overall # ncdf $var or $dim list. For example, if list_index==3 # for a variable, then nc$var[[3]] is the variable we # are talking about. # isdimvar: TRUE if a dimvar, FALSE otherwise # # Note that none of these is valid until the dim or var is # actually created on disk; this is indicted by the default vals # of -1. # ncdf4_make_id <- function( id=-1, group_index=-1, group_id=-1, list_index=-1, isdimvar=FALSE ) { retval <- list( id=id, group_index=group_index, group_id=group_id, list_index=list_index, isdimvar=isdimvar ) class(retval) <- 'ncid4' return( retval ) } #====================================================================================== # Given a netcdf ID, returns the netcdf format. Values here MUST MATCH THE VALUES # COMPILED INTO THE C CODE, file ncdf.c, routine R_nc4_inq_format, about line 1123 # or so. # ncdf4_format <- function( root_id ) { if( ! is.integer(root_id)) root_id <- as.integer( root_id + 0.1 ) ierr <- as.integer(-1) rv <- .Call( "R_nc4_inq_format", as.integer(root_id), ierr, PACKAGE="ncdf4" ) if( ierr != 0 ) { stop(paste("Error in nc_grpname, encountered when root_id=",root_id)) } if( rv == 1 ) return( 'NC_FORMAT_CLASSIC' ) else if( rv == 2 ) return( 'NC_FORMAT_64BIT' ) else if( rv == 3 ) return( 'NC_FORMAT_NETCDF4' ) else if( rv == 4 ) return( 'NC_FORMAT_NETCDF4_CLASSIC' ) else if( rv == 5 ) return( 'NC_FORMAT_CDF5' ) else stop(paste("C call R_nc4_inq_format returned value",rv,"which is not recognized")) } #========================================================================================== # A simple and direct file opener, given a netcdf4 object "nc". Used as part of safemode. # Returns integer ncid. # ncdf4_inner_open = function( nc ) { #if( class( nc ) != 'ncdf4' ) if( ! inherits( nc, 'ncdf4' )) stop(paste("ncdf4 library: internal error: ncdf4_inner_open called with an object that is NOT class ncdf4!")) rv <- list() if( is.null(nc$writable)) stop(paste("Internal error: ncdf4_inner_open called with no $writable element on file", nc$filename)) if( nc$writable ) rv$cmode <- 1 else rv$cmode <- 0 rv$id <- -1 rv$error <- -1 rv <- .C("R_nc4_open", as.character(nc$filename), as.integer(rv$cmode), # write mode=1, read only=0 id=as.integer(rv$id), # note: nc$id is the simple integer ncid of the base file (root group in the file) error=as.integer(rv$error), PACKAGE="ncdf4") if( rv$error != 0 ) stop(paste("Error in nc_open trying to open file",nc$filename)) return( rv$id ) } ncdf4/MD50000644000176200001440000000402514531443302011560 0ustar liggesusers534ba1f8d0e8caec9388f0a74d25e271 *ChangeLog b58a3aa8f60ac4247a97c36bdd50893a *DESCRIPTION 36c1fbaaed8bc2fb94337130abd73011 *NAMESPACE 3c3166bd24be7e2b71a25a6c6bd92937 *R/ncdf4.R d4a8afa839a1b5ecc1f3cfb129de9e40 *R/ncdf4_priv.R ad1f30d6431d4acc6ed2a3da2047e35f *R/ncdf4_priv_att.R 20946d389a779bc4ab8b31f9b3d56038 *R/ncdf4_priv_dim.R f8465510853d66aad16c8e4d4867bfec *R/ncdf4_priv_group.R b57fcbe68b987235980f0c55f0213ffe *R/ncdf4_priv_var.R 375cb891a49b0b7c57a1aff35daf1193 *cleanup d166b74624cd62256b6491b849d5e3ee *configure dd3bd371bb3102f9346afb7a1fc144fd *configure.ac a06df3f633622526b02785e5442b4835 *inst/HDF5_COPYING 11abb9105fa22029de3829b88fdb47ac *man/ancvar_put.Rd b256db50eaf9b1638ae3badef997ac4a *man/nc_close.Rd f356151c969e40edd6c4a89b54808d5b *man/nc_create.Rd da08df27b94adc4bd9fa14cf89c59df8 *man/nc_enddef.Rd 0dd9e093c9600032499b62b6dd49a326 *man/nc_open.Rd e22c2c657dc2283af261991673816c3c *man/nc_redef.Rd a3426766cc750be3467966a3ff4fbffe *man/nc_sync.Rd c4eff28d1e3c26db9d9c498ee1df3149 *man/nc_version.Rd 3229238db9b6df447805d2091b4775e3 *man/ncatt_get.Rd 7c60ab5ac8abe7500b284b82b34474b3 *man/ncatt_put.Rd b01b80f58dd5bb845366a7596747ce5a *man/ncdf4-internal.Rd 25e8de8a3078221e381196b74fc26e8a *man/ncdf4-package.Rd 31d674bde90c1e353bc54e2abdc792ac *man/ncdim_def.Rd 5a045bf701b006b267ca5d5f448c64b9 *man/ncvar_add.Rd 6040d49afcc3a1c4d9816f12523cc1e6 *man/ncvar_change_missval.Rd c0a57d55856cb017d743c2700dd56e27 *man/ncvar_def.Rd 7048e43ec1f69349f08c884fa71fd6ce *man/ncvar_get.Rd 49f06adb81a4b723a850397b4316fb9b *man/ncvar_rename.Rd 5b3232754db0831fcc725c3e2d8c7552 *man/print.ncdf4.Rd 78d681e25a4cad63030a0de445d13fa5 *src/Makevars.in 5b39044dba4ecd2483635c18317c001a *src/Makevars.ucrt a4c6502d32145531debeff453406b6cf *src/Makevars.win 5963251c7446d6670931a7a8b6ab4cc8 *src/ncdf.c b4d36900efe0d6045f65d132445a9b6d *tools/aclocal.m4 dd3bd371bb3102f9346afb7a1fc144fd *tools/configure.ac c385dcbf01f753e75aee4c5db9a66337 *tools/netcdf.m4 f695d66e71d8028902b4801b5ecb5023 *tools/regenerate 2dfd9d1ed07c40cd694379210383ebac *tools/winlibs.R ncdf4/inst/0000755000176200001440000000000014377671533012245 5ustar liggesusersncdf4/inst/HDF5_COPYING0000644000176200001440000001110514377671533014044 0ustar liggesusers Copyright Notice and License Terms for HDF5 (Hierarchical Data Format 5) Software Library and Utilities ----------------------------------------------------------------------------- HDF5 (Hierarchical Data Format 5) Software Library and Utilities Copyright 2006-2012 by The HDF Group. NCSA HDF5 (Hierarchical Data Format 5) Software Library and Utilities Copyright 1998-2006 by the Board of Trustees of the University of Illinois. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted for any purpose (including commercial purposes) provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or materials provided with the distribution. 3. In addition, redistributions of modified forms of the source or binary code must carry prominent notices stating that the original code was changed and the date of the change. 4. All publications or advertising materials mentioning features or use of this software are asked, but not required, to acknowledge that it was developed by The HDF Group and by the National Center for Supercomputing Applications at the University of Illinois at Urbana-Champaign and credit the contributors. 5. Neither the name of The HDF Group, the name of the University, nor the name of any Contributor may be used to endorse or promote products derived from this software without specific prior written permission from The HDF Group, the University, or the Contributor, respectively. DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE HDF GROUP AND THE CONTRIBUTORS "AS IS" WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. In no event shall The HDF Group or the Contributors be liable for any damages suffered by the users arising out of the use of this software, even if advised of the possibility of such damage. ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- Contributors: National Center for Supercomputing Applications (NCSA) at the University of Illinois, Fortner Software, Unidata Program Center (netCDF), The Independent JPEG Group (JPEG), Jean-loup Gailly and Mark Adler (gzip), and Digital Equipment Corporation (DEC). ----------------------------------------------------------------------------- Portions of HDF5 were developed with support from the Lawrence Berkeley National Laboratory (LBNL) and the United States Department of Energy under Prime Contract No. DE-AC02-05CH11231. ----------------------------------------------------------------------------- Portions of HDF5 were developed with support from the University of California, Lawrence Livermore National Laboratory (UC LLNL). The following statement applies to those portions of the product and must be retained in any redistribution of source code, binaries, documentation, and/or accompanying materials: This work was partially produced at the University of California, Lawrence Livermore National Laboratory (UC LLNL) under contract no. W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy (DOE) and The Regents of the University of California (University) for the operation of UC LLNL. DISCLAIMER: This work was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor the University of California nor any of their employees, makes any warranty, express or implied, or assumes any liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately- owned rights. Reference herein to any specific commercial products, process, or service by trade name, trademark, manufacturer, or otherwise, does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or the University of California. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or the University of California, and shall not be used for advertising or product endorsement purposes. ----------------------------------------------------------------------------- ncdf4/cleanup0000755000176200001440000000010714531435002012620 0ustar liggesusers#! /bin/sh rm -f config.* R/load.R src/Makevars rm -rf autom4te.cache ncdf4/configure0000755000176200001440000035257114531435002013171 0ustar liggesusers#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/Makevars.in" ac_subst_vars='OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC LTLIBOBJS LIBOBJS HAVE_NETCDF NETCDF_RPATH NETCDF_CC NETCDF_VERSION NETCDF_LIBS NETCDF_LDFLAGS NETCDF_CPPFLAGS HAS_NC_CONFIG target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_nc_config ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-nc-config=path to nc-config script from netcdf v4 package Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "configure.ac: starting" : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then echo "Could not determine R_HOME" exit 1 fi #--------------------------------------------------------------------------- # The way R's package installation mechanism works, the C compiler and flags # are set by R, and not changable at the package level. So this is really # just for information purposes. Changing these values will NOT result in # a different compiler being used!! #--------------------------------------------------------------------------- CC=`${R_HOME}/bin/R CMD config CC` CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS` # for ncdf4, I've chosen to REQUIRE the netcdf v4 interface # Check whether --with-nc_config was given. if test "${with_nc_config+set}" = set; then : withval=$with_nc_config; NC_CONFIG=$withval fi err=0 if test x$NC_CONFIG = x; then NC_CONFIG_SHORT=nc-config NC_CONFIG_FULLQUAL=nc-config NC_CONFIG_PATH=$PATH else echo "user specified nc-config is $NC_CONFIG" NC_CONFIG_SHORT=`basename $NC_CONFIG` NC_CONFIG_FULLQUAL=$NC_CONFIG NC_CONFIG_PATH=`dirname $NC_CONFIG` fi # Extract the first word of "$NC_CONFIG_SHORT", so it can be a program name with args. set dummy $NC_CONFIG_SHORT; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_HAS_NC_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$HAS_NC_CONFIG"; then ac_cv_prog_HAS_NC_CONFIG="$HAS_NC_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $NC_CONFIG_PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_HAS_NC_CONFIG="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_HAS_NC_CONFIG" && ac_cv_prog_HAS_NC_CONFIG="no" fi fi HAS_NC_CONFIG=$ac_cv_prog_HAS_NC_CONFIG if test -n "$HAS_NC_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_NC_CONFIG" >&5 $as_echo "$HAS_NC_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x$HAS_NC_CONFIG = xno; then echo "-----------------------------------------------------------------------------------" echo "Error, nc-config not found or not executable. This is a script that comes with the" echo "netcdf library, version 4.1-beta2 or later, and must be present for configuration" echo "to succeed." echo " " echo "If you installed the netcdf library (and nc-config) in a standard location, nc-config" echo "should be found automatically. Otherwise, you can specify the full path and name of" echo "the nc-config script by passing the --with-nc-config=/full/path/nc-config argument" echo "flag to the configure script. For example:" echo " " echo "./configure --with-nc-config=/sw/dist/netcdf4/bin/nc-config" echo " " echo "Special note for R users:" echo "-------------------------" echo "To pass the configure flag to R, use something like this:" echo " " echo "R CMD INSTALL --configure-args=\"--with-nc-config=/home/joe/bin/nc-config\" ncdf4" echo " " echo "where you should replace /home/joe/bin etc. with the location where you have" echo "installed the nc-config script that came with the netcdf 4 distribution." echo "-----------------------------------------------------------------------------------" exit -1 fi echo "Using nc-config: $NC_CONFIG_FULLQUAL" echo "Output of nc-config --all:" $NC_CONFIG_FULLQUAL --all echo "---" NETCDF_CC=`$NC_CONFIG_FULLQUAL --cc` NETCDF_LDFLAGS=`$NC_CONFIG_FULLQUAL --libs` NETCDF_CPPFLAGS=`$NC_CONFIG_FULLQUAL --cflags` NETCDF_VERSION=`$NC_CONFIG_FULLQUAL --version` NETCDF_RPATH=' ' echo "netcdf.m4: about to set rpath, here is source string: >$NETCDF_LDFLAGS<" for word in $NETCDF_LDFLAGS; do v2=`expr "$word" : '-L/'` if test $v2 -eq 3; then slibdir=${word:2} NETCDF_RPATH="$NETCDF_RPATH -Wl,-rpath,$slibdir" fi done echo "netcdf.m4: final rpath: $NETCDF_RPATH" NETCDF_V4=`$NC_CONFIG_FULLQUAL --has-nc4` $as_echo "#define HAVE_NETCDF 1" >>confdefs.h if test x$NETCDF_V4 = xyes; then $as_echo "#define HAVE_NETCDF4 1" >>confdefs.h fi echo "Netcdf library version: $NETCDF_VERSION" echo "Netcdf library has version 4 interface present: $NETCDF_V4" echo "Netcdf library was compiled with C compiler: $NETCDF_CC" if test $NETCDF_V4 = "no"; then echo "-------------------------------------------------------------------" echo "ncdf4 REQUIRES the netcdf library be version 4 or above," echo "AND installed with HDF-5 support (i.e., the netcdf library must be" echo "compiled with the --enable-netcdf-4 flag). If you don't want to install" echo "the full version of netcdf-4 with HDF-5 support, then please install" echo "the old, deprecated ncdf package instead." echo "-------------------------------------------------------------------" exit -1 fi HAVE_NETCDF=TRUE NETCDF_LDFLAGS="$NETCDF_RPATH $NETCDF_LDFLAGS $LDFLAGS" ac_config_files="$ac_config_files src/Makevars" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo " " echo "********************** Results of ncdf4 package configure *******************" echo " " echo "netCDF v4 CPP flags = $NETCDF_CPPFLAGS" echo "netCDF v4 LD flags = $NETCDF_LDFLAGS" echo "netCDF v4 runtime path = $NETCDF_RPATH" echo " " echo "netCDF C compiler used = $NETCDF_CC" echo "R C compiler used = $CC $CFLAGS" echo " " echo "******************************************************************************" echo " " #--------------------------------------------------------------------- # Check to see if a different compiler is being used for netcdf and R #--------------------------------------------------------------------- set $NETCDF_CC NETCDF_CC_ARG1=$1 set $CC R_CC_ARG1=$1 TEST_EMIT_WARNING=0 if test x$NETCDF_CC_ARG1 != x$R_CC_ARG1 -o $TEST_EMIT_WARNING -eq 1; then #------------------------------------------------------------------------------ # By default, we emit a warning if the compilers of R and netcdf are different. # This happens with some regularity to naive users. #------------------------------------------------------------------------------ emit_warning=1 #------------------------------------------------------------------------------------------------- # Skip warning if one is gcc and the other is clang -- seems to bother some overly sensitive folks #------------------------------------------------------------------------------------------------- NETCDF_IS_GCC=0 if echo "$NETCDF_CC_ARG1" | grep -q "gcc"; then NETCDF_IS_GCC=1 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $NETCDF_CC_ARG1 do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in $NETCDF_CC_ARG1 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "z$GCC" = zyes; then NETCDF_IS_GCC=1 fi fi NETCDF_IS_CLANG=0 if echo "$NETCDF_CC_ARG1" | grep -q "clang"; then NETCDF_IS_CLANG=1 fi R_IS_GCC=0 if echo "$R_CC_ARG1" | grep -q "gcc"; then R_IS_GCC=1 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $R_CC_ARG1 do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in $R_CC_ARG1 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "z$GCC" = zyes; then R_IS_GCC=1 fi fi R_IS_CLANG=0 if echo "$R_CC_ARG1" | grep -q "clang"; then R_IS_CLANG=1 fi #------------------------------------------------------------- # We don't bother emitting the warning if the two compilers in # use are clang and gcc -- supposedly they are compatible #------------------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi #----------------------------------------------------- # Both same, but different exact names of compilers... # not sure if this actually guarantees success?? #----------------------------------------------------- if test $NETCDF_IS_CLANG -eq 1 -a $R_IS_CLANG -eq 1; then emit_warning=0 fi if test $NETCDF_IS_GCC -eq 1 -a $R_IS_GCC -eq 1; then emit_warning=0 fi echo "netcdf cc arg1: $NETCDF_CC_ARG1 R cc arg1: $R_CC_ARG1 R_IS_GCC: $R_IS_GCC R_IS_CLANG: $R_IS_CLANG NETCDF_IS_GCC: $NETCDF_IS_GCC NETCDF_IS_CLANG: $NETCDF_IS_CLANG emit_warning: $emit_warning" if test $emit_warning -eq 1 -o $TEST_EMIT_WARNING -eq 1; then echo " " echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" echo "Dear ncdf4 user: The software configuration tool thinks that perhaps different compilers are being" echo "used for R and the netcdf library. However, we all know that software configuration tools are" echo "not that smart. If ncdf4 compiles fine for you, then please ignore this message. However, if" echo "installation fails, it might be that you are using different compilers for R and the netcdf library." echo "If so, then you must create a new version of the netcdf library that was compiled with the same" echo "compiler that was used to install R (see information above). Then, try installing the ncdf4" echo "package again using that new netcdf library. If necessary, you can specify the location of" echo "the new nc-config (the one that uses the same compiler used by R) like this:" echo " " echo "R CMD INSTALL --configure-args=\"--with-nc-config=/home/joe/bin/nc-config\"" echo " " echo "(obviously, put in the correct path to YOUR nc-config, don't just use my example location!)" echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" echo " " fi fi