NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.

Re: global map attributes

Hi gary:
Thanks for your contributions. Below are some questions and comments:

> 
> ----------------------------------------------------------------------------
> 
> A first example is a 3-D temperature grid for an ocean model. (I'm just a
> programmer so the real-life applicability of the examples may be off. :)
> Suppose the grid is curvilinear with sigma levels, defined with dimensions
> (i, j, k). But for analysis or plotting the grid may need to be viewed over
> lat/lon and either sigma or depth for the height, where the lat, lon, sigma,
> and depth mappings are stored directly in the file as variables. Lat and lon
> depend upon the (j,k) coordinate, depth depends upon (i,j,k), sigma depends
> upon (i).
> 
>    * lat(j,k)
>    * lon(j,k)
>    * depth(i,j,k)
>    * sigma(i)
> 
> There are at least four coordinate systems which associate the manifold
> domain with an alternate base domain (using the wording Steve mentioned),
> including the identity coordinate system.
> 
>  (i,j,k) => (depth, lon, lat)
>  (i,j,k) => (sigma, lon, lat)
>  (i,j,k) => (i, lon, lat)
>  (i,j,k) => (i,j,k)
> 
> So to associate each alternate mapping with the temperature variable, each
> mapping is named in the temp variable's temp attribute (except for the
> identity since it's implicit):
> 
>         float temp(i, j, k);
>                 temp:temp = "depth-map sigma-map lat-lon-map";
> 
> The mapping name refers to a global attribute which lists the coordinates of
> the system. I appended -map to the names for clarity; I'm not suggesting the
> convention require it.
> 
>         :depth-map = "depth lon lat";
>         :sigma-map = "sigma lon lat";
>         :lat-lon-map = "lon lat";
>         :sigma = "sigma";
> 
>         float lat(j, k);
>         float lon(j, k);
>         float sigma(i);
>         float depth(i,j,k);
>                 depth:depth = "sigma";
> 
> Each coordinate name in a global map attribute refers to the variable which
> maps to the values of that coordinate. There is some important consistency
> here: a variable is always a mapping (from N-space to the 1-D range of the
> variable), and the global map attributes are always used to specify the
> components or range for a mapping, e.g., the coordinates of a coordinate
> system.

I would restate as: "a variable and a coord sys for the variable can both be
considered functions on (more or less) the same index domain". I just wanted to
check if you are saying more?

> 
> Note that the lat-lon-map is independent of the i coordinate, in which case
> the i coordinate is added to the lat-lon-map as an identity mapping of the
> indices along i. E.g., point (1,1,1) of temp is at coordinate (1, -105.0,
> 40.1) in the lat-lon-map coordinate system, point (2,j,k) is at (2,
> lon(j,k), lat(j,k)).
> 
> A user or application can deduce the coordinates on the depth grid of point
> (i,j,k) by calculating (depth(i,j,k), lon(j,k), lat(j,k)). Choosing
> sigma-map yields (sigma(i), lon(j,k), lat(j,k)).
> 
> The sigma global map attribute indicates that it makes sense to plot depth
> along a sigma axis, using the values of the sigma variable as the axis
> coordinates. This is an example of the recursiveness allowed by the
> convention. The temp variable's temp attribute can be followed to the
> depth-map mapping, which points to the depth variable. But the depth
> variable itself has an alternate coordinate system, sigma, whose global map
> attribute refers directly to the sigma variable. Through this recursion an
> application could infer the availability of the sigma-map mapping without it
> being explicitly named in the temp attribute.

I dont understand what the point of the lat-lon map or the sigma-map coord
systems are. It seems like they are implied by the depth-map and the 
sigma-map coord systems?

Also, the need for the identity coord function is not obvious. I would just 
say that the lat-lon coord sys is not complete. I am also noticing that the
identity coord function doesnt really "assign a physical value", which is
my definition of a coord system.  I acknowledge you might need it now and
then for ill-specified files, but I dont really think it deserves much of
a place in our conventions.


