yorick banner

Home

Manual

Packages

Global Index

Keywords

Quick Reference


/*
   NETCDF.I

   Yorick procedures to open a netCDF file

   The definitive reference for netCDF files is:
   Anonymous FTP site: unidata.ucar.edu [128.117.140.3]

   File:               pub/netcdf/netcdf.tar.Z

   $Id: netcdf.i,v 1.1 1993/08/27 18:50:06 munro Exp $
 */
/*    Copyright (c) 1994.  The Regents of the University of California.
                    All rights reserved.  */

/* Note: I don't use netCDF files, so there are probably still some
         bugs in this code (DHM).  */


local netcdf ;

/* DOCUMENT nc_open, nc_create, nc_vardef, nc_enddef, nc_addrec

     are the main routines to read and write netCDF files.


     The ordinary openb function will also open netCDF files.

     Writing a netCDF file is more problematic in Yorick, since

     you must define the entire file structure before you write

     any data.  Therefore, the nc_create call returns only a

     "token" for nc_vardef, which you use to declare variables
     in the file.  When you are done declaring variables, you

     call nc_enddef, which returns an ordinary Yorick file object.

     You can then write data to the file (with f.var=value or

     save,f,var).  To add a record, you must use nc_addrec instead

     of add_record (nc_addrec updates the record count in the file).
 */

/* ------------- netCDF interface --------------------------------- */


func nc_open (_nc_open_filename, mode)

/* DOCUMENT f= nc_open(filename, mode)
     opens a netCDF file FILENAME for reading or update as specified
     by MODE, which defaults to "rb".  Attributes and dimension names

     can be found in the three external variables nc_dims (an array of

     type NC_dim), nc_attrs (an array of type NC_attr), and nc_vars

     (an array of type NC_var) after this call.
     MODE should be either "rb" or "r+b"; nothing else makes sense.

     If FILENAME is an array of strings, exactly those files will be

     opened as a family (if possible).  Note that nc_open("myfile00")

     potentially opens myfile01, myfile02, and so on, as for openb,

     but that nc_open(["myfile00"]) opens myfile00 only.

   SEE ALSO: nc_create, nc_enddef, nc_attribute, nc_dimsof
 */
{
  if (is_void(mode)) mode= "rb";
  f= open(_nc_open_filename(1), mode);

  if (raw_not_cdf(f)) return [];
  return f;
}


func raw_not_cdf (f)
{
  i= array(char, 4);
  _read, f, 0, i;
  if (string(&i)!="CDF\001") return 1;  /* test magic number */

  xdr_primitives, f;

  numrecs= long(0);
  _read, f, 4, numrecs;

  /* Each of the major components of a netCDF file contains information
     not used by Yorick.  Specifically, dimensions are named, the file
     may have attributes, and any variable contained in the file may

     have attributes.  After a call to nc_open, this additional
     information is stored in the external variable nc_file.  */
  extern nc_file;

  pf= print(f);
  name= dir= "";

  sread, pf(where(strmatch(pf,"binary stream:"))), dir, name,
    format= "%s binary stream: %s";

  sread, pf(where(strmatch(pf,"In directory:"))), dir,
    format= " In directory: %s";

  address= 8;

  nc_dims= NC_ReadArray(f, address);

  nc_attrs= NC_ReadArray(f, address);

  nc_vars= NC_ReadArray(f, address);

  nc_file= NC_file(numrecs=numrecs, dims=&nc_dims, attrs=&nc_attrs,
		   vars=&nc_vars, filename=dir+name);


  if (_nc_declare(f, nc_file)) {
    /* check for presence of a file family */
    dims= dimsof(_nc_open_filename);

    ifile= (!is_void(dims) && dims(1));

    while (!_nc_add_next_file(f, ifile)) {
      i= array(char, 4);
      _read, f, 0, i;
      if (string(&i)!="CDF\001") break;  /* test magic number */
      _read, f, 4, numrecs;
      if (!numrecs) continue;
      nc_file.numrecs= numrecs;
      address= 8;

      dims= NC_ReadArray(f, address);

      attrs= NC_ReadArray(f, address);

      vars= NC_ReadArray(f, address);

      if (numberof(dims)!=numberof(nc_dims) ||
	  anyof(dims.size!=nc_dims.size) ||

	  !_nc_declare(f, nc_file, vars))

        error, "File '"+_nc_open_filename(ifile)+"' has different structure";
    }
  }

  jr, f, 1;
  return 0;
}


