NetCDF 파일과 OPeNDAP 데이터 가져오기
여러 가지 방법으로 netCDF 파일에서 데이터를 읽을 수 있습니다. 프로그래밍 방식으로 MATLAB®의 하이 레벨 netCDF 함수 또는 netCDF 라이브러리 네임스페이스의 로우 레벨 함수를 사용할 수 있습니다. 대화형 방식으로는 데이터 가져오기 라이브 편집기 작업을 사용하거나 (MATLAB Online™에서) 가져오기 툴 앱을 사용할 수 있습니다.
MATLAB NetCDF 지원 기능
NetCDF(Network Common Data Form)는 배열 지향적인 과학 데이터를 생성, 액세스 및 공유하도록 지원하는 소프트웨어 라이브러리 및 시스템 독립적인 데이터 형식의 집합입니다. NetCDF는 용이한 데이터의 공유를 위해 표준화된 데이터 저장 방식을 요하는 여러 공학 및 과학 분야에서 사용됩니다.
MATLAB 하이 레벨 함수는 NetCDF 파일이나 OPeNDAP NetCDF 데이터 소스에서 데이터를 가져오는 과정을 단순화합니다. MATLAB 로우 레벨 함수를 사용하면 NetCDF C 라이브러리의 루틴에 액세스하여 가져오기 프로세스를 더 세부적으로 제어할 수 있습니다. 로우 레벨 함수를 효과적으로 사용하려면 NetCDF C 인터페이스를 잘 알고 있어야 합니다. NetCDF 문서는 Unidata 웹사이트에서 참조할 수 있습니다.
참고
별도의 호환되지 않는 형식을 가지고 있는 CDF(Common Data Format) 파일 가져오기에 대한 정보는 Import CDF Files Using Low-Level Functions 항목을 참조하십시오.
OPeNDAP 서버에 연결할 때 보안 관련 고려 사항
신뢰할 수 있는 OPeNDAP 서버에만 연결할 것을 강력히 권장합니다. R2020b 이상 버전에서 MATLAB NetCDF 인터페이스는 서버 인증서 및 호스트 이름 유효성 검사를 수행하여 기본적으로 신뢰할 수 있는 데이터 액세스 프로토콜(DAP) 끝점에만 연결합니다. 이전에는 OPeNDAP 서버에 액세스할 때 서버 인증서 및 호스트 이름 유효성 검사가 모두 기본적으로 비활성화되어 있었습니다.
서버 인증서 및 호스트 이름 유효성 검사를 비활성화하려면 현재 디렉터리의 .dodsrc
파일에 다음 라인을 추가하십시오.
[mylocaltestserver.lab] HTTP.SSL.VALIDATE=0
이렇게 하면 MATLAB NetCDF 인터페이스가 서버 인증서나 호스트 이름에 대한 유효성 검사를 수행하지 않고 URI mylocaltestserver.lab
에 지정된 이름이 있는 OPeNDAP 서버에 연결합니다. 이러한 변경 내용은 향후 MATLAB 세션에서도 유지됩니다.
하이 레벨 함수를 사용하여 NetCDF 파일에서 읽어오기
이 예제에서는 하이 레벨 함수를 사용하여 NetCDF 파일 내용을 표시하고 읽어오는 방법을 보여줍니다.
샘플 NetCDF 파일 example.nc
의 내용을 표시합니다.
ncdisp('example.nc')
Source: \\matlabroot\toolbox\matlab\demos\example.nc Format: netcdf4 Global Attributes: creation_date = '29-Mar-2010' Dimensions: x = 50 y = 50 z = 5 Variables: avagadros_number Size: 1x1 Dimensions: Datatype: double Attributes: description = 'this variable has no dimensions' temperature Size: 50x1 Dimensions: x Datatype: int16 Attributes: scale_factor = 1.8 add_offset = 32 units = 'degrees_fahrenheit' peaks Size: 50x50 Dimensions: x,y Datatype: int16 Attributes: description = 'z = peaks(50);' Groups: /grid1/ Attributes: description = 'This is a group attribute.' Dimensions: x = 360 y = 180 time = 0 (UNLIMITED) Variables: temp Size: [] Dimensions: x,y,time Datatype: int16 /grid2/ Attributes: description = 'This is another group attribute.' Dimensions: x = 360 y = 180 time = 0 (UNLIMITED) Variables: temp Size: [] Dimensions: x,y,time Datatype: int16
ncdisp
는 파일의 모든 그룹과 차원, 변수 정의를 표시합니다. 무제한 차원은 레이블 UNLIMITED
로 식별됩니다.
peaks
변수에서 데이터를 읽어옵니다.
peaksData = ncread('example.nc','peaks');
peaksData
출력값에 대한 정보를 표시합니다.
whos peaksData
Name Size Bytes Class Attributes peaksData 50x50 5000 int16
변수와 연관된 description
특성(Attribute)을 읽어옵니다.
peaksDesc = ncreadatt('example.nc','peaks','description')
peaksDesc = z = peaks(50);
변수 데이터의 3차원 곡면 플롯을 만듭니다. description
특성의 값을 Figure의 제목으로 사용합니다.
surf(double(peaksData)) title(peaksDesc);
/grid1/
그룹과 연관된 description
특성을 읽어옵니다. 그룹 이름을 ncreadatt
함수에 대한 두 번째 입력값으로 지정합니다.
g = ncreadatt('example.nc','/grid1/','description')
g = This is a group attribute.
전역 특성 creation_date
를 읽어옵니다. 전역 특성에서 ncreadatt
에 대한 두 번째 입력 인수를 '/'
로 지정합니다.
creation_date = ncreadatt('example.nc','/','creation_date')
creation_date = 29-Mar-2010
NetCDF 파일에서 무제한 차원 모두 찾기
이 예제에서는 하이 레벨 함수를 사용하여 NetCDF 파일에서 그룹의 무제한 차원을 모두 찾는 방법을 보여줍니다.
ncinfo
함수를 사용하여 샘플 파일 example.nc
의 /grid2/
그룹에 대한 정보를 가져옵니다.
ginfo = ncinfo('example.nc','/grid2/')
ginfo = Filename: '\\matlabroot\toolbox\matlab\demos\example.nc' Name: 'grid2' Dimensions: [1x3 struct] Variables: [1x1 struct] Attributes: [1x1 struct] Groups: [] Format: 'netcdf4'
ncinfo
는 그룹에 대한 정보가 포함된 구조체형 배열을 반환합니다.
이 그룹의 무제한 차원을 나타내는 부울 값으로 구성된 벡터를 가져옵니다.
unlimDims = [ginfo.Dimensions.Unlimited]
unlimDims = 0 0 1
unlimDims
벡터를 사용하여 무제한 차원을 표시합니다.
disp(ginfo.Dimensions(unlimDims))
Name: 'time' Length: 0 Unlimited: 1
로우 레벨 함수를 사용하여 NetCDF 파일에서 읽어오기
이 예제에서는 netcdf
네임스페이스의 MATLAB 로우 레벨 함수를 사용하여 netCDF 파일의 차원, 변수, 특성(attribute)에 대한 정보를 가져오는 방법을 보여줍니다. 이러한 함수를 효과적으로 사용하려면 netCDF C 인터페이스를 잘 알고 있어야 합니다.
NetCDF 파일 열기
netcdf.open
함수를 사용하여 읽기 전용 액세스로 샘플 netCDF 파일 example.nc
를 엽니다.
ncid = netcdf.open("example.nc","NC_NOWRITE");
netcdf.open
은 파일 ID를 반환합니다.
NetCDF 파일에 대한 정보 가져오기
netcdf.inq
함수를 사용하여 파일의 내용에 대한 정보를 가져옵니다. 이 함수는 netCDF 라이브러리 C API의 nc_inq
함수에 대응합니다.
[ndims,nvars,natts,unlimdimID] = netcdf.inq(ncid)
ndims = 3
nvars = 3
natts = 1
unlimdimID = -1
netcdf.inq
는 파일의 차원, 변수, 전역 특성 개수를 반환하고 파일의 무제한 차원 ID를 반환합니다. 무제한 차원은 확장될 수 있습니다.
netcdf.inqAttName
함수를 사용하여 파일의 전역 특성 이름을 가져옵니다. 이 함수는 netCDF 라이브러리 C API의 nc_inq_attname
함수에 대응합니다. 특성 이름을 가져오려면 해당 특성과 연관된 변수 ID와 특성 번호를 지정해야 합니다. 특정 변수와 연관되지 않은 전역 특성에 액세스하려면 상수 "NC_GLOBAL"
을 변수 ID로 사용하십시오.
global_att_name = netcdf.inqAttName(ncid,... netcdf.getConstant("NC_GLOBAL"),0)
global_att_name = 'creation_date'
netcdf.inqAtt
함수를 사용하여 특성의 데이터형과 길이에 대한 정보를 가져옵니다. 이 함수는 netCDF 라이브러리 C API의 nc_inq_att
함수에 대응합니다. 다시 netcdf.getConstant("NC_GLOBAL")
을 사용하여 변수 ID를 지정합니다.
[xtype,attlen] = netcdf.inqAtt(ncid,... netcdf.getConstant("NC_GLOBAL"),global_att_name)
xtype = 2
attlen = 11
netcdf.getAtt
함수를 사용하여 특성 값을 가져옵니다.
global_att_value = netcdf.getAtt(ncid,... netcdf.getConstant("NC_GLOBAL"),global_att_name)
global_att_value = '29-Mar-2010'
netcdf.inqDim
함수를 사용하여 파일의 첫 번째 차원에 대한 정보를 가져옵니다. 이 함수는 netCDF 라이브러리 C API의 nc_inq_dim
함수에 대응합니다. netcdf.inqDim
에 대한 두 번째 입력값은 차원을 식별하는 차원 ID로, 0부터 시작하는 인덱스입니다. 첫 번째 차원의 인덱스 값은 0
입니다.
[dimname,dimlen] = netcdf.inqDim(ncid,0)
dimname = 'x'
dimlen = 50
netcdf.inqDim
은 차원의 이름과 길이를 반환합니다.
netcdf.inqVar
함수를 사용하여 파일의 첫 번째 변수에 대한 정보를 가져옵니다. 이 함수는 netCDF 라이브러리 C API의 nc_inq_var
함수에 대응합니다. netcdf.inqVar
에 대한 두 번째 입력값은 변수를 식별하는 변수 ID로, 0부터 시작하는 인덱스입니다. 첫 번째 변수의 인덱스 값은 0
입니다.
[varname,vartype,dimids,natts] = netcdf.inqVar(ncid,0)
varname = 'avagadros_number'
vartype = 6
dimids = []
natts = 1
netcdf.inqVar
은 변수와 연관된 특성의 이름, 데이터형, 차원 ID 및 개수를 반환합니다. vartype
에서 반환되는 데이터형 정보는 NC_INT
, NC_BYTE
같은 netCDF 데이터형 상수의 숫자형 값입니다. 이러한 상수에 대한 정보는 netCDF 문서를 참조하십시오.
NetCDF 파일에서 데이터 읽어오기
netcdf.getVar
함수를 사용하여 예제 파일에서 변수 avagadros_number
와 연관된 데이터를 읽어옵니다. netcdf.getVar
에 대한 두 번째 입력값은 변수를 식별하는 변수 ID로, 0부터 시작하는 인덱스입니다. avagadros_number
변수의 인덱스 값은 0
입니다.
A_number = netcdf.getVar(ncid,0)
A_number = 6.0221e+23
A_number
의 데이터형을 확인합니다.
whos A_number
Name Size Bytes Class Attributes A_number 1x1 8 double
netcdf
네임스페이스의 함수는 해당 NetCDF 데이터형에 가장 잘 맞는 MATLAB 클래스를 자동으로 선택하지만, netcdf.getVar
에 대한 선택적 인수를 사용하여 반환 데이터의 클래스를 지정할 수도 있습니다.
avagadros_number
와 연관된 데이터를 읽어온 후 해당 데이터를 single
형 클래스로 반환합니다.
A_number = netcdf.getVar(ncid,0,"single")
A_number = single
6.0221e+23
whos A_number
Name Size Bytes Class Attributes A_number 1x1 4 single
NetCDF 파일 닫기
netCDF 파일 example.nc
를 닫습니다.
netcdf.close(ncid)
대화형 방식으로 NetCDF 파일에서 데이터 읽어오기
이 예제에서는 데이터 가져오기 작업을 사용하여 netCDF 파일의 구조를 탐색하고 파일에서 데이터를 가져온 후 데이터를 분석하고 시각화하는 방법을 보여줍니다.
데이터셋 다운로드하기
미국 NOAA PSL(National Oceanic and Atmospheric Administration Physical Sciences Laboratory)은 NSIDC(National Snow and Ice Data Center)가 수집한 보간된 북반구 적설량 데이터의 데이터셋을 호스팅합니다. 이 데이터셋을 현재 폴더에 다운로드합니다.
filename = "snowcover.mon.mean.nc"; url = "https://downloads.psl.noaa.gov/Datasets/snowcover/snowcover.mon.mean.nc"; fullLocalPath = websave(filename,url);
데이터 탐색 및 가져오기
라이브 편집기 탭에서 작업 > 데이터 가져오기를 선택하여 라이브 편집기에서 데이터 가져오기 작업을 엽니다. netCDF 데이터셋의 파일 이름인 snowcover.mon.mean.nc
를 파일 필드에 입력합니다. 이 작업을 사용하여 변수와 그 특성을 포함해 데이터의 구조를 탐색할 수 있습니다.
전역 특성을 통해 참조를 비롯하여 파일에 포함된 데이터의 일반적인 의미를 파악할 수 있습니다.
데이터셋에는 두 개의 공간 차원(
lat
및lon
)과 한 개의 시간 차원(time
), 즉 3개의 차원이 포함되어 있습니다.lat
변수는 크기가 90이고 값이'degrees_north'
인units
라는 특성을 갖습니다. 이 변수는 측정된 점의 위도를 나타내며, 위도는 적도로부터 북쪽 방향으로 도 단위로 측정됩니다.lon
변수는 크기가 360이고 값이'degrees_east'
인units
라는 특성을 갖습니다. 이 변수는 측정된 점의 경도를 나타내며, 경도는 본초자오선으로부터 동쪽 방향으로 도 단위로 측정됩니다.time
변수는 크기가 297이고 차원은 무제한이며 값이'hours since 1800-01-01 00:00:0.0'
인units
라는 특성을 갖습니다. 이 변수는 측정된 시간을 나타냅니다.snowcover
변수는 크기가 360×90×297이고 세 번째 차원은 무제한이며 값이'%'
인units
라는 특성과 값이'Monthly Means Snowcover Extent'
인long_name
이라는 특성을 갖습니다.snowcover
변수는lat
,lon
,time
변수를 통합합니다. 이는 북반구의 특정 점에 대한 특정 달의 월 평균 적설량을 나타내며, 눈으로 덮인 지면의 비율로 측정됩니다.
lat
, lon
, time
, snowcover
변수에서 데이터를 선택하고 가져옵니다.
이 작업이 생성하는 코드를 확인하려면 작업 파라미터 영역 맨 아래에 있는 코드 표시를 클릭하여 작업 표시 영역을 확장합니다.
% Create a structure to store imported netCDF data snowcover_mon_mean = struct(); filename = "snowcover.mon.mean.nc"; snowcover_mon_mean.Variables(1).Name = "lat"; snowcover_mon_mean.Variables(2).Name = "lon"; snowcover_mon_mean.Variables(3).Name = "time"; snowcover_mon_mean.Variables(4).Name = "snowcover"; snowcover_mon_mean.Variables(1).Value = ncread(filename, "/lat"); snowcover_mon_mean.Variables(2).Value = ncread(filename, "/lon"); snowcover_mon_mean.Variables(3).Value = ncread(filename, "/time"); snowcover_mon_mean.Variables(4).Value = ncread(filename, "/snowcover"); clear filename
데이터를 구성하고 준비하기
데이터셋의 변수 각각에 대해 지역 변수를 만듭니다.
lats = snowcover_mon_mean.Variables(1).Value; lons = snowcover_mon_mean.Variables(2).Value; times = snowcover_mon_mean.Variables(3).Value; snows = snowcover_mon_mean.Variables(4).Value;
데이터를 플로팅할 때 lats
와 lons
가 적절하게 표시되도록 준비합니다. 각 축에 10개의 레이블을 표시하는 표시 스케일을 선택합니다.
numLabels = 10; latDisps = strings(length(lats),1); latsLabelInterval = length(lats)/numLabels; latLabelInds = latsLabelInterval:latsLabelInterval:length(lats); latDisps(latLabelInds) = lats(latLabelInds); lonDisps = strings(length(lons),1); lonsLabelInterval = length(lons)/numLabels; lonLabelInds = lonsLabelInterval:lonsLabelInterval:length(lons); lonDisps(lonLabelInds) = lons(lonLabelInds);
time
변수의 units
특성은 time
이 1800년 초부터 시간 단위로 측정되었다는 것을 나타냅니다. 또한 snowcover
변수의 long_name
특성은 값이 월 평균이라는 것을 나타냅니다. 이 정보를 사용하여 times
벡터를 대응하는 datetime
값으로 변환하고, 월과 연도는 포함하지만 일은 표시하지 않도록 times
의 표시 형식을 설정합니다.
sampTimes = datetime("1800-01-01 00:00:00") + hours(times); sampTimes.Format = "MMM-yyyy"; sampTimeDisps = string(sampTimes);
snows
의 첫 번째 차원은 위도를 나타내고 두 번째 차원은 경도를 나타냅니다. 이 데이터의 히트맵을 만들려면 첫 번째 차원은 열(경도), 두 번째 차원은 행(위도)에 대응되어야 합니다. snows
의 이 두 차원을 치환합니다.
snows = permute(snows,[2 1 3]);
데이터 플로팅하기
데이터의 첫 달에 대한 히트맵을 만듭니다.
h = heatmap(lons,lats,snows(:,:,1)); h.XLabel = "Longitude (°E)"; h.YLabel = "Latitude (°N)"; h.XDisplayLabels = lonDisps; h.YDisplayLabels = latDisps; h.Colormap = winter; h.GridVisible = "off";
사용 가능한 모든 시간에 대한 데이터를 루프로 순환하여 히트맵을 애니메이션합니다.
for i = 1:numel(sampTimeDisps) h.ColorData = snows(:,:,i); h.Title = "Percent Snow Cover vs. Location (" + sampTimeDisps(i) + ")"; pause(0.1) end
적설량이 가장 많은 시간 찾기
총 적설량을 시간의 함수로 계산하고 플로팅합니다.
cumSnowsbyTime = squeeze(sum(snows,[1 2])) / (length(lats)*length(lons)); plot(sampTimes,cumSnowsbyTime) xlabel("Date") ylabel("Total Snow Cover (%)") title("Total Snow Cover vs. Date")
적설량이 가장 많은 시간을 찾아 플로팅합니다.
[maxSnowsbyTime,maxSnowsbyTimeInd] = max(cumSnowsbyTime); h = heatmap(lons,lats,snows(:,:,maxSnowsbyTimeInd)); h.XLabel = "Longitude (°E)"; h.YLabel = "Latitude (°N)"; h.Title = "Percent Snow Cover vs. Location (" + sampTimeDisps(maxSnowsbyTimeInd) + ")"; h.XDisplayLabels = lonDisps; h.YDisplayLabels = latDisps; h.Colormap = winter; h.GridVisible = "off";
적설량이 가장 많았던 달은 1978년 2월입니다.
적설량이 가장 많은 위치 찾기
평균 적설량을 위치의 함수로 계산하고 플로팅합니다.
cumSnowsbyLoc = sum(snows,3) / length(times); h = heatmap(lons,lats,cumSnowsbyLoc); h.XLabel = "Longitude (°E)"; h.YLabel = "Latitude (°N)"; h.Title = "Average Percent Snow Cover vs. Location"; h.XDisplayLabels = lonDisps; h.YDisplayLabels = latDisps; h.Colormap = winter; h.GridVisible = "off";
적설량이 가장 많은 위치를 찾아 플로팅합니다.
maxSnowsbyLocVal = max(cumSnowsbyLoc,[],"all"); maxSnowsbyLoc = maxSnowsbyLocVal*(cumSnowsbyLoc == maxSnowsbyLocVal); h = heatmap(lons,lats,maxSnowsbyLoc); h.XLabel = "Longitude (°E)"; h.YLabel = "Latitude (°N)"; h.Title = "Locations of Maximum Snow Cover"; h.XDisplayLabels = lonDisps; h.YDisplayLabels = latDisps; h.Colormap = winter; h.GridVisible = "off";
적설량이 가장 많은 위치에는 그린란드 대부분의 지역, 그리고 스발바르 제도와 프란츠 요제프 제도의 일부가 포함됩니다.
출처
미국 콜로라도주 볼더에 있는 NOAA PSL이 해당 웹사이트(https://psl.noaa.gov
)를 통해 제공한 NH Ease-Grid Snow Cover 데이터.