Hi Pedro,
You're right that it would be useful to have additional public netCDF
functions to make it easy to get the absolute netCDF name from a
dimension ID and the reverse.
There is code for this in the source for ncdump and nccopy. The ncdump
utility outputs the absolute dimension name when there is an ambiguity,
for example one of the test cases for ncdump outputs this variable
declaration for a case where a variable uses several dimensions named
"dim" in different groups (see ncdump/ref_tst_group_data.cdl):
float var2(/dim, /g2/dim, dim) ;
The code for figuring out these names is in ncdump/ncdump.c, preceded by
this comment
/* Subtlety: The following code block is needed because
* nc_inq_dimname() currently returns only a simple dimension
* name, without a prefix identifying the group it came from.
* That's OK unless the dimid identifies a dimension in an
* ancestor group that has the same simple name as a
* dimension in the current group (or some intermediate
* group), in which case the simple name is ambiguous. This
* code tests for that case and provides an absolute dimname
* only in the case where a simple name would be
* ambiguous. */
The 20 or so subsequent lines of code that implement this should be
captured in a separate function, so other developers don't need to
rediscover how to do it with the current public API.
For the other direction, there is this function in ncdump/utils.c that
would also be useful in the public API:
/* Missing functionality that should be in nc_inq_dimid(), to get
* dimid from a full dimension path name that may include group
* names */
int
nc_inq_dimid2(int ncid, const char *dimname, int *dimidp) {
...
We have some plans to provide API additions such as these for developers
of generic netCDF tools in a future version. Thanks for pointing out
the need for these.
--Russ
> This is a multi-part message in MIME format.
>
> --===============0004655921==
> Content-Type: multipart/alternative;
> boundary="----=_NextPart_000_0013_01CE1883.8BB35050"
>
> This is a multi-part message in MIME format.
>
> ------=_NextPart_000_0013_01CE1883.8BB35050
> Content-Type: text/plain;
> charset="iso-8859-1"
> Content-Transfer-Encoding: quoted-printable
>
>
> ok, I think I found the solution...
>
> The fact that group dimension IDs are in fact unique makes possible to =
> match them with dimension IDs for variables...
>
> But only if I have a list of
>
> 1) The full path of all dimensions in the file
> 2) The full path of all dimensions for each variable
>
> I already had this. I constructed my "path only" model by recursively =
> iterating the file, starting at root,=20
> and for every group I store the current path passed as a parameter to =
> the recursive function.
>
> The API gets me all local info for variables, for the current group, =
> including dimensions for variables and dimensions for groups.
>
> The additional step is to store for each group, the dimension ID, and =
> for every variable dimension, its ID.
> Then match them.
>
> So, I take back my comment that "IDs are a recipe for disaster", for =
> dimensions they are actually the solution.
>
> I was thinking more of variable IDs, that can have duplicated values for =
> each group, somehow I missed this dimension ID issue.
>
> Here's my output with this patch applied
>
> ncks: INFO nco_bld_dmn_ids_trv() traversing variable =
> </g16/g16g2/lon1_var>
> match <8> for var dim </g16/lon1> and group dim </g16/lon1>
>
> In summary
>
> 1) the API does not get me the full dimension path for each variable, =
> but it's possible to construct them.
> 2) I don't need variable IDs and group IDs
>
>
> Pedro
>
>
>
> ------
> Pedro Vicente, Earth System Science
> University of California, Irvine
> http://www.ess.uci.edu/
>
>
> ----- Original Message -----=20
> From: Pedro Vicente=20
> To: netcdfgroup@xxxxxxxxxxxxxxxx=20
> Sent: Monday, March 04, 2013 1:40 AM
> Subject: Re: [netcdfgroup] How to find the full dimension names =
> (pathswithgroups) for a variable?
>
>
>
> hmm.. another correction
>
> >> that is, if I compare the nc_inq_vardimid variable dimension IDs =
> with the nc_inq_dimid dimension group IDs for *all* groups in the file=20
>
>
> I did a little experiment that does just this , and if I had a match =
> of variable dimension ID with group dimension ID I printed a message =
> like
>
> ncks: INFO nco_bld_dmn_ids_trv() traversing variable =
> </g16/g16g1/lon1_var>
> match <8> for var dim <lon1> and group dim <lon1>
>
> this tells me that for the variable </g16/g16g1/lon1_var>=20
> I have a dimension with a *relative* name <lon1> and a ID <8>
> and that the IDs for variable dimensions and group dimensions are the =
> same=20
>
> Furthermore, I do not have duplicated dimension IDs, they are nicely =
> ordered from 0 to the number of unique dimensions in my file
> ...so, it seems that dimension IDs are unique.
>
> If this is the case, this is good ...
>
> Is this the case ?
>
> but.. back to the original problem, the API is not telling me the =
> absolute location of the dimension
>
> that output just tells me that for the variable =
> </g16/g16g1/lon1_var>, absolute location ,
>
> it tells me that *somewhere* in scope I have a dimension called "lon1" =
> and that has an ID=3D8
>
> Pedro
>
>
> ------
> Pedro Vicente, Earth System Science
> University of California, Irvine
> http://www.ess.uci.edu/
>
>
> ----- Original Message -----=20
> From: Pedro Vicente=20
> To: Pedro Vicente ; netcdfgroup@xxxxxxxxxxxxxxxx=20
> Sent: Sunday, March 03, 2013 8:42 PM
> Subject: Re: [netcdfgroup] How to find the full dimension names =
> (paths withgroups) for a variable?
>
>
>
> Correction,
>
> "nc_inq_vardimid" is the function to get the dimension IDs for the =
> *variable*
>
> It is part of the "nc_inq_var" family
>
>
> http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c.html
>
> this page does not mention the function in the top index , in the =
> list of Variables functions
>
>
> From the Manual:
>
>
> int nc_inq_vardimid (int ncid, int varid, int dimids[]);
>
> ncid NetCDF ID, from a previous call to nc_open or nc_create.
> varid Variable Id
> dimids Returned vector of *ndimsp dimension IDs corresponding to the =
> variable dimensions
> The caller must allocate enough space for a vector of at least =
> *ndimsp integers to be returned.=20
> The maximum possible number of dimensions for a variable is given by =
> the predefined constant NC_MAX_VAR_DIMS.
>
>
> But this does not mention anything about the *location* of these =
> dimensions (location in the group hierarchy).
>
>
> Can these IDs obtained with nc_inq_vardimid be compared with the =
> IDs obtained with the function that gets dimension IDs for groups ?=20
>
> int nc_inq_dimid (int ncid, const char *name, int *dimidp);
> ncid
> NetCDF ID, from a previous call to nc_open or nc_create.
> name
> Dimension name.
> dimidp
> Pointer to location for the returned dimension ID.=20
>
>
>
> that is, if I compare the nc_inq_vardimid variable dimension IDs =
> with the nc_inq_dimid dimension group IDs for *all* groups in the file =
> (making sure that I get only the dimesion IDs for that
> group at each iteration, not ancestor groups) ,
> then if they have the same numerical value, that means that the =
> matched dimension ID from the variable is located in that particular =
> group ?
>
> Do I have to traverse all the file , or just the groups that are "in =
> scope" of the variable ?
>
> I already have a list of all the objects in the file, that has full =
> group name for objects (groups and variables), this might be easier
> than to build a "in scope" function, based in name comparison =
> (Basically what I did in that code I sent)
>
> Thanks
>
> Pedro
>
> ------
> Pedro Vicente, Earth System Science
> University of California, Irvine
> http://www.ess.uci.edu/
>
>
> PS: here's the function in its full glory :)
>
>
> void =20
> nco_bld_dmn_trv /* [fnc] Build dimension info =
> for all variables */
> (const int nc_id, /* I [ID] File ID */
> trv_tbl_sct * const trv_tbl) /* I/O [sct] GTT (Group =
> Traversal Table) */
> {
> /* Purpose: a netCDF4 variable can have its dimensions located =
> anywhere below *in the group path*
> Construction of this list *must* be done after traversal table is =
> build in nco_grp_itr(),
> where we know the full picture of the file tree
> */
>
> char dmn_nm_var[NC_MAX_NAME];/* [sng] Dimension name for variable =
> */=20
> char dmn_nm_grp[NC_MAX_NAME];/* [sng] Dimension name for group */=20
>
> const int flg_prn=3D1; /* [flg] Dimensions in all parent =
> groups will also be retrieved */=20
>
> int dmn_id_grp[NC_MAX_DIMS]; /* [id] Dimensions IDs array for =
> group */
> int dmn_id_var[NC_MAX_DIMS]; /* [id] Dimensions IDs array for =
> variable */
>
> int nbr_dmn_grp; /* [nbr] Number of dimensions for =
> group */
> int nbr_dmn_var; /* [nbr] Number of dimensions for =
> variable */
> int var_id; /* [id] ID of variable */
> int grp_id; /* [id] ID of group */
>
> char *ptr_chr; /* [sng] Pointer to character '/' in =
> full name */
> int psn_chr; /* [nbr] Position of character '/' in =
> in full name */
>
> /* Loop *object* traversal table */
> for(unsigned uidx=3D0;uidx<trv_tbl->nbr;uidx++){
> if(trv_tbl->lst[uidx].nco_typ =3D=3D nco_obj_typ_var){
> trv_sct trv=3Dtrv_tbl->lst[uidx]; =20
>
> /* Obtain group ID using full group name */
> (void)nco_inq_grp_full_ncid(nc_id,trv.grp_nm_fll,&grp_id);
>
> /* Obtain variable ID using group ID */
> (void)nco_inq_varid(grp_id,trv.nm,&var_id);
>
> /* Get number of dimensions for variable */
> (void)nco_inq_varndims(grp_id,var_id,&nbr_dmn_var);
>
> /* Get dimension IDs for variable */
> (void)nco_inq_vardimid(grp_id,var_id,dmn_id_var);
>
> /* Obtain dimension IDs for group. NB: go to parents */
> (void)nco_inq_dimids(grp_id,&nbr_dmn_grp,dmn_id_grp,flg_prn);
>
> /* Loop over dimensions of variable */
> for(int =
> dmn_idx_var=3D0;dmn_idx_var<nbr_dmn_var;dmn_idx_var++){
>
> /* Get dimension name */
> =
> (void)nco_inq_dimname(grp_id,dmn_id_var[dmn_idx_var],dmn_nm_var);
>
> /* Now the exciting part; we have to locate where =
> "dmn_var_nm" is located
> 1) Dimensions are defined in *groups*: find group where =
> variable resides
> 2) Most common case is for the dimension to be defined in =
> the same group where variable is
> 3) If not, we have to traverse the group back until the =
> dimension name is found
>
> From: "Dennis Heimbigner" <dmh@xxxxxxxxxxxxxxxx>
> Subject: Re: [netcdfgroup] defining dimensions in groups
> 1. The inner dimension is used. The rule is to look up the =
> group tree
> from innermost to root and choose the first one that is =
> found
> with a matching name.
> 2. The fact that it is a dimension for a coordinate variable =
> is not relevant for the
> choice.
> However, note that this rule is only used by ncgen when =
> disambiguating a reference
> in the CDL. The issue does not come up in the netcdf API =
> because
> you have to specifically supply the dimension id when =
> defining the dimension
> for a variable.
>
> 4) Use case example: /g5/g5g1/rz variable and rz(rlev), =
> where dimension "rlev" resides in /g5/rlev=20
> */
>
> /* Loop over dimensions of group *and* parents */
> for(int =
> dmn_idx_grp=3D0;dmn_idx_grp<nbr_dmn_grp;dmn_idx_grp++){
>
> /* Get dimension name for group */
> =
> (void)nco_inq_dimname(grp_id,dmn_id_grp[dmn_idx_grp],dmn_nm_grp);
>
> /* Does dimension name for *variable* match dimension name =
> for *group* ? */=20
> if(strcmp(dmn_nm_var,dmn_nm_grp) =3D=3D 0){
>
> /* Now...we know that *somewhere* for all this group =
> dimensions one is the real deal=20
> Attempt to construct a *possible* full dimension name =
> and compare with the table dimension list
> until a full name match is found ... */
>
> /* Was the dimension found?: handy in all this =
> *tortured* logic; needs revision, but works ! */
> nco_bool dmn_was_found=3DFalse;
>
> /* Construct *possible* dimension full name */
> char =
> *dmn_nm_fll=3D(char*)nco_malloc(strlen(trv.grp_nm_fll)+strlen(dmn_nm_var)=
> +2L);
> strcpy(dmn_nm_fll,trv.grp_nm_fll);
> if(strcmp(trv.grp_nm_fll,"/")) strcat(dmn_nm_fll,"/");
> strcat(dmn_nm_fll,dmn_nm_var);
>
> /* Brute-force approach to find valid "dmn_nm_fll":
> Start at grp_nm_fll/dmn_nm_var and build all possible =
> paths with dmn_nm_var.=20
> Use cases are:
> Real life output of: ncks --get_grp_info =
> ~/nco/data/in_grp.nc
> /g1/lon: 1 dimensions: /lon :=20
> /g5/g5g1/rz: 1 dimensions: /g5/rlev :=20
> /g10/three_dmn_rec_var: 3 dimensions: /time : /lat : =
> /lon : =20
> */
>
> /* Find last occurence of '/' */
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');
> psn_chr=3Dptr_chr-dmn_nm_fll;
>
> /* While there is a possible dimension path */
> while(ptr_chr && !dmn_was_found){
>
> /* Search table dimension list */
> for(unsigned int =
> dmn_lst_idx=3D0;dmn_lst_idx<trv_tbl->nbr_dmn;dmn_lst_idx++){
> dmn_fll_sct dmn_fll=3Dtrv_tbl->lst_dmn[dmn_lst_idx]; =
> =20
>
> /* Does the *possible* dimension full name match a =
> *real* dimension full name ? */
> if(strcmp(dmn_fll.nm_fll,dmn_nm_fll) =3D=3D 0){
>
> /* Store full dimension name */
> =
> trv_tbl->lst[uidx].var_dmn[dmn_idx_var].dmn_nm_fll=3Dstrdup(dmn_nm_fll);
>
> /* The relative dimension name was already stored =
> */
> =
> assert(strcmp(trv_tbl->lst[uidx].var_dmn[dmn_idx_var].dmn_nm,dmn_nm_var) =
> =3D=3D 0);
>
> /* Store full group name where dimension is =
> located. NOTE: using member "grp_nm_fll" of dimension */
> =
> trv_tbl->lst[uidx].var_dmn[dmn_idx_var].grp_nm_fll=3Dstrdup(dmn_fll.grp_n=
> m_fll);
>
> /* Free allocated */
> dmn_nm_fll=3D(char *)nco_free(dmn_nm_fll);
>
> /* Found */
> dmn_was_found=3DTrue;
>
> /* Exit table dimension list loop */
> break;
> } /* End Does the *possible* dimension full name =
> match a *real* dimension full name */
> } /* End Search table dimension list loop */
>
> /* Keep on trying... Re-add dimension name to =
> shortened path */=20
>
> /* If a valid (pointer) name here, then the =
> constructed name was not found */
> if(dmn_nm_fll) {
> dmn_nm_fll[psn_chr]=3D'\0';
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');
> if(ptr_chr){
> psn_chr=3Dptr_chr-dmn_nm_fll;
> dmn_nm_fll[psn_chr]=3D'\0';
> if(strcmp(dmn_nm_fll,"/")) strcat(dmn_nm_fll,"/");
> strcat(dmn_nm_fll,dmn_nm_var);
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');
> psn_chr=3Dptr_chr-dmn_nm_fll;
> } /* !ptr_chr */
> } /* If dmn_nm_fll */
> } /* End While there is a possible dimension path */=20
>
> /* Free allocated (this should never happen here; a =
> dimension must always be found) */
> if(dmn_nm_fll) dmn_nm_fll=3D(char =
> *)nco_free(dmn_nm_fll);
>
> } /* End Does dimension name for variable match dimension =
> name for group ? */
> } /* End Loop over dimensions of group *and* parents */
> } /* End Loop over dimensions of variable */
> } /* End object is variable nco_obj_typ_var */
> } /* End Loop *object* traversal table */
>
>
> } /* end nco_blb_dmn_trv() */
>
>
>
> ----- Original Message -----=20
> From: Pedro Vicente=20
> To: netcdfgroup@xxxxxxxxxxxxxxxx=20
> Sent: Sunday, March 03, 2013 5:10 PM
> Subject: [netcdfgroup] How to find the full dimension names (paths =
> withgroups) for a variable?
>
>
>
> Hi netCDF team
>
> This email is rather long, so please bear with me ...
>
> The short read and main question is:
>
> How to find the full dimension names (paths with groups) for all =
> dimensions that a variable has?
>
> Example:
> Note: Incomplete CDL syntax
>
> group: g16 {=20
> dimensions:
> lon1=3D4; //dimension that has a coordinate variable down in =
> scope at /g16/g16g1/lon1(lon1)=20
> =20
> group: g16g1 {=20
> variables:
> float lon1(lon1); //coordinate variable /g16/g16g1/lon1 that =
> has dimension (/g16/lon1) in scope
> float lon1_var(lon1); // variable /g16/g16g1/lon1_var that =
> has dimension (/g16/lon1) in scope *and* coordinate (/g16/g16g1/lon1) in =
> scope
> =20
> data:
> lon1=3D0.,1.,2.,3.;
> lon1_var=3D0.,1.,2.,3.; =20
> =20
> =20
> Note that coordinate variables can share dimensions; here's a case =
> of a "parallel" group /g16/g16g2/ of /g16/g16g1/
> where variables have their own local coordinate variable that =
> share the ancestor dimension (/g16/lon1)
>
> group: g16g2 {=20
> variables:
> //coordinate variable (/g16/lon1)
> float lon1(lon1);=20
> float lon1_var(lon1); =20
>
> =20
> It is possible to construct other cases, variables with n =
> dimensions, each one defined in different groups (and each one of these =
> dimensions can have coordinate=20
> variables in *other* different groups )
>
>
> More broadly, I am trying to construct a model for ncks of a =
> netCDF4 file that includes :
>
> 1) A list of all "objects" in the file
>
> I call an "object" what I call an object in HDF5: either a group =
> or a variable (a variable is commonly called in HDF5 a "dataset" ).
>
> 2) netCDF4 has dimensions. HDF5 does not (Let's ignore HDF5 =
> dimension scales for now, to keep this simple... Coincidently netCDF4 =
> *happens* to use HDF5
> dimension scales in its inner model, but my understanding is that =
> it did not had to be that way... I think. Imagine for example that HDF5 =
> dimension scales did not exist...
> It would be perfectly possible for netCDF4 to use HDF5 as the =
> underlying format... HDF5 dimension scales are not part of the HDF5 =
> format, they
> are just an abstraction layer build above HDF5 with a so called =
> "High Level" API.... At the time the requirement was for HDF5 to have=20
> the equivalent of HDF(4) "coordinate variables", that could be =
> shared between HDF5 datasets)
>
> excellent article about dimension scales=20
>
> =
> http://www.unidata.ucar.edu/blogs/developer/en/entry/netcdf4_shared_dimen=
> sions
>
>
> Let's call these netCDF4 dimensions, "unique dimensions".
> These are defined in groups.
>
> 3) This model stores *full names* of things: full names, for =
> groups, variables and unique dimensions. Also, full names for coordinate =
> variables.
>
> 4) Coordinate variables.
>
> From the netCDF manual
>
> "It is legal for a variable to have the same name as a dimension. =
> Such variables have no
> special meaning to the netCDF library. However there is a =
> convention that such variables
> should be treated in a special way by software using this library.
> A variable with the same name as a dimension is called a =
> coordinate variable."
>
>
> Dimensions and coordinate variables are used by variables. So, =
> variables must know where dimensions and coordinate variables (if =
> existent for that variable) are.
>
> Example of an output, that prints either a dimension or a =
> coordinate variable for any variable
>
> /g16/g16g1/lon1 ---> coordinate variable=20
> lon1[0]=3D0=20
> lon1[1]=3D1=20
> lon1[2]=3D2=20
> lon1[3]=3D3
>
> /g16/g16g1/lon1_var ---> variable with coordinate variable=20
> lon1[0]=3D0 lon1_var[0]=3D0=20
> lon1[1]=3D1 lon1_var[1]=3D1=20
> lon1[2]=3D2 lon1_var[2]=3D2=20
> lon1[3]=3D3 lon1_var[3]=3D3=20
>
> The API function that returns a dimension name for a variable is
>
> From the netCDF C manual
>
> =
> http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005finq_005f=
> dim-Family.html#nc_005finq_005fdim-Family
>
>
> int nc_inq_dimname (int ncid, int dimid, char *name);
> ncid NetCDF ID, from a previous call to nc_open or nc_create.
> dimid Dimension ID, from a previous call to nc_inq dimid or =
> nc_def_dim.
> name Returned dimension name.
>
> Note: here "ncid" is actually a "location" ID (either a group or =
> the main netCDF file ID), so I think you should change this in the =
> documentation
>
> The "dimid" parameter is an ID of a dimension.
>
> This is obtained with the API function
>
> int nc_inq_dimid (int ncid, const char *name, int *dimidp);
> ncid NetCDF ID, from a previous call to nc_open or nc_create.
> name Dimension name.
> dimidp Pointer to location for the returned dimension ID.
>
> From the manual:
> "When searching for a dimension, the specified group is searched, =
> and then its parent group,
> and then its grandparent group, etc., up to the root group."
>
> Ok, great, the dimension ID "dimidp" can be in a ancestor group, =
> but how to know where?
>
>
> My understanding is that netCDF4 group IDs are "unique"; dimension =
> IDs are not, they can have duplicated values in several groups.
>
> In the above call nc_inq_dimid, dimension IDs in ancestor groups =
> are returned, but duplicates may happen.=20
>
> I think storing IDs, even unique group IDs, in the model above is =
> a recipe for disaster.=20
> I see IDs as an equivalent of the paper ticket number I am given =
> when I take the train and want to keep my luggage at a station for a =
> while.
> When I get my bags back, I dispose the ticket number.=20
> That ticket is helpful for the person that has to identify my bags =
> only.=20
>
> As a developer, for debugging purposes, or even as a netCDF4 user, =
> it is also much easier to identify something by name than by ID.
>
> Possible ways to solve this (to get full dimension name for a =
> variable):
>
> 1) Iterate ancestor groups, get all variables for each group, get =
> variables dimension IDs, and compare with group dimension Ids ?
> 2) Iterate ancestor groups, try to construct a possible full =
> dimension name and match ?
>
> Below is some code sample that tries to solve this using option 2) =
> above,=20
>
> But as a netCDF API user, I don't think that I should have to do =
> this, mainly because it could just be wrong (it could not cover all =
> cases, for example).
>
> What I think is needed here is a new API function that returns =
> the *full* dimension names for all dimensions used by a variable, =
> instead of an ID and relative name only.
> With information if that dimension "name" is a coordinate variable =
> or just a dimension.=20
>
> Would it be possible for the netCDF group to supply this function?
>
> There is a similar function for groups:
>
> =
> http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005finq_005f=
> grpname_005ffull.html#nc_005finq_005fgrpname_005ffull
>
> int nc_inq_grpname_full(int ncid, size_t *lenp, char *full_name);
> ncid The group id for this operation.
> full_name
> Pointer to allocated space of correct length.
>
> That returns the *full name* of the group from the group ID, this =
> is one of the most helpful functions to construct this "full path" model
>
> Thanks for your help
>
> Pedro
>
>
> ------
> Pedro Vicente, Earth System Science
> University of California, Irvine
> http://www.ess.uci.edu/
>
>
> PS: here's the code that tries to find full dimension names
>
>
> /* Loop *object* traversal table */
> for(unsigned uidx=3D0;uidx<trv_tbl->nbr;uidx++){
> if(trv_tbl->lst[uidx].nco_typ =3D=3D nco_obj_typ_var){
> trv_sct trv=3Dtrv_tbl->lst[uidx]; =20
>
> /* Obtain group ID using full group name */
> (void)nco_inq_grp_full_ncid(nc_id,trv.grp_nm_fll,&grp_id);
>
> /* Obtain variable ID using group ID */
> (void)nco_inq_varid(grp_id,trv.nm,&var_id);
>
> /* Get number of dimensions for variable */
> (void)nco_inq_varndims(grp_id,var_id,&nbr_dmn_var);
>
> /* Get dimension IDs for variable */
> (void)nco_inq_vardimid(grp_id,var_id,dmn_id_var);
>
> /* Obtain dimension IDs for group. NB: go to parents */
> =
> (void)nco_inq_dimids(grp_id,&nbr_dmn_grp,dmn_id_grp,flg_prn);
>
> /* Loop over dimensions of variable */
> for(int =
> dmn_idx_var=3D0;dmn_idx_var<nbr_dmn_var;dmn_idx_var++){
>
> /* Get dimension name */
> =
> (void)nco_inq_dimname(grp_id,dmn_id_var[dmn_idx_var],dmn_nm_var);
>
> /* Now the exciting part; we have to locate where =
> "dmn_var_nm" is located
> 1) Dimensions are defined in *groups*: find group where =
> variable resides
> 2) Most common case is for the dimension to be defined in =
> the same group where variable is
> 3) If not, we have to traverse the group back until the =
> dimension name is found
>
> From: "Dennis Heimbigner" <dmh@xxxxxxxxxxxxxxxx>
> Subject: Re: [netcdfgroup] defining dimensions in groups
> 1. The inner dimension is used. The rule is to look up the =
> group tree
> from innermost to root and choose the first one that is =
> found
> with a matching name.
> 2. The fact that it is a dimension for a coordinate =
> variable is not relevant for the
> choice.
> However, note that this rule is only used by ncgen when =
> disambiguating a reference
> in the CDL. The issue does not come up in the netcdf API =
> because
> you have to specifically supply the dimension id when =
> defining the dimension
> for a variable.
>
> 4) Use case example: /g5/g5g1/rz variable and rz(rlev), =
> where dimension "rlev" resides in /g5/rlev=20
> */
>
> /* Loop over dimensions of group *and* parents */
> for(int =
> dmn_idx_grp=3D0;dmn_idx_grp<nbr_dmn_grp;dmn_idx_grp++){
>
> /* Get dimension name for group */
> =
> (void)nco_inq_dimname(grp_id,dmn_id_grp[dmn_idx_grp],dmn_nm_grp);
>
> /* Does dimension name for *variable* match dimension =
> name for *group* ? */=20
> if(strcmp(dmn_nm_var,dmn_nm_grp) =3D=3D 0){
>
>
>
>
>
> -------------------------------------------------------------------------=
> -
>
>
> _______________________________________________
> netcdfgroup mailing list
> netcdfgroup@xxxxxxxxxxxxxxxx
> For list information or to unsubscribe, visit: =
> http://www.unidata.ucar.edu/mailing_lists/
>
>
> -------------------------------------------------------------------------=
> -----
>
>
> _______________________________________________
> netcdfgroup mailing list
> netcdfgroup@xxxxxxxxxxxxxxxx
> For list information or to unsubscribe, visit: =
> http://www.unidata.ucar.edu/mailing_lists/
> ------=_NextPart_000_0013_01CE1883.8BB35050
> Content-Type: text/html;
> charset="iso-8859-1"
> Content-Transfer-Encoding: quoted-printable
>
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
> <HTML><HEAD>
> <META content=3D"text/html; charset=3Diso-8859-1" =
> http-equiv=3DContent-Type>
> <META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16464">
> <STYLE></STYLE>
> </HEAD>
> <BODY bgColor=3D#ffffff>
> <DIV> </DIV>
> <DIV>ok, I think I found the solution...</DIV>
> <DIV> </DIV>
> <DIV>The fact that group dimension IDs are in fact unique makes possible =
> to=20
> match them with dimension IDs for variables...</DIV>
> <DIV> </DIV>
> <DIV>But only if I have a list of</DIV>
> <DIV> </DIV>
> <DIV>1) The full path of all dimensions in the file<BR>2) The full path =
> of all=20
> dimensions for each variable</DIV>
> <DIV> </DIV>
> <DIV>I already had this. I constructed my "path only" model by =
> recursively=20
> iterating the file, starting at root, <BR>and for every group I store =
> the=20
> current path passed as a parameter to the recursive function.</DIV>
> <DIV> </DIV>
> <DIV>The API gets me all local info for variables, for the current =
> group,=20
> including dimensions for variables and dimensions for groups.</DIV>
> <DIV> </DIV>
> <DIV>The additional step is to store for each group, the dimension ID, =
> and for=20
> every variable dimension, its ID.<BR>Then match them.</DIV>
> <DIV> </DIV>
> <DIV>So, I take back my comment that "IDs are a recipe for disaster", =
> for=20
> dimensions they are actually the solution.</DIV>
> <DIV> </DIV>
> <DIV>I was thinking more of variable IDs, that can have duplicated =
> values for=20
> each group, somehow I missed this dimension ID issue.</DIV>
> <DIV> </DIV>
> <DIV>Here's my output with this patch applied</DIV>
> <DIV> </DIV>
> <DIV>ncks: INFO nco_bld_dmn_ids_trv() traversing variable=20
> </g16/g16g2/lon1_var><BR>match <8> for var dim =
> </g16/lon1> and=20
> group dim </g16/lon1></DIV>
> <DIV> </DIV>
> <DIV>In summary</DIV>
> <DIV> </DIV>
> <DIV>1) the API does not get me the full dimension path for each =
> variable, but=20
> it's possible to construct them.<BR>2) I don't need variable IDs and =
> group=20
> IDs</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV>Pedro</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial>------<BR>Pedro Vicente, Earth System=20
> Science<BR>University of California, Irvine<BR><A=20
> href=3D"http://www.ess.uci.edu/">http://www.ess.uci.edu/</A></FONT></DIV>=
>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial></FONT> </DIV>
> <BLOCKQUOTE=20
> style=3D"BORDER-LEFT: #000000 2px solid; PADDING-LEFT: 5px; =
> PADDING-RIGHT: 0px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px">
> <DIV style=3D"FONT: 10pt arial">----- Original Message ----- </DIV>
> <DIV=20
> style=3D"FONT: 10pt arial; BACKGROUND: #e4e4e4; font-color: =
> black"><B>From:</B>=20
> <A title=3Dpvicente@xxxxxxx href=3D"mailto:pvicente@xxxxxxx">Pedro =
> Vicente</A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>To:</B> <A =
> title=3Dnetcdfgroup@xxxxxxxxxxxxxxxx=20
> =
> href=3D"mailto:netcdfgroup@xxxxxxxxxxxxxxxx">netcdfgroup@xxxxxxxxxxxxxxxx=
> </A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Monday, March 04, 2013 =
> 1:40=20
> AM</DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Subject:</B> Re: [netcdfgroup] How =
> to find=20
> the full dimension names (pathswithgroups) for a variable?</DIV>
> <DIV><BR></DIV>
> <DIV> </DIV>
> <DIV>hmm.. another correction</DIV>
> <DIV> </DIV>
> <DIV>>> that is, if I compare the nc_inq_vardimid variable =
> dimension IDs=20
> with the nc_inq_dimid dimension group IDs for *all* groups in the file =
> </DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV>I did a little experiment that does just this , and if I had a =
> match of=20
> variable dimension ID with group dimension ID I printed a message =
> like</DIV>
> <DIV> </DIV>
> <DIV>ncks: INFO nco_bld_dmn_ids_trv() traversing variable=20
> </g16/g16g1/lon1_var><BR>match <8> for var dim =
> <lon1> and=20
> group dim <lon1></DIV>
> <DIV> </DIV>
> <DIV>this tells me that for the variable =
> </g16/g16g1/lon1_var>=20
> </DIV>
> <DIV>I have a dimension with a *relative* name <lon1> and =
> a ID=20
> <8></DIV>
> <DIV>and that the IDs for variable dimensions and group dimensions are =
> the=20
> same </DIV>
> <DIV> </DIV>
> <DIV>Furthermore, I do not have duplicated dimension IDs, they are =
> nicely=20
> ordered from 0 to the number of unique dimensions in my file</DIV>
> <DIV>...so, it seems that dimension IDs are unique.</DIV>
> <DIV> </DIV>
> <DIV>If this is the case, this is good ...</DIV>
> <DIV> </DIV>
> <DIV>Is this the case ?</DIV>
> <DIV> </DIV>
> <DIV>but.. back to the original problem, the API is not =
> telling me=20
> the absolute location of the dimension</DIV>
> <DIV> </DIV>
> <DIV>that output just tells me that for the variable =20
> </g16/g16g1/lon1_var>, absolute location ,</DIV>
> <DIV> </DIV>
> <DIV>it tells me that *somewhere* in scope I have a dimension called =
> "lon1"=20
> and that has an ID=3D8</DIV>
> <DIV> </DIV>
> <DIV>Pedro</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial>------<BR>Pedro Vicente, Earth System =
>
> Science<BR>University of California, Irvine<BR><A=20
> =
> href=3D"http://www.ess.uci.edu/">http://www.ess.uci.edu/</A></FONT></DIV>=
>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial></FONT> </DIV>
> <BLOCKQUOTE=20
> style=3D"BORDER-LEFT: #000000 2px solid; PADDING-LEFT: 5px; =
> PADDING-RIGHT: 0px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px"=20
> dir=3Dltr>
> <DIV style=3D"FONT: 10pt arial">----- Original Message ----- </DIV>
> <DIV=20
> style=3D"FONT: 10pt arial; BACKGROUND: #e4e4e4; font-color: =
> black"><B>From:</B>=20
> <A title=3Dpvicente@xxxxxxx href=3D"mailto:pvicente@xxxxxxx">Pedro =
> Vicente</A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>To:</B> <A =
> title=3Dpvicente@xxxxxxx=20
> href=3D"mailto:pvicente@xxxxxxx">Pedro Vicente</A> ; <A=20
> title=3Dnetcdfgroup@xxxxxxxxxxxxxxxx=20
> =
> href=3D"mailto:netcdfgroup@xxxxxxxxxxxxxxxx">netcdfgroup@xxxxxxxxxxxxxxxx=
> </A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Sunday, March 03, 2013 =
> 8:42=20
> PM</DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Subject:</B> Re: [netcdfgroup] =
> How to find=20
> the full dimension names (paths withgroups) for a variable?</DIV>
> <DIV><BR></DIV>
> <DIV> </DIV>
> <DIV>Correction,</DIV>
> <DIV> </DIV>
> <DIV>"nc_inq_vardimid" is the function to get the dimension IDs for =
> the=20
> *variable*</DIV>
> <DIV> </DIV>
> <DIV>It is part of the "nc_inq_var" family</DIV>
> <DIV> </DIV>
> <DIV><BR><A=20
> =
> href=3D"http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c.html">h=
> ttp://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c.html</A></DIV>
> <DIV> </DIV>
> <DIV>this page does not mention the function in the top index , in =
> the list=20
> of Variables functions</DIV>
> <DIV> </DIV>
> <DIV><BR>From the Manual:</DIV>
> <DIV> </DIV>
> <DIV><BR>int nc_inq_vardimid (int ncid, int varid, int =
> dimids[]);</DIV>
> <DIV> </DIV>
> <DIV>ncid NetCDF ID, from a previous call to nc_open or =
> nc_create.<BR>varid=20
> Variable Id<BR>dimids Returned vector of *ndimsp dimension IDs =
> corresponding=20
> to the variable dimensions<BR>The caller must allocate enough space =
> for a=20
> vector of at least *ndimsp integers to be returned. <BR>The maximum =
> possible=20
> number of dimensions for a variable is given by the predefined =
> constant=20
> NC_MAX_VAR_DIMS.</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV>But this does not mention anything about the *location* of =
> these=20
> dimensions (location in the group hierarchy).</DIV>
> <DIV> </DIV>
> <DIV><BR>Can these IDs obtained with nc_inq_vardimid be =
> compared with=20
> the IDs obtained with the function that gets dimension IDs for =
> groups ?=20
> </DIV>
> <DIV> </DIV>
> <DIV>int nc_inq_dimid (int ncid, const char *name, int=20
> *dimidp);<BR>ncid<BR> NetCDF ID, from a previous =
> call to=20
> nc_open or nc_create.<BR>name<BR> Dimension=20
> name.<BR>dimidp<BR> Pointer to location for the =
> returned=20
> dimension ID. </DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV>that is, if I compare the nc_inq_vardimid variable dimension =
> IDs with=20
> the nc_inq_dimid dimension group IDs for *all* groups in the=20
> file (making sure that I get only the dimesion =
> IDs for=20
> that<BR>group at each iteration, not ancestor groups) ,<BR>then if =
> they have=20
> the same numerical value, that means that the matched dimension ID =
> from the=20
> variable is located in that particular group ?</DIV>
> <DIV> </DIV>
> <DIV>Do I have to traverse all the file , or just the groups that =
> are "in=20
> scope" of the variable ?</DIV>
> <DIV> </DIV>
> <DIV>I already have a list of all the objects in the file, that has =
> full=20
> group name for objects (groups and variables), this might be =
> easier<BR>than=20
> to build a "in scope" function, based in name comparison (Basically =
> what I=20
> did in that code I sent)</DIV>
> <DIV> </DIV>
> <DIV>Thanks</DIV>
> <DIV> </DIV>
> <DIV>Pedro</DIV>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial>------<BR>Pedro Vicente, Earth =
> System=20
> Science<BR>University of California, Irvine<BR><A=20
> =
> href=3D"http://www.ess.uci.edu/">http://www.ess.uci.edu/</A></FONT></DIV>=
>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV>PS: here's the function in its full glory :)</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> =
> <DIV>void &nbs=
> p;  =
> ; =20
> =
> <BR>nco_bld_dmn_trv =
> &=
> nbsp;=20
> /* [fnc] Build dimension info for all variables */<BR>(const int=20
> =
> nc_id, &=
> nbsp; =20
> /* I [ID] File ID */<BR> trv_tbl_sct * const=20
> trv_tbl) /* I/O =
> [sct] GTT=20
> (Group Traversal Table) */<BR>{<BR> /* Purpose: a netCDF4 =
> variable can=20
> have its dimensions located anywhere below *in the group =
> path*<BR> =20
> Construction of this list *must* be done after traversal table is =
> build in=20
> nco_grp_itr(),<BR> where we know the full picture of the file=20
> tree<BR> */</DIV>
> <DIV> </DIV>
> <DIV> char dmn_nm_var[NC_MAX_NAME];/* [sng] Dimension name for =
>
> variable */ <BR> char dmn_nm_grp[NC_MAX_NAME];/* [sng] =
> Dimension name=20
> for group */ </DIV>
> <DIV> </DIV>
> <DIV> const int=20
> flg_prn=3D1; /* =
> [flg]=20
> Dimensions in all parent groups will also be retrieved */ </DIV>
> <DIV> </DIV>
> <DIV> int dmn_id_grp[NC_MAX_DIMS]; /* [id] Dimensions IDs =
> array for=20
> group */<BR> int dmn_id_var[NC_MAX_DIMS]; /* [id] Dimensions =
> IDs array=20
> for variable */</DIV>
> <DIV> </DIV>
> <DIV> int=20
> =
> nbr_dmn_grp; &=
> nbsp; =20
> /* [nbr] Number of dimensions for group */<BR> int=20
> =
> nbr_dmn_var; &=
> nbsp; =20
> /* [nbr] Number of dimensions for variable */<BR> int=20
> =
> var_id; =
> =20
> /* [id] ID of variable */<BR> int=20
> =
> grp_id; =
> =20
> /* [id] ID of group */</DIV>
> <DIV> </DIV>
> <DIV> char=20
> =
> *ptr_chr; &nbs=
> p; =20
> /* [sng] Pointer to character '/' in full name */<BR> int=20
> =
> psn_chr;  =
> ; =20
> /* [nbr] Position of character '/' in in full name */</DIV>
> <DIV> </DIV>
> <DIV> /* Loop *object* traversal table */<BR> =
> for(unsigned=20
> uidx=3D0;uidx<trv_tbl->nbr;uidx++){<BR> =20
> if(trv_tbl->lst[uidx].nco_typ =3D=3D=20
> nco_obj_typ_var){<BR> trv_sct=20
> trv=3Dtrv_tbl->lst[uidx]; </DIV>
> <DIV> </DIV>
> <DIV> /* Obtain group ID using full =
> group name=20
> */<BR> =20
> (void)nco_inq_grp_full_ncid(nc_id,trv.grp_nm_fll,&grp_id);</DIV>
> <DIV> </DIV>
> <DIV> /* Obtain variable ID using =
> group ID=20
> */<BR> =20
> (void)nco_inq_varid(grp_id,trv.nm,&var_id);</DIV>
> <DIV> </DIV>
> <DIV> /* Get number of dimensions for =
> variable=20
> */<BR> =20
> (void)nco_inq_varndims(grp_id,var_id,&nbr_dmn_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Get dimension IDs for =
> variable=20
> */<BR> =20
> (void)nco_inq_vardimid(grp_id,var_id,dmn_id_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Obtain dimension IDs for =
> group. NB:=20
> go to parents */<BR> =20
> =
> (void)nco_inq_dimids(grp_id,&nbr_dmn_grp,dmn_id_grp,flg_prn);</DIV>
> <DIV> </DIV>
> <DIV> /* Loop over dimensions of =
> variable=20
> */<BR> for(int=20
> dmn_idx_var=3D0;dmn_idx_var<nbr_dmn_var;dmn_idx_var++){</DIV>
> <DIV> </DIV>
> <DIV> /* Get dimension =
> name=20
> */<BR> =20
> =
> (void)nco_inq_dimname(grp_id,dmn_id_var[dmn_idx_var],dmn_nm_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Now the exciting =
> part; we=20
> have to locate where "dmn_var_nm" is=20
> located<BR> 1) Dimensions =
> are=20
> defined in *groups*: find group where variable=20
> resides<BR> 2) Most common =
> case is=20
> for the dimension to be defined in the same group where variable=20
> is<BR> 3) If not, we have =
> to=20
> traverse the group back until the dimension name is found</DIV>
> <DIV> </DIV>
> <DIV> From: "Dennis =
> Heimbigner"=20
> <<A=20
> =
> href=3D"mailto:dmh@xxxxxxxxxxxxxxxx">dmh@xxxxxxxxxxxxxxxx</A>><BR>&nbs=
> p; =20
> Subject: Re: [netcdfgroup] defining dimensions in=20
> groups<BR> 1. The inner =
> dimension=20
> is used. The rule is to look up the group=20
> tree<BR> from innermost to =
> root=20
> and choose the first one that is=20
> found<BR> with a matching=20
> name.<BR> 2. The fact that =
> it is a=20
> dimension for a coordinate variable is not relevant for=20
> the<BR> =20
> choice.<BR> However, note =
> that=20
> this rule is only used by ncgen when disambiguating a=20
> reference<BR> in the =
> CDL. =20
> The issue does not come up in the netcdf API=20
> because<BR> you have to=20
> specifically supply the dimension id when defining the=20
> dimension<BR> for a=20
> variable.</DIV>
> <DIV> </DIV>
> <DIV> 4) Use case example: =
>
> /g5/g5g1/rz variable and rz(rlev), where dimension "rlev" resides in =
>
> /g5/rlev <BR> */</DIV>
> <DIV> </DIV>
> <DIV> /* Loop over =
> dimensions of=20
> group *and* parents */<BR> =
> for(int=20
> dmn_idx_grp=3D0;dmn_idx_grp<nbr_dmn_grp;dmn_idx_grp++){</DIV>
> <DIV> </DIV>
> <DIV> /* Get =
> dimension=20
> name for group =
> */<BR> =20
> =
> (void)nco_inq_dimname(grp_id,dmn_id_grp[dmn_idx_grp],dmn_nm_grp);</DIV>
> <DIV> </DIV>
> <DIV> /* Does=20
> dimension name for *variable* match dimension name for *group* ? */=20
> <BR> =20
> if(strcmp(dmn_nm_var,dmn_nm_grp) =3D=3D 0){</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Now...we know that *somewhere* for all this group dimensions one is =
> the real=20
> deal =
> <BR> =20
> Attempt to construct a *possible* full dimension name and compare =
> with the=20
> table dimension=20
> =
> list<BR>  =
> ;=20
> until a full name match is found ... */</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Was the dimension found?: handy in all this *tortured* logic; needs=20
> revision, but works !=20
> =
> */<BR> =
>
> nco_bool dmn_was_found=3DFalse;</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Construct *possible* dimension full name=20
> =
> */<BR> =
>
> char=20
> =
> *dmn_nm_fll=3D(char*)nco_malloc(strlen(trv.grp_nm_fll)+strlen(dmn_nm_var)=
> +2L);<BR> &nbs=
> p;=20
> =
> strcpy(dmn_nm_fll,trv.grp_nm_fll);<BR>  =
> ; =20
> if(strcmp(trv.grp_nm_fll,"/"))=20
> =
> strcat(dmn_nm_fll,"/");<BR> &nbs=
> p; =20
> strcat(dmn_nm_fll,dmn_nm_var);</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Brute-force approach to find valid=20
> =
> "dmn_nm_fll":<BR> &n=
> bsp; =20
> Start at grp_nm_fll/dmn_nm_var and build all possible paths with =
> dmn_nm_var.=20
> =
> <BR> =
> Use=20
> cases=20
> =
> are:<BR>  =
> ;=20
> Real life output of: ncks --get_grp_info =20
> =
> ~/nco/data/in_grp.nc<BR> &=
> nbsp; =20
> /g1/lon: 1 dimensions: /lon :=20
> =
> <BR> =20
> /g5/g5g1/rz: 1 dimensions: /g5/rlev :=20
> =
> <BR> =20
> /g10/three_dmn_rec_var: 3 dimensions: /time : /lat : /lon=20
> : =20
> =
> <BR> =20
> */</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Find last occurence of '/'=20
> =
> */<BR> =
>
> =
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');<BR>  =
> ; =20
> psn_chr=3Dptr_chr-dmn_nm_fll;</DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> While there is a possible dimension path=20
> =
> */<BR> =
>
> while(ptr_chr && !dmn_was_found){</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Search table dimension list=20
> =
> */<BR> &=
> nbsp; =20
> for(unsigned int=20
> =
> dmn_lst_idx=3D0;dmn_lst_idx<trv_tbl->nbr_dmn;dmn_lst_idx++){<BR>&nb=
> sp; &nbs=
> p; =20
> dmn_fll_sct dmn_fll=3Dtrv_tbl->lst_dmn[dmn_lst_idx]; </DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Does the *possible* dimension full name match a *real* dimension =
> full=20
> name ?=20
> =
> */<BR> &=
> nbsp; =20
> if(strcmp(dmn_fll.nm_fll,dmn_nm_fll) =3D=3D 0){</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Store full dimension name =20
> =
> */<BR> &=
> nbsp; =20
> =
> trv_tbl->lst[uidx].var_dmn[dmn_idx_var].dmn_nm_fll=3Dstrdup(dmn_nm_fll=
> );</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* The relative dimension name was already stored =20
> =
> */<BR> &=
> nbsp; =20
> =
> assert(strcmp(trv_tbl->lst[uidx].var_dmn[dmn_idx_var].dmn_nm,dmn_nm_va=
> r)=20
> =3D=3D 0);</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Store full group name where dimension is located. NOTE: using =
> member=20
> "grp_nm_fll" of dimension =20
> =
> */<BR> &=
> nbsp; =20
> =
> trv_tbl->lst[uidx].var_dmn[dmn_idx_var].grp_nm_fll=3Dstrdup(dmn_fll.gr=
> p_nm_fll);</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Free allocated=20
> =
> */<BR> &=
> nbsp; =20
> dmn_nm_fll=3D(char *)nco_free(dmn_nm_fll);</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Found=20
> =
> */<BR> &=
> nbsp; =20
> dmn_was_found=3DTrue;</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Exit table dimension list loop=20
> =
> */<BR> &=
> nbsp; =20
> =
> break;<BR> &nb=
> sp; =20
> } /* End Does the *possible* dimension full name match a *real* =
> dimension=20
> full name=20
> =
> */<BR> &=
> nbsp; =20
> } /* End Search table dimension list loop */</DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* Keep on trying... Re-add dimension name to shortened path */ =
> </DIV>
> <DIV> </DIV>
> =
> <DIV> &n=
> bsp; =20
> /* If a valid (pointer) name here, then the constructed name was not =
> found=20
> =
> */<BR> &=
> nbsp; =20
> if(dmn_nm_fll)=20
> =
> {<BR> &n=
> bsp; =20
> =
> dmn_nm_fll[psn_chr]=3D'\0';<BR> =
> =20
> =
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');<BR>  =
> ; =20
> =
> if(ptr_chr){<BR> &nb=
> sp; =20
> =
> psn_chr=3Dptr_chr-dmn_nm_fll;<BR> &nbs=
> p; =20
> =
> dmn_nm_fll[psn_chr]=3D'\0';<BR> =
> =20
> if(strcmp(dmn_nm_fll,"/"))=20
> =
> strcat(dmn_nm_fll,"/");<BR> &nbs=
> p; =20
> =
> strcat(dmn_nm_fll,dmn_nm_var);<BR> &nb=
> sp; =20
> =
> ptr_chr=3Dstrrchr(dmn_nm_fll,'/');<BR>  =
> ; =20
> =
> psn_chr=3Dptr_chr-dmn_nm_fll;<BR> &nbs=
> p; =20
> } /* !ptr_chr=20
> =
> */<BR> &=
> nbsp; =20
> } /* If dmn_nm_fll=20
> =
> */<BR> =
> }=20
> /* End While there is a possible dimension path */ </DIV>
> <DIV> </DIV>
> =
> <DIV> =
> /*=20
> Free allocated (this should never happen here; a dimension must =
> always be=20
> found)=20
> =
> */<BR> =
>
> if(dmn_nm_fll) dmn_nm_fll=3D(char *)nco_free(dmn_nm_fll);</DIV>
> <DIV> </DIV>
> <DIV> } /* End =
> Does=20
> dimension name for variable match dimension name for group ? =20
> */<BR> } /* End Loop over=20
> dimensions of group *and* parents =
> */<BR> } /*=20
> End Loop over dimensions of variable */<BR> } /* =
> End=20
> object is variable nco_obj_typ_var */<BR> } /* End Loop =
> *object*=20
> traversal table */</DIV>
> <DIV> </DIV>
> <DIV><BR>} /* end nco_blb_dmn_trv() */</DIV>
> <DIV> </DIV>
> <DIV> </DIV>
> <DIV><FONT size=3D2 face=3DArial></FONT> </DIV>
> <BLOCKQUOTE=20
> style=3D"BORDER-LEFT: #000000 2px solid; PADDING-LEFT: 5px; =
> PADDING-RIGHT: 0px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px">
> <DIV style=3D"FONT: 10pt arial">----- Original Message ----- =
> </DIV>
> <DIV=20
> style=3D"FONT: 10pt arial; BACKGROUND: #e4e4e4; font-color: =
> black"><B>From:</B>=20
> <A title=3Dpvicente@xxxxxxx href=3D"mailto:pvicente@xxxxxxx">Pedro =
> Vicente</A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>To:</B> <A=20
> title=3Dnetcdfgroup@xxxxxxxxxxxxxxxx=20
> =
> href=3D"mailto:netcdfgroup@xxxxxxxxxxxxxxxx">netcdfgroup@xxxxxxxxxxxxxxxx=
> </A>=20
> </DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Sunday, March 03, =
> 2013 5:10=20
> PM</DIV>
> <DIV style=3D"FONT: 10pt arial"><B>Subject:</B> [netcdfgroup] How =
> to find=20
> the full dimension names (paths withgroups) for a variable?</DIV>
> <DIV><BR></DIV>
> <DIV><FONT size=3D2 face=3DArial><BR><FONT size=3D3>Hi netCDF =
> team</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>This email is rather long, so please bear with =
> me=20
> ...</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>The short read and main question =
> is:</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>How to find the full dimension names (paths =
> with groups)=20
> for all dimensions that a variable has?</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Example:<BR>Note: Incomplete CDL =
> syntax</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>group: g16 { <BR> =20
> dimensions:<BR> lon1=3D4; //dimension that =
> has a=20
> coordinate variable down in scope at /g16/g16g1/lon1(lon1)=20
> <BR> <BR> group: g16g1 {=20
> <BR> =
> variables:<BR> float=20
> lon1(lon1); //coordinate variable /g16/g16g1/lon1 that has =
> dimension=20
> (/g16/lon1) in scope<BR> float =
> lon1_var(lon1); //=20
> variable /g16/g16g1/lon1_var that has dimension (/g16/lon1) in =
> scope *and*=20
> coordinate (/g16/g16g1/lon1) in scope<BR> =20
> <BR> data:<BR> =20
> lon1=3D0.,1.,2.,3.;<BR> =
> lon1_var=3D0.,1.,2.,3.; =20
> <BR> <BR> <BR>Note =
> that=20
> coordinate variables can share dimensions; here's a case of a =
> "parallel"=20
> group /g16/g16g2/ of /g16/g16g1/<BR>where variables have their own =
> local=20
> coordinate variable that share the ancestor dimension=20
> (/g16/lon1)</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3> group: g16g2 {=20
> <BR> =
> variables:<BR> =20
> //coordinate variable (/g16/lon1)<BR> =
> float=20
> lon1(lon1); <BR> float =
> lon1_var(lon1); =20
> </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3> <BR>It is possible to =
> construct=20
> other cases, variables with n dimensions, each one defined =
> in=20
> different groups (and each one of these dimensions can have =
> coordinate=20
> <BR>variables in *other* different groups )</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><BR><FONT size=3D3>More broadly, I am trying to construct a =
> model for=20
> ncks of a netCDF4 file that includes :</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>1) A list of all "objects" in the =
> file</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>I call an "object" what I call an object in =
> HDF5: either=20
> a group or a variable (a variable is commonly called in HDF5 a =
> "dataset"=20
> ).</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>2) netCDF4 has dimensions. HDF5 does not =
> (Let's ignore=20
> HDF5 dimension scales for now, to keep this simple... Coincidently =
> netCDF4=20
> *happens* to use HDF5<BR>dimension scales in its inner model, but =
> my=20
> understanding is that it did not had to be that way... I think. =
> Imagine=20
> for example that HDF5 dimension scales did not exist...<BR>It =
> would be=20
> perfectly possible for netCDF4 to use HDF5 as the underlying =
> format...=20
> HDF5 dimension scales are not part of the HDF5 format, they<BR>are =
> just an=20
> abstraction layer build above HDF5 with a so called "High Level" =
> API....=20
> At the time the requirement was for HDF5 to have <BR>the =
> equivalent of=20
> HDF(4) "coordinate variables", that could be shared between HDF5=20
> datasets)</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>excellent article about dimension scales =
> </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><A=20
> =
> href=3D"http://www.unidata.ucar.edu/blogs/developer/en/entry/netcdf4_shar=
> ed_dimensions">http://www.unidata.ucar.edu/blogs/developer/en/entry/netcd=
> f4_shared_dimensions</A></DIV>
> <DIV> </DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Let's call these netCDF4 dimensions, "unique=20
> dimensions".<BR>These are defined in groups.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>3) This model stores *full names* of things: =
> full names,=20
> for groups, variables and unique dimensions. Also, full names for=20
> coordinate variables.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>4) Coordinate variables.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>From the netCDF manual</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>"It is legal for a variable to have the same =
> name as a=20
> dimension. Such variables have no<BR>special meaning to the netCDF =
>
> library. However there is a convention that such =
> variables<BR>should be=20
> treated in a special way by software using this library.<BR>A =
> variable=20
> with the same name as a dimension is called a coordinate=20
> variable."</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><BR><FONT size=3D3>Dimensions and coordinate variables are =
> used by=20
> variables. So, variables must know where dimensions and coordinate =
>
> variables (if existent for that variable) are.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Example of an output, that prints either a =
> dimension or=20
> a coordinate variable for any variable</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>/g16/g16g1/lon1 ---> coordinate =
> variable=20
> <BR>lon1[0]=3D0 <BR>lon1[1]=3D1 <BR>lon1[2]=3D2 =
> <BR>lon1[3]=3D3</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>/g16/g16g1/lon1_var ---> variable with =
> coordinate=20
> variable <BR>lon1[0]=3D0 lon1_var[0]=3D0 <BR>lon1[1]=3D1 =
> lon1_var[1]=3D1=20
> <BR>lon1[2]=3D2 lon1_var[2]=3D2 <BR>lon1[3]=3D3 lon1_var[3]=3D3 =
> </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>The API function that returns a dimension name =
> for a=20
> variable is</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>From the netCDF C manual</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><A=20
> =
> href=3D"http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005f=
> inq_005fdim-Family.html#nc_005finq_005fdim-Family"><FONT=20
> =
> size=3D3>http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005=
> finq_005fdim-Family.html#nc_005finq_005fdim-Family</FONT></A></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>int nc_inq_dimname (int ncid, int dimid, char=20
> *name);<BR>ncid NetCDF ID, from a previous call to nc_open or=20
> nc_create.<BR>dimid Dimension ID, from a previous call to nc_inq =
> dimid or=20
> nc_def_dim.<BR>name Returned dimension name.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Note: here "ncid" is actually a "location" ID =
> (either a=20
> group or the main netCDF file ID), so I think you should change =
> this in=20
> the documentation</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>The "dimid" parameter is an ID of a=20
> dimension.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>This is obtained with the API =
> function</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>int nc_inq_dimid (int ncid, const char *name, =
> int=20
> *dimidp);<BR>ncid NetCDF ID, from a previous call to nc_open or=20
> nc_create.<BR>name Dimension name.<BR>dimidp Pointer to location =
> for the=20
> returned dimension ID.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>From the manual:<BR>"When searching for a =
> dimension, the=20
> specified group is searched, and then its parent group,<BR>and =
> then its=20
> grandparent group, etc., up to the root group."</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Ok, great, the dimension ID "dimidp" can be in =
> a=20
> ancestor group, but how to know where?</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><BR><FONT size=3D3>My understanding is that netCDF4 group IDs =
> are=20
> "unique"; dimension IDs are not, they can have duplicated values =
> in=20
> several groups.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>In the above call nc_inq_dimid, dimension IDs =
> in=20
> ancestor groups are returned, but duplicates may happen. =
> </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>I think storing IDs, even unique group IDs, in =
> the model=20
> above is a recipe for disaster. <BR>I see IDs as an equivalent of =
> the=20
> paper ticket number I am given when I take the train and want to =
> keep my=20
> luggage at a station for a while.<BR>When I get my bags back, I =
> dispose=20
> the ticket number. <BR>That ticket is helpful for the person that =
> has to=20
> identify my bags only. </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>As a developer, for debugging purposes, or =
> even as a=20
> netCDF4 user, it is also much easier to identify something by name =
> than by=20
> ID.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Possible ways to solve this (to get full =
> dimension name=20
> for a variable):</FONT></DIV>
> <DIV><BR><FONT size=3D3>1) Iterate ancestor groups, get all =
> variables for=20
> each group, get variables dimension IDs, and compare with group =
> dimension=20
> Ids ?<BR>2) Iterate ancestor groups, try to construct a possible =
> full=20
> dimension name and match ?</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Below is some code sample that tries to solve =
> this using=20
> option 2) above, </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>But as a netCDF API user, I don't think that I =
> should=20
> have to do this, mainly because it could just be wrong (it could =
> not cover=20
> all cases, for example).</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>What I think is needed here is a new API =
> function=20
> that returns the *full* dimension names for all dimensions used by =
> a=20
> variable, instead of an ID and relative name only.<BR>With =
> information if=20
> that dimension "name" is a coordinate variable or just a =
> dimension.=20
> </FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Would it be possible for the netCDF group to =
> supply this=20
> function?</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>There is a similar function for =
> groups:</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><A=20
> =
> href=3D"http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005f=
> inq_005fgrpname_005ffull.html#nc_005finq_005fgrpname_005ffull"><FONT=20
> =
> size=3D3>http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005=
> finq_005fgrpname_005ffull.html#nc_005finq_005fgrpname_005ffull</FONT></A>=
> </DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>int nc_inq_grpname_full(int ncid, size_t =
> *lenp, char=20
> *full_name);<BR>ncid The group id for this=20
> operation.<BR>full_name<BR>Pointer to allocated space of correct=20
> length.</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>That returns the *full name* of the group from =
> the group=20
> ID, this is one of the most helpful functions to construct this =
> "full=20
> path" model</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Thanks for your help</FONT></DIV>
> <DIV><FONT size=3D3></FONT> </DIV>
> <DIV><FONT size=3D3>Pedro</FONT></FONT></DIV>
> <DIV><FONT face=3DArial></FONT> </DIV>
> <DIV><FONT face=3DArial></FONT> </DIV>
> <DIV><FONT face=3DArial>------<BR>Pedro Vicente, Earth System=20
> Science<BR>University of California, Irvine<BR><A=20
> =
> href=3D"http://www.ess.uci.edu/">http://www.ess.uci.edu/</A></FONT></DIV>=
>
> <DIV><FONT face=3DArial></FONT> </DIV>
> <DIV><FONT face=3DArial></FONT> </DIV>
> <DIV><FONT face=3DArial>PS: here's the code that tries to find =
> full=20
> dimension names</FONT></DIV>
> <DIV> </DIV><FONT face=3DArial>
> <DIV><BR>/* Loop *object* traversal table */<BR> =
> for(unsigned=20
> uidx=3D0;uidx<trv_tbl->nbr;uidx++){<BR> =20
> if(trv_tbl->lst[uidx].nco_typ =3D=3D=20
> nco_obj_typ_var){<BR> trv_sct=20
> trv=3Dtrv_tbl->lst[uidx]; </DIV>
> <DIV> </DIV>
> <DIV> /* Obtain group ID using full =
> group=20
> name */<BR> =20
> =
> (void)nco_inq_grp_full_ncid(nc_id,trv.grp_nm_fll,&grp_id);</DIV>
> <DIV> </DIV>
> <DIV> /* Obtain variable ID using =
> group ID=20
> */<BR> =20
> (void)nco_inq_varid(grp_id,trv.nm,&var_id);</DIV>
> <DIV> </DIV>
> <DIV> /* Get number of dimensions =
> for=20
> variable */<BR> =20
> (void)nco_inq_varndims(grp_id,var_id,&nbr_dmn_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Get dimension IDs for =
> variable=20
> */<BR> =20
> (void)nco_inq_vardimid(grp_id,var_id,dmn_id_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Obtain dimension IDs for =
> group. NB:=20
> go to parents */<BR> =20
> =
> (void)nco_inq_dimids(grp_id,&nbr_dmn_grp,dmn_id_grp,flg_prn);</DIV>
> <DIV> </DIV>
> <DIV> /* Loop over dimensions of =
> variable=20
> */<BR> for(int=20
> dmn_idx_var=3D0;dmn_idx_var<nbr_dmn_var;dmn_idx_var++){</DIV>
> <DIV> </DIV>
> <DIV> /* Get dimension =
> name=20
> */<BR> =20
> =
> (void)nco_inq_dimname(grp_id,dmn_id_var[dmn_idx_var],dmn_nm_var);</DIV>
> <DIV> </DIV>
> <DIV> /* Now the =
> exciting part;=20
> we have to locate where "dmn_var_nm" is=20
> located<BR> 1) =
> Dimensions are=20
> defined in *groups*: find group where variable=20
> resides<BR> 2) Most =
> common case=20
> is for the dimension to be defined in the same group where =
> variable=20
> is<BR> 3) If not, we =
> have to=20
> traverse the group back until the dimension name is found</DIV>
> <DIV> </DIV>
> <DIV> From: "Dennis =
> Heimbigner"=20
> <<A=20
> =
> href=3D"mailto:dmh@xxxxxxxxxxxxxxxx">dmh@xxxxxxxxxxxxxxxx</A>><BR>&nbs=
> p; =20
> Subject: Re: [netcdfgroup] defining dimensions in=20
> groups<BR> 1. The inner=20
> dimension is used. The rule is to look up the group=20
> tree<BR> from innermost =
> to root=20
> and choose the first one that is=20
> found<BR> with a =
> matching=20
> name.<BR> 2. The fact =
> that it is=20
> a dimension for a coordinate variable is not relevant for=20
> the<BR> =20
> choice.<BR> However, =
> note that=20
> this rule is only used by ncgen when disambiguating a=20
> reference<BR> in the =
> CDL. =20
> The issue does not come up in the netcdf API=20
> because<BR> you have to=20
> specifically supply the dimension id when defining the=20
> dimension<BR> for a=20
> variable.</DIV>
> <DIV> </DIV>
> <DIV> 4) Use case =
> example:=20
> /g5/g5g1/rz variable and rz(rlev), where dimension "rlev" resides =
> in=20
> /g5/rlev <BR> */</DIV>
> <DIV> </DIV>
> <DIV> /* Loop over =
> dimensions of=20
> group *and* parents =
> */<BR> =20
> for(int =
> dmn_idx_grp=3D0;dmn_idx_grp<nbr_dmn_grp;dmn_idx_grp++){</DIV>
> <DIV> </DIV>
> <DIV> /* Get =
>
> dimension name for group=20
> */<BR> =20
> =
> (void)nco_inq_dimname(grp_id,dmn_id_grp[dmn_idx_grp],dmn_nm_grp);</DIV>
> <DIV> </DIV>
> <DIV> /* =
> Does=20
> dimension name for *variable* match dimension name for *group* ? =
> */=20
> <BR> =20
> if(strcmp(dmn_nm_var,dmn_nm_grp) =3D=3D 0){</DIV>
> <DIV> </DIV>
> <DIV></FONT> </DIV>
> <DIV><FONT face=3DArial></FONT> </DIV>
> <P>
> <HR>
>
> =
> <P></P>_______________________________________________<BR>netcdfgroup=20
> mailing list<BR>netcdfgroup@xxxxxxxxxxxxxxxx<BR>For list =
> information or to=20
> unsubscribe, visit:=20
> http://www.unidata.ucar.edu/mailing_lists/</BLOCKQUOTE></BLOCKQUOTE>
> <P>
> <HR>
>
> <P></P>_______________________________________________<BR>netcdfgroup =
> mailing=20
> list<BR>netcdfgroup@xxxxxxxxxxxxxxxx<BR>For list information or to=20
> unsubscribe, visit:=20
> http://www.unidata.ucar.edu/mailing_lists/</BLOCKQUOTE></BODY></HTML>
>
> ------=_NextPart_000_0013_01CE1883.8BB35050--
>
>
> --===============0004655921==
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline
>
> _______________________________________________
> netcdfgroup mailing list
> netcdfgroup@xxxxxxxxxxxxxxxx
> For list information or to unsubscribe, visit: http://www.unidata.ucar.edu/m
> ailing_lists/
> --===============0004655921==--