Skip to content

Commit cd100f6

Browse files
author
Scisco
committed
Merge pull request #169 from developmentseed/develop
v0.12.2
2 parents 14f14ec + 18120db commit cd100f6

10 files changed

+197
-191
lines changed

CHANGES.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Changes
22
=======
33

4+
0.12.2 (2016-02-18)
5+
------------------
6+
- Fix for #167
7+
- Fix for #145
8+
49
0.12.0 (2016-02-18)
510
------------------
611
- Add USGS download fallback closes #89

landsat/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.12.1'
1+
__version__ = '0.12.2'

landsat/downloader.py

+85-85
Original file line numberDiff line numberDiff line change
@@ -58,42 +58,49 @@ def download(self, scenes, bands=None):
5858
"""
5959

6060
if isinstance(scenes, list):
61-
output = {}
61+
files = []
6262

6363
for scene in scenes:
64-
# If bands are provided the image is from 2015 or later use Amazon
65-
self.scene_interpreter(scene)
66-
67-
if (bands and int(scene[12]) > 4):
68-
if isinstance(bands, list):
69-
# Create a folder to download the specific bands into
70-
path = check_create_folder(join(self.download_dir, scene))
71-
try:
72-
# Always grab MTL.txt if bands are specified
73-
if 'BQA' not in bands:
74-
bands.append('QA')
75-
76-
if 'MTL' not in bands:
77-
bands.append('MTL')
78-
79-
for band in bands:
80-
self.amazon_s3(scene, band, path)
81-
output[scene] = 'aws'
82-
except RemoteFileDoesntExist:
83-
self.google_storage(scene, self.download_dir)
84-
output[scene] = 'google'
85-
86-
else:
87-
raise Exception('Expected bands list')
88-
else:
89-
self.google_storage(scene, self.download_dir)
90-
output[scene] = 'google'
91-
92-
return output
64+
65+
# for all scenes if bands provided, first check AWS, if the bands exist
66+
# download them, otherwise use Google and then USGS.
67+
try:
68+
# if bands are not provided, directly go to Goodle and then USGS
69+
if not isinstance(bands, list):
70+
raise RemoteFileDoesntExist
71+
files.append(self.amazon_s3(scene, bands))
72+
73+
except RemoteFileDoesntExist:
74+
try:
75+
files.append(self.google_storage(scene, self.download_dir))
76+
except RemoteFileDoesntExist:
77+
files.append(self.usgs_eros(scene, self.download_dir))
78+
79+
return files
9380

9481
else:
9582
raise Exception('Expected sceneIDs list')
9683

84+
def usgs_eros(self, scene, path):
85+
""" Downloads the image from USGS """
86+
87+
# download from usgs if login information is provided
88+
if self.usgs_user and self.usgs_pass:
89+
try:
90+
api_key = api.login(self.usgs_user, self.usgs_pass)
91+
except USGSError as e:
92+
error_tree = ElementTree.fromstring(str(e.message))
93+
error_text = error_tree.find("SOAP-ENV:Body/SOAP-ENV:Fault/faultstring", api.NAMESPACES).text
94+
raise USGSInventoryAccessMissing(error_text)
95+
96+
download_url = api.download('LANDSAT_8', 'EE', [scene], api_key=api_key)
97+
if download_url:
98+
self.output('Source: USGS EarthExplorer', normal=True, arrow=True)
99+
return self.fetch(download_url[0], path)
100+
101+
raise RemoteFileDoesntExist('%s is not available on AWS S3, Google or USGS Earth Explorer' % scene)
102+
raise RemoteFileDoesntExist('%s is not available on AWS S3 or Google Storage' % scene)
103+
97104
def google_storage(self, scene, path):
98105
"""
99106
Google Storage Downloader.
@@ -110,67 +117,49 @@ def google_storage(self, scene, path):
110117
:returns:
111118
Boolean
112119
"""
113-
sat = self.scene_interpreter(scene)
114120

115-
filename = scene + '.tar.bz'
121+
sat = self.scene_interpreter(scene)
116122
url = self.google_storage_url(sat)
117123

118-
if self.remote_file_exists(url):
119-
return self.fetch(url, path, filename)
124+
self.remote_file_exists(url)
120125

121-
else:
122-
# download from usgs if login information is provided
123-
if self.usgs_user and self.usgs_pass:
124-
try:
125-
api_key = api.login(self.usgs_user, self.usgs_pass)
126-
except USGSError as e:
127-
error_tree = ElementTree.fromstring(str(e.message))
128-
error_text = error_tree.find("SOAP-ENV:Body/SOAP-ENV:Fault/faultstring", api.NAMESPACES).text
129-
raise USGSInventoryAccessMissing(error_text)
126+
self.output('Source: Google Storge', normal=True, arrow=True)
127+
return self.fetch(url, path)
130128

131-
download_url = api.download('LANDSAT_8', 'EE', [scene], api_key=api_key)
132-
if download_url:
133-
return self.fetch(download_url[0], path, filename)
129+
def amazon_s3(self, scene, bands):
130+
"""
131+
Amazon S3 downloader
132+
"""
134133

135-
raise RemoteFileDoesntExist('%s is not available on AWS S3, Google or USGS Earth Explorer' % filename)
134+
sat = self.scene_interpreter(scene)
136135

137-
raise RemoteFileDoesntExist('%s is not available on AWS S3 or Google Storage' % filename)
136+
# Always grab MTL.txt and QA band if bands are specified
137+
if 'BQA' not in bands:
138+
bands.append('QA')
138139

139-
def amazon_s3(self, scene, band, path):
140-
"""
141-
Amazon S3 downloader
140+
if 'MTL' not in bands:
141+
bands.append('MTL')
142142