func _nc_add_next_file (f, &ifile)
{

  /* modified add_next file checks whether nc_open has been called
   * with an explicit list of file names

   * -- eventually this should be installed in openb generally
   */

  if (!ifile) return add_next_file(f);
  ifile+= 1;

  if (ifile>numberof(_nc_open_filename)) return 1;

  if (add_next_file(f, _nc_open_filename(ifile), 0))

    error, "File '"+_nc_open_filename(ifile)+"' not found";
  return 0;
}


func _nc_declare (f, ncf, check_vars)
{
  nc_dims= *ncf.dims;
  nc_vars= *ncf.vars;
  numrecs= ncf.numrecs;

  if (!is_void(check_vars)) {

    if (numberof(nc_vars)!=numberof(check_vars) ||
	anyof(nc_vars.name!=check_vars.name) ||
	anyof(nc_vars.type!=check_vars.type) ||
	anyof(nc_vars.len!=check_vars.len) ||
	anyof(nc_vars.address!=check_vars.address)) return 0;
  }

  /* check whether there is an unlimited (history) dimension */

  if (is_void(nc_dims)) unlimited= -1;
  else {
    unlimited= (nc_dims.size==0);

    if (noneof(unlimited)) unlimited= -1;

    else unlimited= where(unlimited)(0);
  }

  /* first pass sets non-history variables */
  type_names= ["char", "char", "short", "long", "float", "double"];
  nvars= numberof(nc_vars);

  if (nvars) nonRecord= array(int, nvars);
  else nonRecord= 1;
  for (i=1 ; i<=nvars ; ++i) {
    var= nc_vars(i);
    dimlist= *var.dimlist;
    if (numberof(dimlist)) {
      dimlist+= 1;
      if (dimlist(1)==unlimited) continue;  /* record variable */

      dimlist= grow([numberof(dimlist)], nc_dims.size(dimlist(0:1:-1)));
    } else {
      dimlist= [0];
    }
    nonRecord(i)= 1;
    if (is_void(check_vars))

      add_variable, f, var.address, var.name, type_names(var.type), dimlist;
  }


  /* second pass sets history variables */
  if (nallof(nonRecord)) {
    if (is_void(check_vars))
      add_record, f;
    recList= where(!nonRecord);
    ha= min(nc_vars.address(recList));
    time_address= 0;
    time_type= 0;
    for (i=1 ; i<=nvars ; ++i) {
      if (nonRecord(i)) continue;
      var= nc_vars(i);
      dimlist= *var.dimlist;
      ++dimlist;

      if (numberof(dimlist) > 1) {

	dimlist= grow([numberof(dimlist)-1], nc_dims.size(dimlist(0:2:-1)));
      } else {
	dimlist= [0];
	if (var.name=="time" && (var.type==5 || var.type==6)) {
	  time_address= var.address;
	  time_type= var.type;
	}
      }
      if (is_void(check_vars))
	add_variable, f, var.address-ha,
	                 var.name, type_names(var.type), dimlist;
    }

    /* Note: If there is exactly one record variable, then the records
       need not begin on a 4-byte boundary.  This is only an issue for

       a single record variable of type char or short.  */


    if (numberof(recList)>1 || var.type>3) {
      hs= sum(nc_vars.len(recList));
    } else {
      hs= (var.type==3? 2 : 1);
      for (i=2 ; i<=1+dimlist(1) ; ++i) hs*= dimlist(i);
    }
    if (numrecs) {
      if (time_address) {
	if (time_type==6) time= 0.0;
	else time= 0.0f;
	times= array(0.0, numrecs);
	for (i=1 ; i<=numrecs ; ++i) {
	  _read, f, time_address, time;
	  time_address+= hs;
	  times(i)= time;
	}

	add_record, f, times, , ha+hs*indgen(0:numrecs-1);
      } else {

	add_record, f, , , ha+hs*indgen(0:numrecs-1);
      }
    }

    return 1;
  }

  return 0;
}