> 
> Note that this example doesn't change much if some of the variables are
> dependent upon time. If the lat and lon variable mappings are static, the
> coordinate systems would look like below.
> 
> dimensions:
>         time (UNLIMITED);
>         i = 10;
>         j = 100;
>         k = 100;
> 
> variables:
> 
>         float time(time);
>         float temp(time, i, j, k);
>                 temp:temp = "depth-map sigma-map lat-lon-map";
>         float salinity(time, i, j, k);
>                 temp:temp = "depth-map sigma-map lat-lon-map";
>         float density(time, i, j, k);
>                 temp:temp = "depth-map sigma-map lat-lon-map";
>         float depth(time, i,j,k);
>                 depth:depth = "sigma";
>         float lat(j, k);
>         float lon(j, k);
>         float sigma(i);
> 
>         :depth-map = "depth lon lat";
>         :sigma-map = "sigma lon lat";
>         :lat-lon-map = "lon lat";
>         :sigma = "sigma";
>         :time = "time";
> 
> The time mapping attribute is essentially an encoding of the usual
> interpretation of 1-D coordinate variables. For backwards compatibility, the
> existence of a coordinate variable could imply this attribute. Since none of
> the alternate mappings for temp depend upon the time coordinate, time is
> looked up as its own mapping, and the time global attribute refers back to
> the time variable.
> 
> The temp coordinate systems could also be named "more completely" as
> follows:
> 
>         :depth-map = "time depth lon lat";
>         :sigma-map = "time sigma lon lat";
>         :lat-lon-map = "time i lon lat";
> 
> This is perhaps clearer and might be preferred by some users. The i
> component in the lat-lon-map does not refer to another variable or mapping,
> so it reverts to the identity mapping from the domain of the i coordinate.
> (The identity mapping is effectively the default coordinate system for a
> dimension.)
> 
> Comments
> 
> I thought about allowing the mapping names to refer directly to the
> variable's attributes rather a global attribute, but in my opinion it's
> better to make a mapping name unique for the whole file and avoid allowing
> conflicting uses of map names between variables. I also considered letting a
> mapping name refer directly to a variable name, so that these global
> attributes would be unnecessary.
> 
>         :sigma = "sigma";
>         :time = "time";
> 
> But that violates the orthogonality and consistency of mapping names always
> being global attributes. I think some confusion could be avoided by naming
> every mapping explicitly as a global attribute, even those mappings
> currently implied by the coordinate variable convention.

I think its important to have global specification with variable override.
Imagine you have a file with 150 variables in it, and you have to specify the 
coord
sys for each individual variable. Now you have a ncdump output: gotta check 
each one
to see if they are the same (barf) ! On the other hand, if you have three 
variables
each with a different coord system, its more compact to specify at the variable 
level.

> 
> Lastly, there is nothing preventing an application from merging alternate
> mappings of a variable. The temperature mappings could be listed as follows:
> 
>         float temp(time, i, j, k);
>                 temp:temp = "time depth-map sigma-map lat-lon-map";
> 
>         :depth-map = "depth";
>         :sigma-map = "sigma";
>         :lat-lon-map = "lon lat";
>         :sigma = "sigma";
>         :time = "time";
> 
> An application could assemble all possible combinations of mappings and
> their coordinates, and in any order, including:
> 
>  (time(time), i, j, k)
>  (time(time), sigma(i), j, k)
>  (time(time), depth(time,i,j,k), lat(j,k), lon(j,k))
>  (lat(j,k), lon(j,k), i, time)
>  (i, j, k, time(time), sigma(i), depth(time,i,j,k), lon(j,k), lat(j,k))
> 
> The last mapping, consisting of the intersection of all of the possible
> coordinate systems, might be useful for a table. (A really, really, big
> table. :) The mappings which can be described with this convention are
> merely a superset of those possible with the proposed coordinates
> referential attribute, which essentially lists the independent variables of
> each alternate coordinate system for a variable. I'm merely suggesting an
> extension of the referential idea to allow naming specific sets of
> coordinates, so that each coordinate set can completely and more intuitively
> describe a base coordinate system, not just for one variable but for the
> whole file.

I really think this is the wrong way to go, but as I see that you basically 
argue 
against it below, I'll assume you agree. But by saying that you would allow it I
think you confuse whether you are listing coordinate systems or coordinate 
functions (I think "independent variables" is not true). All your good examples
I think list coord systems.  