143-
:param scene:
144-
The scene ID.
145-
:type scene:
146-
String
147-
:param band:
148-
The band number.
149-
:type band:
150-
String, Integer
151-
:param path:
152-
The directory path to where the image should be stored
153-
:type path:
154-
String
143+
urls = []
155144

156-
:returns:
157-
Boolean
158-
"""
159-
sat = self.scene_interpreter(scene)
145+
for band in bands:
146+
# get url for the band
147+
url = self.amazon_s3_url(sat, band)
160148

161-
if band != 'MTL':
162-
filename = '%s_B%s.TIF' % (scene, band)
163-
else:
164-
filename = '%s_%s.txt' % (scene, band)
165-
url = self.amazon_s3_url(sat, filename)
149+
# make sure it exist
150+
self.remote_file_exists(url)
151+
urls.append(url)
166152

167-
if self.remote_file_exists(url):
168-
return self.fetch(url, path, filename)
153+
# create folder
154+
path = check_create_folder(join(self.download_dir, scene))
169155

170-
else:
171-
raise RemoteFileDoesntExist('%s is not available on Amazon S3' % filename)
156+
self.output('Source: AWS S3', normal=True, arrow=True)
157+
for url in urls:
158+
self.fetch(url, path)
159+
160+
return path
172161

173-
def fetch(self, url, path, filename):
162+
def fetch(self, url, path):
174163
""" Downloads the given url.
175164
176165
:param url:
@@ -190,18 +179,26 @@ def fetch(self, url, path, filename):
190179
Boolean
191180
"""
192181

182+
segments = url.split('/')
183+
filename = segments[-1]
184+
185+
# remove query parameters from the filename
186+
filename = filename.split('?')[0]
187+
193188
self.output('Downloading: %s' % filename, normal=True, arrow=True)
194189

190+
# print(join(path, filename))
191+
# raise Exception
195192
if exists(join(path, filename)):
196193
size = getsize(join(path, filename))
197194
if size == self.get_remote_file_size(url):
198195
self.output('%s already exists on your system' % filename, normal=True, color='green', indent=1)
199-
return False
200196

201-
fetch(url, path)
197+
else:
198+
fetch(url, path)
202199
self.output('stored at %s' % path, normal=True, color='green', indent=1)
203200

204-
return True
201+
return join(path, filename)
205202

206203
def google_storage_url(self, sat):
207204
"""
@@ -218,7 +215,7 @@ def google_storage_url(self, sat):
218215
filename = sat['scene'] + '.tar.bz'
219216
return url_builder([self.google, sat['sat'], sat['path'], sat['row'], filename])
220217