func nc_create (filename)

/* DOCUMENT ncf= nc_create(filename)
     creates a netCDF file FILENAME.

     After this call, use nc_vardef to declare the netCDF variables.

     Then use nc_enddef to write the netCDF self-descriptive

     information.  Only after this are you free to actually write data.


   SEE ALSO: nc_open, nc_vardef, nc_attrdef, nc_enddef, nc_addrec,

             nc_attribute, nc_dimsof
 */
{

  return NC_file(filename=filename);
}


func nc_vardef (ncf, name, type, dims, template=, record=, dimnames=)

/* DOCUMENT nc_vardef, ncf, name, type, dims, record=0/1

       -or- nc_vardef, ncf, name, type, record=0/1

       -or- nc_vardef, ncf, name, template=template, record=0/1

     define a variable in the NCF (returned by nc_create) with name

     NAME, type TYPE (as returned by typeof or structof), and dimensions

     DIMS (as returned by dimsof).  The template= keyword may be used

     instead of type and dims; the type and dimsput bin s./usr/share/yorick-doc/html_i/netcdf_i.html0100644000000000000000000014160407423711313017614 0ustar  rootroot  
i/netcdf
 


yorick banner

Home

Manual

Packages

Global Index

Keywords

Quick Reference


/*
   NETCDF.I

   Yorick procedures to open a netCDF file

   The definitive reference for netCDF files is:
   Anonymous FTP site: unidata.ucar.edu [128.117.140.3]

   File:               pub/netcdf/netcdf.tar.Z

   $Id: netcdf.i,v 1.1 1993/08/27 18:50:06 munro Exp $
 */
/*    Copyright (c) 1994.  The Regents of the University of California.
                    All rights reserved.  */

/* Note: I don't use netCDF files, so there are probably still some
         bugs in this code (DHM).  */


local netcdf ;

/* DOCUMENT nc_open, nc_create, nc_vardef, nc_enddef, nc_addrec

     are the main routines to read and write netCDF files.


     The ordinary openb function will also open netCDF files.

     Writing a netCDF file is more problematic in Yorick, since

     you must define the entire file structure before you write

     any data.  Therefore, the nc_create call returns only a

     "token" for nc_vardef, which you use to declare variables
     in the file.  When you are done declaring variables, you

     call nc_enddef, which returns an ordinary Yorick file object.

     You can then write data to the file (with f.var=value or

     save,f,var).  To add a record, you must use nc_addrec instead

     of add_record (nc_addrec updates the record count in the file).
 */

/* ------------- netCDF interface --------------------------------- */


func nc_open (_nc_open_filename, mode)

/* DOCUMENT f= nc_open(filename, mode)
     opens a netCDF file FILENAME for reading or update as specified
     by MODE, which defaults to "rb".  Attributes and dimension names

     can be found in the three external variables nc_dims (an array of

     type NC_dim), nc_attrs (an array of type NC_attr), and nc_vars

     (an array of type NC_var) after this call.
     MODE should be either "rb" or "r+b"; nothing else makes sense.

     If FILENAME is an array of strings, exactly those files will be

     opened as a family (if possible).  Note that nc_open("myfile00")

     potentially opens myfile01, myfile02, and so on, as for openb,

     but that nc_open(["myfile00"]) opens myfile00 only.

   SEE ALSO: nc_create, nc_enddef, nc_attribute, nc_dimsof
 */
{
  if (is_void(mode)) mode= "rb";
  f= open(_nc_open_filename(1), mode);

  if (raw_not_cdf(f)) return [];
  return f;
}


