从 AWS NetCDF 文件noaa-16 存储桶的时间转换

问题描述

我从 AWS(亚马逊网络服务)上托管的 noaa-16 存储桶下载了一个数据集(“OR_GLM-L2-LCFA_G16_s20202530000000_e20202530000200_c20202530000226.nc”)。该数据集包含一个名为“flash_time_offset_of_first_event”的变量,详细说明自 2020 年 9 月 9 日以来的秒数,在 00:00:00 和 00:00:20 之间...

Screenshot of AWS NetCDF file as seen in Panoly

我正在使用以下方法读取 netCDF 文件

using NCDatasets
flash_times = []
fname1 = "OR_GLM-L2-LCFA_G16_s20202530000000_e20202530000200_c20202530000226.nc"
fpath1 = string("C:\\mydir\\",fname1)
NCDataset(fpath1) do ds
    [push!(flash_times,string(x)) for x in ds["flash_time_offset_of_first_event"][:,:]]
end

产生:

sort(flash_times)
481-element Array{Any,1}:
 "2020-09-08T23:59:42.594"
 "2020-09-08T23:59:42.672"
 "2020-09-08T23:59:42.688"
 ⋮
 "2020-09-09T00:00:07.324"
 "2020-09-09T00:00:07.366"
 "2020-09-09T00:00:07.42"

问题是时间与值图中显示的时间不匹配,如在 Panoply 中绘制的(如下所示)。在 Panoply 中,绘制的值范围从 ~-0.7s (2020-09-08T23:59:59.3) 到 ~19.4s (2020-09-09T00:00:19.4):

A plot of the flash times,as plotted by Panoply

我正在使用以下方法提取日期时间数组中最早和最晚的时间:

@info("",Earliest_time=sort(flash_times)[1],Latest_time=sort(flash_times)[end])

产生:

┌ Info: 
│   Earliest_time = "2020-09-08T23:59:42.594"
└   Latest_time = "2020-09-09T00:00:07.42"   

我的问题:我该如何正确提取这些时间,或者更正我提取的时间? NetCDF 还包含 scale_factoradd_offset 变量的信息,但到目前为止我还没有能够实现这些。我还尝试使用 NetCDF 包提取 netCDF 数据,但这会返回一个整数数组,我已尝试(未成功)使用 scale_factoradd_offset 变量进行转换。

解决方法

NCDatasets 已经自动应用了 scale_factoradd_offset 属性,但是这里还有另一个属性 _Unsigned,NCDatasets 还不知道,而其他库,如在 Panoply 中使用的和 xarray 做。我为它创建了这个问题:https://github.com/Alexander-Barth/NCDatasets.jl/issues/133

所以简而言之,数据存储为 Int16,并且在后半部分具有负值。由于这些负值应该被解释为无符号(正)值,这会影响最终出现的日期。我们现在可以自己挖掘并应用这些步骤,以从原始数据中获得正确的值:

using NCDatasets
using Downloads
using Dates
url = "http://ftp.cptec.inpe.br/goes/goes16/glm/2020/09/09/OR_GLM-L2-LCFA_G16_s20202530000000_e20202530000200_c20202530000226.nc"

path = Downloads.download(url)
ds = NCDataset(path)
var = ds["flash_time_offset_of_first_event"]
# flash_time_offset_of_first_event (481)
#   Datatype:    Int16
#   Dimensions:  number_of_flashes
#   Attributes:
#    long_name            = GLM L2+ Lightning Detection: time of occurrence of first constituent event in flash
#    standard_name        = time
#    _Unsigned            = true
#    scale_factor         = 0.0003814756
#    add_offset           = -5.0
#    units                = seconds since 2020-09-09 00:00:00.000
#    axis                 = T

# see the issue,these dates are incorrect
extrema(var)
# DateTime("2020-09-08T23:59:42.594")
# DateTime("2020-09-09T00:00:07.420")

raw = var.var[:]  # Vector{Int16}
# interpret as unsigned,and apply scale and offset
val = reinterpret(unsigned(eltype(raw)),raw) .* NCDatasets.scale_factor(var) .+ NCDatasets.add_offset(var)
# get dates by adding these as seconds to the epoch
epoch = DateTime("2020-09-09T00:00:00")
times = epoch .+ Millisecond.(round.(Int,val .* 1000))
extrema(times)  # these are as expected
# DateTime("2020-09-08T23:59:59.251")
# DateTime("2020-09-09T00:00:19.408")

当然这并不理想,用户在 NCDatasets 本身中解决这个问题会更容易。