【问题标题】:Using NCML to reduce dimensions in netCDF file使用 NCML 减少 netCDF 文件中的维度
【发布时间】:2013-09-22 07:45:39
【问题描述】:

我正在尝试使用 NCML 将 CF-1.4 文件“转换”为 CF-1.6。特别感兴趣的是如何 1) 删除维度,然后 2) 更改变量的维度。例如,下面是两个 netCDF 文件的顶部 (ncdump)。第一个是 CF-1.4,尺寸为 timezlatlon。在这个文件中,变量(例如 temp)是这四个函数的函数:temp(time,z,lat,lon)。我想通过 NCML 将其转换为 CF-1.6 文件,如第二个文件所示,其中 z/lat/lon 不再是维度,变量只是时间的函数。谢谢,

文件 1:

netcdf wqb_1.4 {
dimensions:
        time = UNLIMITED ; // (109008 currently)
        z = 1 ;
        lat = 1 ;
        lon = 1 ;
variables:
        float time(time) ;
                time:long_name = "Time" ;
                time:standard_name = "time" ;
                time:short_name = "time" ;
                time:axis = "T" ;
                time:units = "minutes since 2008-01-01 00:00:00 -10:00" ;
        float z(z) ;
                z:long_name = "depth below mean sea level" ;
                z:standard_name = "depth" ;
                z:short_name = "depth" ;
                z:axis = "z" ;
                z:units = "meters" ;
        float lat(lat) ;
                lat:long_name = "Latitude" ;
                lat:standard_name = "latitude" ;
                lat:short_name = "lat" ;
                lat:axis = "Y" ;
                lat:units = "degrees_north" ;
        float lon(lon) ;
                lon:long_name = "Longitude" ;
                lon:standard_name = "longitude" ;
                lon:short_name = "lon" ;
                lon:axis = "X" ;
                lon:units = "degrees_east" ;
        float temp(time, z, lat, lon) ;
                temp:long_name = "Temperature" ;
                temp:standard_name = "sea_water_temperature" ;
                temp:short_name = "temp" ;
                temp:units = "Celsius" ;
                temp:coordinates = "time lat lon alt" ;
                temp:valid_range = 10., 35. ;
                temp:_FillValue = -999.f ;
                temp:observation_type = "measured" ;

文件 2:

netcdf wqb_1.6 {
dimensions:
        time = UNLIMITED ; // (109008 currently)
        name_strlen = 5 ;
variables:
        char station_name(name_strlen) ;
                station_name:long_name = "wqbaw" ;
                station_name:cf_role = "timeseries_id" ;
        float time(time) ;
                time:long_name = "Time" ;
                time:standard_name = "time" ;
                time:short_name = "time" ;
                time:axis = "T" ;
                time:units = "minutes since 2008-01-01 00:00:00 -10:00" ;
        float z ;
                z:long_name = "depth below mean sea level" ;
                z:standard_name = "depth" ;
                z:short_name = "depth" ;
                z:axis = "z" ;
                z:units = "meters" ;
        float lat ;
                lat:long_name = "Latitude" ;
                lat:standard_name = "latitude" ;
                lat:short_name = "lat" ;
                lat:axis = "Y" ;
                lat:units = "degrees_north" ;
        float lon ;
                lon:long_name = "Longitude" ;
                lon:standard_name = "longitude" ;
                lon:short_name = "lon" ;
                lon:axis = "X" ;
                lon:units = "degrees_east" ;
        float temp(time) ;
                temp:long_name = "Temperature" ;
                temp:standard_name = "sea_water_temperature" ;
                temp:short_name = "temp" ;
                temp:units = "Celsius" ;
                temp:coordinates = "time lat lon alt" ;
                temp:valid_range = 10., 35. ;
                temp:_FillValue = -999.f ;
                temp:observation_type = "measured" ;

【问题讨论】:

    标签: netcdf ncml thredds


    【解决方案1】:

    更新: 下面的解决方案似乎可以工作,但它不能:从中提取数据失败,正如 John M. 发现的那样(请参阅其他答案)。我们认为我们已经找到了解决方案,但从四个维度变为一维最终会导致错误。正如 Sean A. 所指出的,您无法使用 NcML 更改变量的形状。

    原始“解决方案”(实际上不起作用):

    如果您的目标是使您的数据符合 CF-1.6,您可以将该维度设为 station,其值为 1。所以你可以这样做:

    <?xml version="1.0" encoding="UTF-8"?>
    <netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" location="/usgs/data/file1.nc">
      <remove type="dimension" name="lon"/>
      <remove type="dimension" name="lat"/>
      <remove type="dimension" name="z"/>
      <dimension name="station" length="1"/>
      <dimension name="name_strlen" length="20" />
      <variable name="lat" shape="station"/>
      <variable name="lon" shape="station"/>
      <variable name="z" shape="station"/>
      <variable name="temp" shape="time station"/>
      <variable name="site" shape="station name_strlen" type="char">
        <attribute name="standard_name" value="station_id" />
        <attribute name="cf_role" value="timeseries_id" />
        <values> my_station_001 </values>
      </variable>
      <attribute name="Conventions" value="CF-1.6" />
      <attribute name="featureType" value="timeSeries" />
    </netcdf>
    

    【讨论】:

      【解决方案2】:

      Rich 的解决方案适用于这种非常具体的情况,但原因是错误的。在 NcML 中,您可以删除维度对象,但不能重塑数据变量。对于这种特殊情况,当您尝试删除单一维度(大小为 1)时,事情似乎会解决,因为它并没有真正改变数据在磁盘上的布局方式。例如,如果您在 Rich 的回答中使用 Unidata 的 toolsUI 使用 NcML 为 temp 变量执行 ncdump,您会看到单例维度仍然存在并且没有真正被删除。我不确定这会如何影响您的文件的阅读 - 我认为这将取决于客户。但是,如果您尝试删除非单一维度,那么这将失败。

      如果你真的想正确地重塑你的数据,你将不得不重写你的 netCDF 文件。不幸的是,据我所知,没有任何“捷径”。例如,如果你在 Unidata 的 toolsUI 中使用 Rich 的 NcML 并尝试基于它写出一个新文件,你会得到一个错误,例如“ERROR: Number of range in section (1) must be = 0 for Variable z。”这是因为 netCDF 文件中仍然存在单一维度,但 NcML 文件试图将范围强制为 0。但是,如果您了解 python,那么编写一个脚本来重写您的 netCDF 文件应该非常简单。

      请注意,使用 NcML 重塑变量的能力是我们定期听到的功能请求 - 向 support-netcdf-java@unidata.ucar.edu 发送功能请求不会有什么坏处。另请注意,Unidata 是一个社区驱动的组织,Rich 是我们用户委员会的成员,该委员会将于下个月开会。我建议他在会议上也提到功能请求。

      干杯!

      肖恩

      【讨论】:

      • Rich 是正确的,这样做的目的是尝试将我们的数据提升到 CF-1.6,这样做的目的是让我们可以通过 SOS 服务我们的数据。更具体地说,我们想使用 ncSOS(基于 TDS),而这种特殊的 SOS 风格需要 CF-1.6。
      • Sean 是正确的(正如 Jim 和 John 痛苦地发现的那样)——当您尝试通过 OPeNDAP 或 SOS 从这些 NcML 修改的数据集中提取数据时,它不起作用。我们认为我们有一种巧妙的方法可以让我们将 ncSOS 与我们现有的时间序列数据一起使用,但事实证明我们没有。对不起,追逐野鹅。 :-(
      • 尝试使用 shape="lat one" 的 NCML 添加退化维度同样失败。 THREDDS 似乎提供了它,但子集请求失败并出现“范围数 ...”错误。
      【解决方案3】:

      Rich 是对的,这样做的目的是尝试将我们的数据提升到 CF-1.6,这样做的目的是为了让我们可以通过 SOS 服务我们的数据。更具体地说,我们想使用 ncSOS(建立在 TDS 之上),而这种特殊的 SOS 风格需要 CF-1.6。在这方面,通过 NCML 进行的修改似乎有效(加上一些额外的;见下文)。

      我不想修改数据集,其中一些可以追溯到几年前。肖恩关于客户端工具的观点也很重要,因为我们的许多用例都涉及需要变量具有纬度/经度维度的工具。因此,我们的解决方案是通过两个 NCML“包装器”通过 TDS 提供一个数据集,一个用于 ncSOS,另一个用于通过 OPeNDAP 访问的需要纬度/经度的特定客户端。

      除了上面 Rich 的建议,为了在 ncSOS 中工作,我们必须:

      1. 添加 CF-1.6 '坐标' 属性(“time lat lon z”)
      2. 添加全局属性“featureType = timeSeries”
      3. 添加 station_name 变量
      4. 从点到站更改数据类型

      这里给出结果:

          <attribute name="featureType" value="timeSeries" />
          <remove type="dimension" name="lon"/>
          <remove type="dimension" name="lat"/>
          <remove type="dimension" name="z"/>
          <dimension name="name_strlen" length="4"/>
          <variable name="lat" shape=""/>
          <variable name="lon" shape=""/>
          <variable name="z" shape=""/>
          <variable name="station_name" shape="name_strlen" type="char">
            <attribute name="long_name" value="NS01" />
            <attribute name="cf_role" value="timeseries_id" />
            <values>NS01</values>
          </variable>
          <variable name="temp" shape="time">
            <attribute name="coordinates" value="time lat lon z" />
          </variable>
      

      【讨论】:

        【解决方案4】:

        为了跟进 Jim 的上述帖子,虽然 Rich 的 NcML 解决方案最初似乎有效,但通过 OPeNDAP 或 ncSOS 获取数据的尝试没有成功,这证实了 Sean 的上述怀疑。

        目录成功显示,OPeNDAP 表单显示 CF-1.6 的新尺寸和重新调整的变量。此外,ncSOS GetCapabilities 文档也成功显示。

        但是,尝试使用 OPeNDAP 表单下载一些数据时会出现问题。我无法在 OPeNDAP 表单上获得变量的子集。例如:

        http://oos.soest.hawaii.edu/thredds-test/dodsC/hioos/nss/ns01/ns01_2012_02_23.nc.html

        如果我尝试使用此 URL 获取第一个临时值:

        http://oos.soest.hawaii.edu/thredds-test/dodsC/hioos/nss/ns01/ns01_2012_02_23.nc.ascii?temp[0:1:0]

        它给了我这个错误:

        Error {
            code = 500;
            message = "NcSDArray InvalidRangeException=Number of ranges in section (1) must be = 4";
        };
        

        唯一成功的是获取所有值:

        http://oos.soest.hawaii.edu/thredds-test/dodsC/hioos/nss/ns01/ns01_2012_02_23.nc.ascii?temp[0:1:359]

        此外,尝试通过 ncSOS GetObservation 获取数据也会失败。尝试了以下 URL:

        http://oos.soest.hawaii.edu/thredds-test/sos/hioos/nss/ns01agg.ncml?service=SOS&version=1.0.0&request=GetObservation&responseFormat=text%2Fxml%3Bsubtype%3D%22om%2F1.0.0%22&offering=NS01&observedProperty=temp&procedure=urn:ioos:station:org.pacioos:NS01

        这会导致 threddsServlet.log 中出现以下错误消息:

        2013-10-02T09:03:44.844 -1000 [1288472818][    2602] INFO  - threddsServlet - Remote host: 128.171.151.240 - Request: "GET /thredds-test/sos/hioos/nss/ns01agg.ncml?service=SOS&version=1.0.0&request=GetObs
        ervation&responseFormat=text%2Fxml%3Bsubtype%3D%22om%2F1.0.0%22&offering=NS01&observedProperty=temp&procedure=urn:ioos:station:org.pacioos:NS01 HTTP/1.1"
        2013-10-02T09:03:44.845 -1000 [1288472819][    2602] INFO  - com.asascience.ncsos.controller.SosController - Handling SOS metadata request.
        2013-10-02T09:03:45.614 -1000 [1288473588][    2602] ERROR - ucar.nc2.Structure - Structure.IteratorRank1.readNext()
        ucar.ma2.InvalidRangeException: Number of ranges in section (1) must be = 4
            at ucar.ma2.Section.fill(Section.java:144)
            at ucar.nc2.Variable.read(Variable.java:673)
            at ucar.nc2.Variable.read(Variable.java:647)
            at ucar.nc2.ncml.AggregationOuterDimension$DatasetOuterDimension.read(AggregationOuterDimension.java:774)
            at ucar.nc2.ncml.AggregationOuterDimension.reallyRead(AggregationOuterDimension.java:293)
            at ucar.nc2.dataset.VariableDS._read(VariableDS.java:533)
            at ucar.nc2.Variable.read(Variable.java:673)
            at ucar.nc2.dataset.VariableDS.reallyRead(VariableDS.java:553)
            at ucar.nc2.dataset.VariableDS._read(VariableDS.java:533)
            at ucar.nc2.Variable.read(Variable.java:673)
            at ucar.nc2.Variable.read(Variable.java:647)
            at ucar.nc2.dataset.StructurePseudoDS.reallyRead(StructurePseudoDS.java:193)
            at ucar.nc2.Variable._read(Variable.java:861)
            at ucar.nc2.Variable.read(Variable.java:673)
            at ucar.nc2.Variable.read(Variable.java:619)
            at ucar.nc2.Structure.readStructure(Structure.java:378)
            at ucar.nc2.Structure$IteratorRank1.readNext(Structure.java:464)
            at ucar.nc2.Structure$IteratorRank1.next(Structure.java:447)
            at ucar.nc2.ft.point.PointIteratorFromStructureData.nextStructureData(PointIteratorFromStructureData.java:103)
            at ucar.nc2.ft.point.PointIteratorFromStructureData.hasNext(PointIteratorFromStructureData.java:68)
            at ucar.nc2.ft.point.PointCollectionImpl.calcBounds(PointCollectionImpl.java:128)
            at com.asascience.ncsos.util.DatasetHandlerAdapter.calcBounds(DatasetHandlerAdapter.java:122)
            at com.asascience.ncsos.cdmclasses.TimeSeries.setData(TimeSeries.java:243)
            at com.asascience.ncsos.getobs.SOSGetObservationRequestHandler.setCDMDatasetForStations(SOSGetObservationRequestHandler.java:193)
            at com.asascience.ncsos.getobs.SOSGetObservationRequestHandler.<init>(SOSGetObservationRequestHandler.java:138)
            at com.asascience.ncsos.service.SOSParser.enhanceGETRequest(SOSParser.java:197)
            at com.asascience.ncsos.controller.SosController.handleSOSRequest(SosController.java:80)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
            at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
            at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
            at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
            at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
            at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
            at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
            at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at thredds.servlet.filter.RequestPathFilter.doFilter(RequestPathFilter.java:102)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at thredds.server.RequestBracketingLogMessageFilter.doFilter(RequestBracketingLogMessageFilter.java:48)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
            at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
            at java.lang.Thread.run(Unknown Source)
        2013-10-02T09:03:45.616 -1000 [1288473590][    2602] ERROR - com.asascience.ncsos.util.DatasetHandlerAdapter - Could not calculate the bounds of the PointFeatureCollection NS01
        Structure.Iterator.readNext()
        2013-10-02T09:03:45.616 -1000 [1288473590][    2602] ERROR - com.asascience.ncsos.cdmclasses.baseCDMClass - TimeSeries - setData; exception:
        java.lang.NullPointerException
        2013-10-02T09:03:45.616 -1000 [1288473590][    2602] ERROR - com.asascience.ncsos.service.SOSParser - java.lang.NullPointerException
        2013-10-02T09:03:45.617 -1000 [1288473591][    2602] ERROR - com.asascience.ncsos.controller.SosController -
        2013-10-02T09:03:45.817 -1000 [1288473791][    2602] INFO  - threddsServlet - Request Completed - 200 - -1 - 973:1
        

        【讨论】:

        • 只是为了确认这个问题与我非常相关。我们面临着类似的情况。 +1 对 Sean A. 的建议,将其作为 TDS 的功能请求提出。
        • 尝试使用 shape="lat one" 的 NCML 添加退化维度同样失败。 THREDDS 似乎提供了它,但子集请求失败并出现“范围数 ...”错误。
        【解决方案5】:

        NcML 现在(从 4.4 版开始)有一个删除长度为 1 的维度的操作,例如:

        <variable name="temp">
          <logicalReduce dimNames="lat lon" />
        </variable>
        

        http://www.unidata.ucar.edu/software/thredds/current/netcdf-java/ncml/AnnotatedSchema4.html#logicalReduce

        【讨论】:

          猜你喜欢
          • 2013-02-20
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          • 2013-12-11
          • 2014-07-20
          • 2015-02-05
          • 1970-01-01
          • 2017-11-17
          相关资源
          最近更新 更多