func raw_not_cdf (f)
{
  i= array(char, 4);
  _read, f, 0, i;
  if (string(&i)!="CDF\001") return 1;  /* test magic number */

  xdr_primitives, f;

  numrecs= long(0);
  _read, f, 4, numrecs;

  /* Each of the major components of a netCDF file contains information
     not used by Yorick.  Specifically, dimensions are named, the file
     may have attributes, and any variable contained in the file may

     have attributes.  After a call to nc_open, this additional
     information is stored in the external variable nc_file.  */
  extern nc_file;

  pf= print(f);
  name= dir= "";

  sread, pf(where(strmatch(pf,"binary stream:"))), dir, name,
    format= "%s binary stream: %s";

  sread, pf(where(strmatch(pf,"In directory:"))), dir,
    format= " In directory: %s";

  address= 8;

  nc_dims= NC_ReadArray(f, address);

  nc_attrs= NC_ReadArray(f, address);

  nc_vars= NC_ReadArray(f, address);

  nc_file= NC_file(numrecs=numrecs, dims=&nc_dims, attrs=&nc_attrs,
		   vars=&nc_vars, filename=dir+name);


  if (_nc_declare(f, nc_file)) {
    /* check for presence of a file family */
    dims= dimsof(_nc_open_filename);

    ifile= (!is_void(dims) && dims(1));

    while (!_nc_add_next_file(f, ifile)) {
      i= array(char, 4);
      _read, f, 0, i;
      if (string(&i)!="CDF\001") break;  /* test magic number */
      _read, f, 4, numrecs;
      if (!numrecs) continue;
      nc_file.numrecs= numrecs;
      address= 8;

      dims= NC_ReadArray(f, address);

      attrs= NC_ReadArray(f, address);

      vars= NC_ReadArray(f, address);

      if (numberof(dims)!=numberof(nc_dims) ||
	  anyof(dims.size!=nc_dims.size) ||

	  !_nc_declare(f, nc_file, vars))

        error, "File '"+_nc_open_filename(ifile)+"' has different structure";
    }
  }

  jr, f, 1;
  return 0;
}


func _nc_add_next_file (f, &ifile)
{

  /* modified add_next file checks whether nc_open has been called
   * with an explicit list of file names

   * -- eventually this should be installed in openb generally
   */

  if (!ifile) return add_next_file(f);
  ifile+= 1;

  if (ifile>numberof(_nc_open_filename)) return 1;

  if (add_next_file(f, _nc_open_filename(ifile), 0))

    error, "File '"+_nc_open_filename(ifile)+"' not found";
  return 0;
}


func _nc_declare (f, ncf, check_vars)
{
  nc_dims= *ncf.dims;
  nc_vars= *ncf.vars;
  numrecs= ncf.numrecs;

  if (!is_void(check_vars)) {

    if (numberof(nc_vars)!=numberof(check_vars) ||
	anyof(nc_vars.name!=check_vars.name) ||
	anyof(nc_vars.type!=check_vars.type) ||
	anyof(nc_vars.len!=check_vars.len) ||
	anyof(nc_vars.address!=check_vars.address)) return 0;
  }

  /* check whether there is an unlimited (history) dimension */

  if (is_void(nc_dims)) unlimited= -1;
  else {
    unlimited= (nc_dims.size==0);

    if (noneof(unlimited)) unlimited= -1;

    else unlimited= where(unlimited)(0);
  }

  /* first pass sets non-history variables */
  type_names= ["char", "char", "short", "long", "float", "double"];
  nvars= numberof(nc_vars);

  if (nvars) nonRecord= array(int, nvars);
  else nonRecord= 1;
  for (i=1 ; i<=nvars ; ++i) {
    var= nc_vars(i);
    dimlist= *var.dimlist;
    if (numberof(dimlist)) {
      dimlist+= 1;
      if (dimlist(1)==unlimited) continue;  /* record variable */

      dimlist= grow([numberof(dimlist)], nc_dims.size(dimlist(0:1:-1)));
    } else {
      dimlist= [0];
    }
    nonRecord(i)= 1;
    if (is_void(check_vars))

      add_variable, f, var.address, var.name, type_names(var.type), dimlist;
  }


  /* second pass sets history variables */
  if (nallof(nonRecord)) {
    if (is_void(check_vars))
      add_record, f;
    recList= where(!nonRecord);
    ha= min(nc_vars.address(recList));
    time_address= 0;
    time_type= 0;
    for (i=1 ; i<=nvars ; ++i) {
      if (nonRecord(i)) continue;
      var= nc_vars(i);
      dimlist= *var.dimlist;
      ++dimlist;

      if (numberof(dimlist) > 1) {

	dimlist= grow([numberof(dimlist)-1], nc_dims.size(dimlist(0:2:-1)));
      } else {
	dimlist= [0];
	if (var.name=="time" && (var.type==5 || var.type==6)) {
	  time_address= var.address;
	  time_type= var.type;
	}
      }
      if (is_void(check_vars))
	add_variable, f, var.address-ha,
	                 var.name, type_names(var.type), dimlist;
    }

    /* Note: If there is exactly one record variable, then the records
       need not begin on a 4-byte boundary.  This is only an issue for

       a single record variable of type char or short.  */


    if (numberof(recList)>1 || var.type>3) {
      hs= sum(nc_vars.len(recList));
    } else {
      hs= (var.type==3? 2 : 1);
      for (i=2 ; i<=1+dimlist(1) ; ++i) hs*= dimlist(i);
    }
    if (numrecs) {
      if (time_address) {
	if (time_type==6) time= 0.0;
	else time= 0.0f;
	times= array(0.0, numrecs);
	for (i=1 ; i<=numrecs ; ++i) {
	  _read, f, time_address, time;
	  time_address+= hs;
	  times(i)= time;
	}

	add_record, f, times, , ha+hs*indgen(0:numrecs-1);
      } else {

	add_record, f, , , ha+hs*indgen(0:numrecs-1);
      }
    }

    return 1;
  }

  return 0;
}