> 
> ----------------------------------------------------------------------------
> 
> Examples
> 
> Wire Coil
> 
> Here's Steve's wire coil example using the above ideas. I added two
> coordinate systems for the wire temperature: the physical distance along the
> wire and the cartesian coordinates.
> 
>     dimensions:
>         s = 100;
> 
>     variables:
>         float temp(s);  // temperature along spiral
>             temp:temp = "distance-map cylinder-map cartesian-map"
>         float rho(s);   // distance from CCS center axis
>         float theta(s); // CCS azimuth
>         float z(s);     // CCS height
>         float distance(s);
>                 distance:units = "cm";
>         float y(s);
>         float x(s);
> 
>         // physical distance along wire
>         :distance-map = "distance"
>         // cylindrical coordinate system (CCS)
>         :cylinder-map = "z rho theta";
>         // Cartesian map
>         :cartesian-map = "z y x";

this is good.

> 
> Rectilinear Grid
> 
> The simple coordinate variable case for a rectilinear grid
> 
>         float temp(lat,lon);
>         float lat(lat);
>         float lon(lon);
> 
> becomes:
> 
>         float temp(time,lat,lon);
>                 temp:temp = "world-map";
>         float lat(lat);
>         float lon(lon);
>         :world-map = "lon lat";
> 
> The lat and lon dimensions could be renamed without affecting the
> association described. Since the lat and lon mappings are independent of
> each other in this case, this example could boil down to exactly the
> previous referential attribute examples, except the usual coordinate
> variable convention has been made explicit with a global map attribute:
> 
>         float temp(time,lat,lon);
>                 temp:temp = "lat lon";
>         float lat(lat);
>         float lon(lon);
>         :lat = "lat";
>         :lon = "lon";
> 
> Comparisons to coordinates Attribute
> 
> The temp mappings in the wire coil example can be replaced with their
> constituent coordinates (variables), similar to the Walker and Waring
> example and to Signell's independent variables:
> 
> >       double salt(n,k,j,i);
> >             salt:long_name = "Salinity";
> >             salt:units = "1";
> >             salt:coordinates = "t cell_z cell_y cell_x cell_lat
> 
>                 temp:temp = "distance z rho theta y x"
> 
> An application can generate all possible combinations of the mappings,
> "factor out" (Russ' words) coordinates where possible and if desired, and
> allow a user to choose the ones which make most sense. However, using the
> global coordinate attribute allows the sensible mappings to be explicitly
> named once for a file and referred to directly in each variable, and the
> availability of "common" coordinate systems is more immediately evident to
> the user. Also, the first mapping in a variable's referential attribute can
> designate the default coordinate system.
> 
> Also, I'd prefer using a global attribute over using variable attributes
> with the same name as the corresponding dimension. Several fields with the
> same "manifold" domain would each need attributes for each dimension,
> instead of naming a single mapping in a single variable attribute. A global
> map attribute would be unique for the whole file, whereas dimension
> attributes among different variables would be redundant and could
> contradict. Russ gave similar arguments and others in support of the global
> dimension attribute.
> 
> >From John Caron's comments about Walker and Waring:
> >
> > One part of their example I disagree with is lumping all of the
> > coordinate functions together:
> >       double salt(n,k,j,i);
> >             salt:long_name = "Salinity";
> >             salt:units = "1";
> >             salt:coordinates = "t cell_z cell_y cell_x cell_lat
> > cell_lon";
> >
> > While there's nothing illegal about it, better is:
> >             salt:coordinates_xy = "t cell_z cell_y cell_x";
> >             salt:coordinates_latlon = "t cell_z cell_lat cell_lon";
> > emphasizing that you are specifying two coordinate systems.
> 
> I would agree with John, but I'd suggest this construction:
> 
>         double salt(n,k,j,i);
>                 salt:long_name = "Salinity";
>                 salt:units = "1";
>                 salt:salt = "lat-lon-map cartesian-map";
> 
>         :lat-lon-map = "t cell_z cell_lat cell_lon";
>         :cartesian-map = "t cell_z cell_y cell_x";
> 
> The coordinate systems are explicit, and they only need to be specified once
> rather than for each variable.

your formulation would be acceptable; i'm not convinced that the temp:temp part
is worth the trouble; theres nothing to suggest such an attribute should point
to a coordinate system. The tradeoff is explicitness (eg an attribute 
"coordinate")
vs avoiding "english-centricity". 

also i dont really agree/understand the notion of "factoring out".

> 
> Boundary Layers
> 
> Russ' boundary layer example using referential attributes, converted to
> global map attributes:
> 
>     dimensions:
> 
>         bndlay = 5 ;           // boundary layers
>         lon =  93 ;
>         lat =  65 ;
> 
>     variables:
> 
>         float   RH_bndlay(bndlay, lat, lon) ;
>                 RH_bndlay:long_name = "relative humidity in boundary layer" ;
>                 RH_bndlay:units = "percent" ;
>                 RH_bndlay:RH_bndlay = "boundary-map";
> 
>         float   bndlay_bot(bndlay) ;
>                 bndlay_bot:long_name = "bottom of layer" ;
>                 bndlay_bot:units = "hPa" ;
> 
>         float   bndlay_top(bndlay) ;
>                 bndlay_top:long_name = "top of layer" ;
>                 bndlay_top:units = "hPa" ;
> 
>         :boundary-map = "bndlay_bot bndlay_top lat lon";

ive been toying with the idea of introducing a grouping syntax, like:
         :boundary-map = "(bndlay_bot bndlay_top) lat lon";
but i havent yet thought it through. 


> 
> record Attribute
> 
> The NUWG conventions suggest a record attribute for model grids.
> 
>         float u(record, z, x, y);
>                 u:record = "valtime, reftime";
> 
>         double valtime(record);
>                 valtime:long_name = "valid time of model";
>                 valtime:units = "minutes since (1993-1-1 00:00:00.0)";
> 
>         double reftime(record);
>                 reftime:long_name = "reference time of model";
>                 reftime:units = "minutes since (1993-1-1 00:00:00.0)";
> 
> Using map attributes, the multiple time components become a global mapping,
> similar to Russ' example of a dimension attribute for time:
> 
>  2.  A global "dimension attribute":
> 
>      :time = "year day_of_year second_of_day";
> 
> Following are the corresponding examples using global map attributes. The
> time mappings could be combined with lat/lon or other mappings for the other
> dimensions as needed.
> 
>         variables:
>                 float u (record, z, y, x);
>                    u:u = "model-time-map";
>                 float observed_temp (record, z, y, x);
>                    observed_temp:observed_temp
>                         "time-map model-time-map month-map";
>                 int year(record);
>                 int day_of_year(record);
>                 float second_of_day(record);
>                 char month(record,4);
> 
>         :time-map = "year day_of_year second_of_day";
>         :model-time-map = "valtime reftime";
>         :month-map = "year month";

this is a confusing example, partly because of the indirection
but once i parse it, i guess its straightforward:
(i'll eliminate the x,y,z dimensions):
we have two variables u(record) and observer_temp(record).
 u has coordinate system model-time-map, and observed_temp
has coordinate systems model-time-map, time-map, and month-map.

it would be surprising (though certainly possible) that in a real file
u would not also have the other two time coords.

> 
> Grid levels
> 
> Here is an example based on the NUWG conventions for alternate grid level
> coordinates, p or vpt.
> 
>         float u(record, z, x, y);
>                 u:z = "vpt, p";
> 
> Using the global map attributes:
> 
>         float u(record, z, x, y);
>                 u:u = "pres-grid-map vpt-grid-map";
>         float p(record, z, x, y);
>                 u:u = "vpt-grid-map";
>         float vpt(record, z, x, y);
>                 u:u = "pres-grid-map";
> 
>         :pres-grid-map = "p x y";
>         :vpt-grid-map = "vpt x y";
> 
> The default coordinate system for u would use pressure p for the height
> axis, but availability of vpt is evident.

actually, its explicit.

> 
> ----------------------------------------------------------------------------
> 
> Extensions
> 
> Set Notation
> 
> Looking to the future, the global mapping attribute could adopt some
> specialized syntax so that simple mappings could be included as a formula
> rather than a whole array of data. If the distance variable in the wiring
> example above is proportional to s, then distance-map could describe the
> mapping using set notation.
> 
>         :distance-map = "{ (s) : s*1.6 }"

this could be worth exploring. we'd need a syntax definition.
did i say we couldn't embed methods? 

> 
> Virtual Vector Variables
> 
> Since the global map attribute essentially lists multiple components of an
> n-space range, it could also be interpreted as a vector. Perhaps call it a
> virtual vector variable:
> 
>         float u_wind (time);
>         float v_wind (time);
>         float w_wind (time);
> 
>         :wind = "u_wind v_wind w_wind";         // 3-D vectors over time
> 
> The problem is how to clearly indicate wind as a virtual variable. Perhaps
> in a global vectors or variables attribute.

how about
        :vector_<name> = "list of components";
eg
        :vector_wind = "u_wind v_wind w_wind";         // 3-D vectors over time

although the question of what applications might do with tat info is unanswered.

> 
> Sub-mapping
> 
> It would be interesting to be able to specify mappings which map directly to
> the coordinates of dimensions in the file. Suppose we wanted to specify a
> subset of the ocean temperature grid in the first example. We could specify
> a coordinate system whose range maps a subset of the domain of the temp
> variable over (i,j,k). As one possibility, specify integer variables which
> map into i, j, and k, and a global mapping which uses a colon (':') to
> indicate that the coordinates map directly into the i, j, and k coordinates
> of temp. The same method could be used for specifying the path of a particle
> through the grid:
> 
>         dimensions:
>                 i = 10;         // Whole grid
>                 j = 100;
>                 k = 100;
>                 i2 = 10;        // Region of grid
>                 j2 = 20;
>                 k2 = 20;
> 
>         float temp (time, i, j, k);
>                 temp:temp = "subgrid-map particle-trace-map";
>         float depth(time, i,j,k);
>                 depth:depth = "depth-estimate particle-trace-map";
>         float lat(j, k);
>                 lat:lat = "particle-trace-map";
>         float lon(j, k);
>                 lon:lon = "particle-trace-map";
> 
>         int a (i2, j2, k2);
>         int b (i2, j2, k2);
>         int c (i2, j2, k2);
> 
>         int particle_i (time);
>         int particle_j (time);
>         int particle_k (time);
> 
>         :subgrid-map = "a:i b:j c:k";
>         :particle-trace-map = "particle_i:i particle_j:j particle_k:k";
> 
> Using a "sub-mapping" implies a different domain for the variable's mapping.
> In the case of plotting the water temperature along the particle track, the
> user asks for temp over the particle-trace-map, which an application can
> directly expand to
> 
> temp (particle_i(time), particle_j(time), particle_k(time))
> 
> The particle's locations would be
> 
>  lat (particle_j(time), particle_k(time))
>  lon (particle_j(time), particle_k(time))
>  depth (time, particle_i(time), particle_j(time), particle_k(time))
> 
> which in turn might be described by a "virtual vector":
> 
>         :particle_locn = "lat lon depth";
> 
> If the sub-grid were sampled along each dimension independent of the other
> dimensions:
> 
>         int a (i2);
>         int b (j2);
>         int c (k2);

sorry, my eyeballs glazed over....
i'll try this example again later....

> 
> Close
> 
> I left out details, like the specific syntax of the referential attribute,
> and I'm concentrating specifically on describing coordinates systems and
> mappings. Other conventions could be added later, such as units, projection
> types, labelling of geographic coordinates so that applications can
> recognize them, orientation of coordinates (e.g. vertical vs horizontal),
> and so on.
> 
> I've been working with netcdf since the beginning, especially with regards
> to visualization software (Zebra) which stores and interprets
> multi-dimensional data. Some netcdf conventions for describing these data
> and their geographic coordinates would be very helpful, so I wanted to
> contribute some ideas. If any of my reasoning is wrong, faulty, or unclear,
> please let me and/or the netcdf mailing list know. Thanks for taking time to
> check this out.
> 
> ----------------------------------------------------------------------------
> 
>                                                                 Gary Granger
>                                                                July 12, 1997

i would be interested in examples from real life that you think a convention 
should cover,
especially if not already listed in http://acd.ucar.edu/~caron/coordvar.html

Regards,

John.


  • 1997 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: