file - read - cómo leer los archivos binarios de NASA.hgt
binary file extension (5)
Estoy seguro de que esto es realmente simple si sabes algo sobre archivos binarios, pero soy un novato en ese aspecto.
¿Cómo extraería los datos de los archivos .hgt de la NASA? Aquí hay una descripción de www2.jpl.nasa.gov/srtm/faq.html:
Los archivos de datos SRTM tienen nombres como "N34W119.hgt". ¿A qué se refieren las letras y los números, y qué es el formato ".hgt"?
Cada archivo de datos cubre un bloque de un grado de latitud por un grado de longitud de la superficie de la Tierra. Los primeros siete caracteres indican la esquina suroeste del bloque, con N, S, E y W que se refieren al norte, sur, este y oeste. Por lo tanto, el archivo "N34W119.hgt" abarca las latitudes 34 a 35 norte y las longitudes 118-119 oeste (este archivo incluye el centro de Los Ángeles, California). La extensión de nombre de archivo ".hgt" simplemente significa la palabra "altura", que significa elevación. NO es un tipo de formato. Estos archivos están en formato "crudo" (sin encabezados y no comprimidos), enteros de 16 bits, elevación medida en metros sobre el nivel del mar, en proyección "geográfica" (latitud y longitud), con vacíos de datos indicados por -32768 . Los archivos internacionales de 3 segundos de arco tienen 1201 columnas y 1201 filas de datos, con un tamaño de archivo total de 2,884,802 bytes (= 1201 x 1201 x 2). Los archivos de 1 arco de Estados Unidos tienen 3601 columnas y 3601 filas de datos, con un tamaño total de 25,934,402 bytes (= 3601 x 3601 x 2). Para obtener más información, lea el archivo de texto "SRTM_Topo.txt" en http://edcftp.cr.usgs.gov/pub/data/srtm/Readme.html
¡Gracias por cualquier ayuda! Voy a utilizar estos datos en una secuencia de comandos python, por lo que si no puede utilizar ningún truco específico del idioma para otros idiomas, sería increíble.
Como los registros son de longitud fija (enteros de 16 bits con signo) y conoce el tamaño de la cuadrícula (1201 x 1201 o 3601x3601), el módulo struct de Python parece ideal (código no probado):
from struct import unpack,calcsize
# ''row_length'' being 1201 or 3601 and ''row'' being the raw data for one row
def read_row( row, row_length ):
format = ''h'' # h stands for signed short
for i in range(0, row_length):
offset = i * calcsize(format)
(height,) = unpack(format, row[offset : offset+calcsize(format))
# do something with the height
Describiéndolo en términos más genéricos, básicamente quiere leer el archivo en 2 bytes a la vez, analizar los bytes leídos como un entero de 16 bits con signo y procesarlo. Como ya conoce el tamaño de la cuadrícula, puede leerlo fila por fila o de cualquier otra manera que sea conveniente para su aplicación. También significa que puede buscar aleatoriamente coordenadas específicas dentro del archivo de datos.
Los archivos de datos SRTM de la NASA están en formato Big-Endian, por lo que dependiendo de la plataforma en la que esté leyendo los datos, es posible que tenga que hacer una conversión de Big-Endian a Little-Endian.
Existen numerosas fuentes sobre cómo hacer esto, no tengo experiencia con Python, así que no puedo ayudarte allí.
Pero si olvidas esto, tus valores van a estar completamente desordenados.
Si tiene photoshop, es posible que pueda jugar con la importación sin procesar para que lea estos archivos y los guarde en algo más útil. He tenido cierto éxito haciendo este tipo de cosas en el pasado.
Si desea un poco más de velocidad que la que obtiene de millones de llamadas a struct.unpack, eche un vistazo a array.array. Si bien la implementación de "struct-and-for-loop" lleva varios segundos en mi lenta portátil, lo siguiente es casi instantáneo:
from array import array
f = open(filename, ''rb'')
format = ''h''
row_length = 1201
data = array(format)
data.fromfile(f, row_length*row_length)
data.byteswap()
f.close()
Un ejemplo numpy probado:
import os
import math
import numpy
fn = ''DMV/N51E000.hgt''
siz = os.path.getsize(fn)
dim = int(math.sqrt(siz/2))
assert dim*dim*2 == siz, ''Invalid file size''
data = numpy.fromfile(fn, numpy.dtype(''>i2''), dim*dim).reshape((dim, dim))