func nc_create (filename)

/* DOCUMENT ncf= nc_create(filename)
     creates a netCDF file FILENAME.

     After this call, use nc_vardef to declare the netCDF variables.

     Then use nc_enddef to write the netCDF self-descriptive

     information.  Only after this are you free to actually write data.


   SEE ALSO: nc_open, nc_vardef, nc_attrdef, nc_enddef, nc_addrec,

             nc_attribute, nc_dimsof
 */
{

  return NC_file(filename=filename);
}


func nc_vardef (ncf, name, type, dims, template=, record=, dimnames=)

/* DOCUMENT nc_vardef, ncf, name, type, dims, record=0/1

       -or- nc_vardef, ncf, name, type, record=0/1

       -or- nc_vardef, ncf, name, template=template, record=0/1

     define a variable in the NCF (returned by nc_create) with name

     NAME, type TYPE (as returned by typeof or structof), and dimensions

     DIMS (as returned by dimsof).  The template= keyword may be used

     instead of type and dims; the type and dimsput bin s./usr/share/yorick-doc/html_i/netcdf_i.html0100644000000000000000000014160407423711313017614 0ustar  rootroot  
i/netcdf
 


yorick banner

Home

Manual

Packages

Global Index

Keywords

Quick Reference


/*
   NETCDF.I

   Yorick procedures to open a netCDF file

   The definitive reference for netCDF files is:
   Anonymous FTP site: unidata.ucar.edu [128.117.140.3]

   File:               pub/netcdf/netcdf.tar.Z

   $Id: netcdf.i,v 1.1 1993/08/27 18:50:06 munro Exp $
 */
/*    Copyright (c) 1994.  The Regents of the University of California.
                    All rights reserved.  */

/* Note: I don't use netCDF files, so there are probably still some
         bugs in this code (DHM).  */


local netcdf ;

/* DOCUMENT nc_open, nc_create, nc_vardef, nc_enddef, nc_addrec

     are the main routines to read and write netCDF files.


     The ordinary openb function will also open netCDF files.

     Writing a netCDF file is more problematic in Yorick, since

     you must define the entire file structure before you write

     any data.  Therefore, the nc_create call returns only a

     "token" for nc_vardef, which you use to declare variables
     in the file.  When you are done declaring variables, you

     call nc_enddef, which returns an ordinary Yorick file object.

     You can then write data to the file (with f.var=value or

     save,f,var).  To add a record, you must use nc_addrec instead

     of add_record (nc_addrec updates the record count in the file).
 */

/* ------------- netCDF interface --------------------------------- */


func nc_open (_nc_open_filename, mode)