221-
def amazon_s3_url(self, sat, filename):
218+
def amazon_s3_url(self, sat, band):
222219
"""
223220
Return an amazon s3 url the contains the scene and band provided.
224221
@@ -234,6 +231,11 @@ def amazon_s3_url(self, sat, filename):
234231
:returns:
235232
(String) The URL to a S3 file
236233
"""
234+
if band != 'MTL':
235+
filename = '%s_B%s.TIF' % (sat['scene'], band)
236+
else:
237+
filename = '%s_%s.txt' % (sat['scene'], band)
238+
237239
return url_builder([self.s3, sat['sat'], sat['path'], sat['row'], sat['scene'], filename])
238240

239241
def remote_file_exists(self, url):
@@ -249,10 +251,8 @@ def remote_file_exists(self, url):
249251
"""
250252
status = requests.head(url).status_code
251253

252-
if status == 200:
253-
return True
254-
else:
255-
return False
254+
if status != 200:
255+
raise RemoteFileDoesntExist
256256

257257
def get_remote_file_size(self, url):
258258
""" Gets the filesize of a remote file.

landsat/landsat.py

+14-16
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,15 @@ def main(args):
324324
s = Search()
325325

326326
try:
327-
lat = float(args.lat) if args.lat else None
328-
lon = float(args.lon) if args.lon else None
327+
if args.lat is not None:
328+
lat = float(args.lat)
329+
else:
330+
lat = None
331+
332+
if args.lon is not None:
333+
lon = float(args.lon)
334+
else:
335+
lon = None
329336
except ValueError:
330337
return ["The latitude and longitude values must be valid numbers", 1]
331338

@@ -392,23 +399,14 @@ def main(args):
392399
if not args.bands:
393400
bands = [4, 3, 2]
394401

395-
downloaded = d.download(args.scenes, bands)
402+
files = d.download(args.scenes, bands)
396403

397404
if args.process:
398405
if not args.bands:
399406
args.bands = '432'
400407
force_unzip = True if args.force_unzip else False
401-
for scene, src in downloaded.iteritems():
402-
if args.dest:
403-
path = join(args.dest, scene)
404-
else:
405-
path = join(settings.DOWNLOAD_DIR, scene)
406-
407-
# Keep using Google if the image is before 2015
408-
if src == 'google':
409-
path = path + '.tar.bz'
410-
411-
stored = process_image(path, args.bands, False, args.pansharpen, args.ndvi, force_unzip,
408+
for f in files:
409+
stored = process_image(f, args.bands, False, args.pansharpen, args.ndvi, force_unzip,
412410
args.ndvigrey, bounds=bounds)
413411

414412
if args.upload:
@@ -467,8 +465,8 @@ def process_image(path, bands=None, verbose=False, pansharpen=False, ndvi=False,
467465
p = Simple(path, bands=bands, dst_path=settings.PROCESSED_IMAGE, verbose=verbose, force_unzip=force_unzip,
468466
bounds=bounds)
469467

470-
except IOError:
471-
exit("Zip file corrupted", 1)
468+
except IOError as e:
469+
exit(e.message, 1)
472470
except FileDoesNotExist as e:
473471
exit(e.message, 1)
474472

landsat/search.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def query_builder(self, paths_rows=None, lat=None, lon=None, address=None, start
218218

219219
if address:
220220
query.append(self.address_builder(address))
221-
elif lat and lon:
221+
elif (lat is not None) and (lon is not None):
222222
query.append(self.lat_lon_builder(lat, lon))
223223

224224
if query:

requirements/docker.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ boto>=2.38.0
88
polyline==1.1
99
geocoder>=1.5.1
1010
jsonschema==2.5.1
11-
git+git://github.com/developmentseed/usgs@develop
11+
usgs==0.1.9

setup.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def readme():
3535
license='CCO',
3636
platforms='Posix; MacOS X; Windows',
3737
install_requires=[
38-
'usgs2==0.2.0',
38+
'usgs==0.1.9',
3939
'requests==2.7.0',
4040
'python-dateutil>=2.4.2',
4141
'numpy>=1.9.3',
@@ -47,7 +47,8 @@ def readme():
4747
'homura>=0.1.2',
4848
'boto>=2.38.0',
4949
'polyline==1.1',
50-
'geocoder>=1.5.1'
50+
'geocoder>=1.5.1',
51+
'matplotlib==1.5.1'
5152
],
5253
test_suite='nose.collector',
5354
tests_require=test_requirements

0 commit comments

Comments
 (0)