탐색 건너뛰기

NASADEM

SatelliteImagery EarthObservation AIforEarth NASA

NASADEM 프로그램의 전 세계 지형 정보입니다.

NASADEM은 SRTM(Shuttle Radar Topography Mission)을 통해 캡처된 데이터에서 주로 파생된 전 세계 지형 데이터를 1각초(~30m) 수평 해상도로 제공합니다.

스토리지 리소스

데이터는 미국 동부 데이터 센터에 있는 다음 Blob 컨테이너의 Blob에 저장됩니다.

https://nasadem.blob.core.windows.net/nasadem-nc

해당 컨테이너 내에서 데이터는 다음에 따라 정리됩니다.

v001/NASADEM_NC_[lat_tile][lon_tile].[extension]

lat_tile은 각 타일로 나타낸 위도에서 파생된 문자(‘n’ 또는 ‘s’)+2자리 위도 값입니다. 지정된 위도의 위도 코드를 찾으려면 floor() 연산을 수행한 후 절대값을 취해 양수 위도(0 포함)의 경우 접두사 ‘n’을 붙이고 음수 위도의 경우 ‘s’를 붙인 다음, 2자리까지 0을 채웁니다. 예를 들어 위도 35.3606은 ‘n35’가 됩니다.

long_tile은 각 타일로 나타낸 경도에서 파생된 문자(‘e’ 또는 ‘w’)+3자리 경도 값입니다. 지정된 경도의 경도 코드를 찾으려면 floor() 연산을 수행한 후 절대값을 취해 양수 경도(0 포함)의 경우 접두사 ‘e’를 붙이고 음수 경도의 경우 ‘w’를 붙인 다음, 3자리까지 0을 채웁니다. 예를 들어 경도 138.72는 ‘e138’이 됩니다.

각 타일의 경우 다음과 같은 3개 확장명이 포함된 파일 이름이 제공됩니다.

  • 1.jpg(미리 보기 이미지)
  • nc(데이터 자체)
  • nc.xml(타일 생성 메타데이터)

이미지는 NetCDF 형식으로 저장됩니다.

NASADEM 데이터에 액세스하고 NASADEM 데이터를 그리는 전체 Python 예제는 “데이터 액세스” 아래에서 제공되는 Notebook에서 사용할 수 있습니다.

또한 Blob 컨테이너를 드라이브로 탑재할 수 있게 해주는 BlobFuse 등을 통해 NASADEM 데이터에 액세스할 수 있는 읽기 전용 SAS(공유 액세스 서명) 토큰을 제공합니다.

st=2020-03-16T17%3A16%3A02Z&se=2034-03-17T17%3A16%3A00Z&sp=rl&sv=2018-03-28&sr=c&sig=opfihPRJOhedqmupra5pf7esHL52nxrxlgJd3UPwRmY%3D

Linux용 탑재 지침은 여기에 있습니다.

대규모 처리는 이미지가 저장된 미국 동부 Azure 데이터 센터에서 최상으로 수행됩니다. 환경 과학 응용 분야에 NASADEM 데이터를 사용 중인 경우 컴퓨팅 요구 사항을 지원하려면 지구 환경 AI(AI for Earth) 보조금 신청을 고려해 보세요.

색인

전체 파일 목록은 여기에서 제공됩니다.

라이선스 및 귀속 정보

NASADEM 데이터는 로열티 또는 기타 제한 없이 상업용이든 또는 기타 어떤 목적이든 관계없이 제한 없이 사용할 수 있습니다. 정확한 데이터, 이미지 또는 기타 파생된 제품을 재판매하는 경우에도 특별한 권한이나 보상이 필요하지 않습니다.

가능한 경우 이 데이터를 사용할 때는 제공자를 밝히는 “Courtesy NASA/JPL-Caltech” 문구를 추가해 주세요.

멋진 사진


후지산 지역의 지형입니다.

연락처

이 데이터 세트에 대한 질문이 있는 경우 aiforearthdatasets@microsoft.com으로 문의하세요.

고지 사항

Microsoft는 Azure Open Datasets를 “있는 그대로” 제공합니다. Microsoft는 귀하의 데이터 세트 사용과 관련하여 어떠한 명시적이거나 묵시적인 보증, 보장 또는 조건을 제공하지 않습니다. 귀하가 거주하는 지역의 법규가 허용하는 범위 내에서 Microsoft는 귀하의 데이터 세트 사용으로 인해 발생하는 일체의 직접적, 결과적, 특별, 간접적, 부수적 또는 징벌적 손해 또는 손실을 비롯한 모든 손해 또는 손실에 대한 모든 책임을 부인합니다.