/* DOCUMENT f= nc_open(filename, mode)
     opens a netCDF file FILENAME for reading or update as specified
     by MODE, which defaults to "rb".  Attributes and dimension names

     can be found in the three external variables nc_dims (an array of

     type NC_dim), nc_attrs (an array of type NC_attr), and nc_vars

     (an array of type NC_var) after this call.
     MODE should be either "rb" or "r+b"; nothing else makes sense.

     If FILENAME is an array of strings, exactly those files will be

     opened as a family (if possible).  Note that nc_open("myfile00")

     potentially opens myfile01, myfile02, and so on, as for openb,

     but that nc_open(["myfile00"]) opens myfile00 only.

   SEE ALSO: nc_create, nc_enddef, nc_attribute, nc_dimsof
 */
{
  if (is_void(mode)) mode= "rb";
  f= open(_nc_open_filename(1), mode);

  if (raw_not_cdf(f)) return [];
  return f;
}


func raw_not_cdf (f)
{
  i= array(char, 4);
  _read, f, 0, i;
  if (string(&i)!="CDF\001") return 1;  /* test magic number */

  xdr_primitives, f;

  numrecs= long(0);
  _read, f, 4, numrecs;

  /* Each of the major components of a netCDF file contains information
     not used by Yorick.  Specifically, dimensions are named, the file
     may have attributes, and any variable contained in the file may

     have attributes.  After a call to nc_open, this additional
     information is stored in the external variable nc_file.  */
  extern nc_file;

  pf= print(f);
  name= dir= "";

  sread, pf(where(strmatch(pf,"binary stream:"))), dir, name,
    format= "%s binary stream: %s";

  sread, pf(where(strmatch(pf,"In directory:"))), dir,
    format= " In directory: %s";

  address= 8;

  nc_dims= NC_ReadArray(f, address);

  nc_attrs= NC_ReadArray(f, address);

  nc_vars= NC_ReadArray(f, address);

  nc_file= NC_file(numrecs=numrecs, dims=&nc_dims, attrs=&nc_attrs,
		   vars=&nc_vars, filename=dir+name);


  if (_nc_declare(f, nc_file)) {
    /* check for presence of a file family */
    dims= dimsof(_nc_open_filename);

    ifile= (!is_void(dims) && dims(1));

    while (!_nc_add_next_file(f, ifile)) {
      i= array(char, 4);
      _read, f, 0, i;
      if (string(&i)!="CDF\001") break;  /* test magic number */
      _read, f, 4, numrecs;
      if (!numrecs) continue;
      nc_file.numrecs= numrecs;
      address= 8;

      dims= NC_ReadArray(f, address);

      attrs= NC_ReadArray(f, address);

      vars= NC_ReadArray(f, address);

      if (numberof(dims)!=numberof(nc_dims) ||
	  anyof(dims.size!=nc_dims.size) ||

	  !_nc_declare(f, nc_file, vars))

        error, "File '"+_nc_open_filename(ifile)+"' has different structure";
    }
  }

  jr, f, 1;
  return 0;
}


func _nc_add_next_file (f, &ifile)
{

  /* modified add_next file checks whether nc_open has been called
   * with an explicit list of file names

   * -- eventually this should be installed in openb generally
   */

  if (!ifile) return add_next_file(f);
  ifile+= 1;

  if (ifile>numberof(_nc_open_filename)) return 1;

  if (add_next_file(f, _nc_open_filename(ifile), 0))

    error, "File '"+_nc_open_filename(ifile)+"' not found";
  return 0;
}


func _nc_declare (f, ncf, check_vars)
{
  nc_dims= *ncf.dims;
  nc_vars= *ncf.vars;
  numrecs= ncf.numrecs;

  if (!is_void(check_vars)) {

    if (numberof(nc_vars)!=numberof(check_vars) ||
	anyof(nc_vars.name!=check_vars.name) ||
	anyof(nc_vars.type!=check_vars.type) ||
	anyof(nc_vars.len!=check_vars.len) ||
	anyof(nc_vars.address!=check_vars.address)) return 0;
  }

  /* check whether there is an unlimited (history) dimension */

  if (is_void(nc_dims)) unlimited= -1;
  else {
    unlimited= (nc_dims.size==0);

    if (noneof(unlimited)) unlimited= -1;

    else unlimited= where(unlimited)(0);
  }

  /* first pass sets non-history variables */
  type_names= ["char", "char", "short", "long", "float", "double"];
  nvars= numberof(nc_vars);

  if (nvars) nonRecord= array(int, nvars);
  else nonRecord= 1;
  for (i=1 ; i<=nvars ; ++i) {
    var= nc_vars(i);
    dimlist= *var.dimlist;
    if (numberof(dimlist)) {
      dimlist+= 1;
      if (dimlist(1)==unlimited) continue;  /* record variable */

      dimlist= grow([numberof(dimlist)], nc_dims.size(dimlist(0:1:-1)));
    } else {
      dimlist= [0];
    }
    nonRecord(i)= 1;
    if (is_void(check_vars))

      add_variable, f, var.address, var.name, type_names(var.type), dimlist;
  }


  /* second pass sets history variables */
  if (nallof(nonRecord)) {
    if (is_void(check_vars))
      add_record, f;
    recList= where(!nonRecord);
    ha= min(nc_vars.address(recList));
    time_address= 0;
    time_type= 0;
    for (i=1 ; i<=nvars ; ++i) {
      if (nonRecord(i)) continue;
      var= nc_vars(i);
      dimlist= *var.dimlist;
      ++dimlist;

      if (numberof(dimlist) > 1) {

	dimlist= grow([numberof(dimlist)-1], nc_dims.size(dimlist(0:2:-1)));
      } else {
	dimlist= [0];
	if (var.name=="time" && (var.type==5 || var.type==6)) {
	  time_address= var.address;
	  time_type= var.type;
	}
      }
      if (is_void(check_vars))
	add_variable, f, var.address-ha,
	                 var.name, type_names(var.type), dimlist;
    }

    /* Note: If there is exactly one record variable, then the records
       need not begin on a 4-byte boundary.  This is only an issue for

       a single record variable of type char or short.  */


    if (numberof(recList)>1 || var.type>3) {
      hs= sum(nc_vars.len(recList));
    } else {
      hs= (var.type==3? 2 : 1);
      for (i=2 ; i<=1+dimlist(1) ; ++i) hs*= dimlist(i);
    }
    if (numrecs) {
      if (time_address) {
	if (time_type==6) time= 0.0;
	else time= 0.0f;
	times= array(0.0, numrecs);
	for (i=1 ; i<=numrecs ; ++i) {
	  _read, f, time_address, time;
	  time_address+= hs;
	  times(i)= time;
	}

	add_record, f, times, , ha+hs*indgen(0:numrecs-1);
      } else {

	add_record, f, , , ha+hs*indgen(0:numrecs-1);
      }
    }

    return 1;
  }

  return 0;
}


func nc_create (filename)

/* DOCUMENT ncf= nc_create(filename)
     creates a netCDF file FILENAME.

     After this call, use nc_vardef to declare the netCDF variables.

     Then use nc_enddef to write the netCDF self-descriptive

     information.  Only after this are you free to actually write data.


   SEE ALSO: nc_open, nc_vardef, nc_attrdef, nc_enddef, nc_addrec,

             nc_attribute, nc_dimsof
 */
{

  return NC_file(filename=filename);
}


func nc_vardef (ncf, name, type, dims, template=, record=, dimnames=)

/* DOCUMENT nc_vardef, ncf, name, type, dims, record=0/1

       -or- nc_vardef, ncf, name, type, record=0/1

       -or- nc_vardef, ncf, name, template=template, record=0/1

     define a variable in the NCF (returned by nc_create) with name

     NAME, type TYPE (as returned by typeof or structof), and dimensions

     DIMS (as returned by dimsof).  The template= keyword may be used

     instead of type and dims; the type and dimsput bin s./usr/share/yorick-doc/html_i/netcdf_i.html0100644000000000000000000014160407423711313017614 0ustar  rootroot  
i/netcdf
 


yorick banner

Home

Manual

Packages

Global Index

Keywords

Quick Reference


/*
   NETCDF.I

   Yorick procedures to