이 데이터 세트는 Microsoft가 원본 데이터를 받은 원래 사용 약관에 따라 제공됩니다. 데이터 세트에는 Microsoft가 제공한 데이터가 포함될 수 있습니다.

Access

Available inWhen to use
Azure Notebooks

Quickly explore the dataset with Jupyter notebooks hosted on Azure or your local machine.

Select your preferred service:

Azure Notebooks

Azure Notebooks

Package: Language: Python

Demo notebook for accessing NASADEM data on Azure

This notebook provides an example of accessing NASADEM data from blob storage on Azure, including (1) finding the NASADEM tile corresponding to a lat/lon coordinate, (2) retrieving that tile from blob storage, (3) opening the downloaded file using the NetCDF4 library, and (4) rendering the tile in a couple different ways.

NASADEM data are stored in the East US data center, so this notebook will run most efficiently on Azure compute located in East US. We recommend that substantial computation depending on NASADEM data also be situated in East US. If you are using NASADEM data for environmental science applications, consider applying for an AI for Earth grant to support your compute requirements.

Imports and environment

In [26]:
# Mostly-standard imports
import os
import tempfile
import numpy as np
import shutil
import urllib
import math
import matplotlib.pyplot as plt

from mpl_toolkits.basemap import Basemap

# Less-common-but-still-pip-installable imports
from netCDF4 import Dataset

# pip install progressbar2, not progressbar
import progressbar

# Storage locations are documented at http://aka.ms/ai4edata-nasadem
nasadem_account_name = 'nasadem'
nasadem_container_name = 'nasadem-nc'
nasadem_account_url = 'https://' + nasadem_account_name + '.blob.core.windows.net'
nasadem_blob_root = nasadem_account_url + '/' + nasadem_container_name + '/v001/'

# A full list of files is available at:
#
# https://nasadem.blob.core.windows.net/nasadem-nc/v001/index/file_list.txt
nasadem_file_index_url = nasadem_blob_root + 'index/nasadem_file_list.txt'

nasadem_content_extension = '.nc'
nasadem_file_prefix = 'NASADEM_NC_'

# This will contain just the .nc files
nasadem_file_list = None
                                   
temp_dir = os.path.join(tempfile.gettempdir(),'nasadem')
os.makedirs(temp_dir,exist_ok=True)

%matplotlib inline

Functions

In [27]:
class DownloadProgressBar():
    """
    https://stackoverflow.com/questions/37748105/how-to-use-progressbar-module-with-urlretrieve
    """
    
    def __init__(self):
        self.pbar = None

    def __call__(self, block_num, block_size, total_size):
        if not self.pbar:
            self.pbar = progressbar.ProgressBar(max_value=total_size)
            self.pbar.start()
            
        downloaded = block_num * block_size
        if downloaded < total_size:
            self.pbar.update(downloaded)
        else:
            self.pbar.finish()
            

def download_url(url, destination_filename=None, progress_updater=None, force_download=False):
    """
    Download a URL to a temporary file
    """
    
    # This is not intended to guarantee uniqueness, we just know it happens to guarantee
    # uniqueness for this application.
    if destination_filename is None:
        url_as_filename = url.replace('://', '_').replace('/', '_')    
        destination_filename = \
            os.path.join(temp_dir,url_as_filename)
    if (not force_download) and (os.path.isfile(destination_filename)):
        print('Bypassing download of already-downloaded file {}'.format(
            os.path.basename(url)))
        return destination_filename
    print('Downloading file {} to {}'.format(os.path.basename(url),
                                             destination_filename),end='')
    urllib.request.urlretrieve(url, destination_filename, progress_updater)  
    assert(os.path.isfile(destination_filename))
    nBytes = os.path.getsize(destination_filename)
    print('...done, {} bytes.'.format(nBytes))
    return destination_filename


def lat_lon_to_nasadem_tile(lat,lon):
    """
    Get the NASADEM file name for a specified latitude and longitude
    """
    
    # A tile name looks like:
    #
    # NASADEM_NUMNC_n00e016.nc
    #
    # The translation from lat/lon to that string is represented nicely at:
    #
    # https://dwtkns.com/srtm30m/

    # Force download of the file list
    get_nasadem_file_list()
        
    ns_token = 'n' if lat >=0 else 's'
    ew_token = 'e' if lon >=0 else 'w'
    
    lat_index = abs(math.floor(lat))
    lon_index = abs(math.floor(lon))
    
    lat_string = ns_token + '{:02d}'.format(lat_index)
    lon_string = ew_token + '{:03d}'.format(lon_index)
    
    filename =  nasadem_file_prefix + lat_string + lon_string + \
        nasadem_content_extension

    if filename not in nasadem_file_list:
        print('Lat/lon {},{} not available'.format(lat,lon))
        filename = None
    
    return filename


def get_nasadem_file_list():
    """
    Retrieve the full list of NASADEM tiles
    """
    
    global nasadem_file_list
    if nasadem_file_list is None:
        nasadem_file = download_url(nasadem_file_index_url)
        with open(nasadem_file) as f:
            nasadem_file_list = f.readlines()
            nasadem_file_list = [f.strip() for f in nasadem_file_list]
            nasadem_file_list = [f for f in nasadem_file_list if \
                                 f.endswith(nasadem_content_extension)]
    return nasadem_file_list

Download a NASADEM tile for a known lat/lon

In [28]:
# Interesting places for looking at SRTM data
everest = [27.9881,86.9250]
seattle = [47.6062,-122.3321]
grand_canyon = [36.101690, -112.107676]
mount_fuji = [35.3606, 138.7274]
mont_blanc = [45.832778, 6.865000]
invalid = [-15.1,41]

tile_of_interest = mount_fuji

tile_name = lat_lon_to_nasadem_tile(tile_of_interest[0],tile_of_interest[1])
url = nasadem_blob_root + tile_name
fn = download_url(url,progress_updater=DownloadProgressBar())
Bypassing download of already-downloaded file nasadem_file_list.txt
Bypassing download of already-downloaded file NASADEM_NC_n35e138.nc

Load and plot the tile

In [29]:
fh = Dataset(fn, mode='r')
heights = fh['NASADEM_HGT'][:]
lons = fh.variables['lon'][:]
lats = fh.variables['lat'][:]

min_height = np.min(heights)
max_height = np.max(heights)
height_units = fh.variables['NASADEM_HGT'].units

fh.close()

print('Height ranges from {} {} to {} {}'.format(min_height,height_units,
      max_height,height_units))

extent = [np.min(lons), np.max(lons), np.min(lats), np.max(lats)]
plt.imshow(heights,extent=extent)
plt.xlabel('Longitude')
plt.ylabel('Latitude')
cb = plt.colorbar()
cb.set_label('Height ({})'.format(height_units))
Height ranges from -18 meters to 3756 meters

Also plot on a basemap

In [30]:
# To plot on a basemap, we'll want to downsample the data substantially
ds_factor = 10

# Show a little space around each edge on the basemap (this is in lat/lon units)
expansion_distance = 0.75

lon_0 = lons.mean()
lat_0 = lats.mean()
lons_ds = lons[::ds_factor]
lats_ds = lats[::ds_factor]
heights_ds = heights[::ds_factor,::ds_factor,]

# Convert to a 2D grid for plotting
lon_plot, lat_plot = np.meshgrid(lons_ds, lats_ds)

plt.figure(num=None, figsize=(8, 8), dpi=100)

m = Basemap(projection='stere',resolution='l',
            lat_ts=lat_0,lat_0=lat_0,lon_0=lon_0,
            llcrnrlon=extent[0]-expansion_distance, 
            llcrnrlat=extent[2]-expansion_distance,
            urcrnrlon=extent[1]+expansion_distance,
            urcrnrlat=extent[3]+expansion_distance)

xi, yi = m(lon_plot, lat_plot)

cs = m.pcolor(xi,yi,np.squeeze(heights_ds))

# Add grid lines
m.drawparallels(np.arange(-80., 81., 10.), labels=[1,0,0,0], fontsize=10)
m.drawmeridians(np.arange(-180., 181., 10.), labels=[0,0,0,1], fontsize=10)

# Add coastlines and state/country borders

# drawcoastlines() fails when no coastlines are visible
try:
    m.drawcoastlines()
except:
    pass
m.drawstates()
m.drawcountries()

cbar = m.colorbar(cs, location='bottom', pad="10%")
cbar.set_label(height_units)
plt.title('SRTM height')
plt.show()

Clean up temporary files

In [18]:
shutil.rmtree(temp_dir)