-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modis 6 #53
Modis 6 #53
Changes from all commits
f7874c3
9e2d811
55b57d5
17b21bf
3a9deaf
fab2386
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,13 +70,13 @@ class modisAsset(Asset): | |
|
||
_assets = { | ||
'MCD43A4': { | ||
'pattern': 'MCD43A4*hdf', | ||
'pattern': 'MCD43A4.A???????.h??v??.???.?????????????.hdf', | ||
'url': 'http://e4ftl01.cr.usgs.gov/MOTA/MCD43A4.006', | ||
'startdate': datetime.date(2000, 2, 18), | ||
'latency': -15 | ||
}, | ||
'MCD43A2': { | ||
'pattern': 'MCD43A2*hdf', | ||
'pattern': 'MCD43A2.A???????.h??v??.???.?????????????.hdf', | ||
'url': 'http://e4ftl01.cr.usgs.gov/MOTA/MCD43A2.006', | ||
'startdate': datetime.date(2000, 2, 18), | ||
'latency': -15 | ||
|
@@ -150,15 +150,23 @@ class modisAsset(Asset): | |
def __init__(self, filename): | ||
""" Inspect a single file and get some metadata """ | ||
super(modisAsset, self).__init__(filename) | ||
bname = os.path.basename(filename) | ||
self.asset = bname[0:7] | ||
self.tile = bname[17:23] | ||
year = bname[9:13] | ||
doy = bname[13:16] | ||
|
||
bname = os.path.basename(filename) | ||
parts = bname.split('.') | ||
|
||
self.asset = parts[0] | ||
self.tile = parts[2] | ||
self.sensor = parts[0][:3] | ||
|
||
year = parts[1][1:5] | ||
doy = parts[1][5:8] | ||
self.date = datetime.datetime.strptime(year + doy, "%Y%j").date() | ||
self.sensor = bname[:3] | ||
|
||
collection = int(parts[3]) | ||
file_version = int(parts[4]) | ||
self.version = float('{}.{}'.format(collection, file_version)) | ||
|
||
|
||
@classmethod | ||
def fetch(cls, asset, tile, date): | ||
#super(modisAsset, cls).fetch(asset, tile, date) | ||
|
@@ -209,7 +217,16 @@ def fetch(cls, asset, tile, date): | |
#raise Exception('Unable to find remote match for %s at %s' % (pattern, mainurl)) | ||
VerboseOut('Unable to find remote match for %s at %s' % (pattern, mainurl), 4) | ||
|
||
|
||
def updated(self, newasset): | ||
''' | ||
Compare the version for this to that of newasset. | ||
Return true if newasset version is greater. | ||
''' | ||
return (self.sensor == newasset.sensor and | ||
self.tile == newasset.tile and | ||
self.date == newasset.date and | ||
self.version < newasset.version) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it meaningful to compare two assets if they don't match in the first three comparators? If not I suggest raising an exception: def newer_than(self, other):
if (self.sensor, self.tile, self.date) != (other.sensor, other.tile, other.date):
raise ValueError("Can't compare versions of mismatched data", self, other)
return self.version < other.version |
||
|
||
class modisData(Data): | ||
""" A tile of data (all assets and products) """ | ||
name = 'Modis' | ||
|
@@ -291,7 +308,8 @@ def process(self, *args, **kwargs): | |
missingassets = [] | ||
availassets = [] | ||
allsds = [] | ||
|
||
versions = {} | ||
|
||
# Default sensor for products | ||
sensor = 'MCD' | ||
|
||
|
@@ -303,6 +321,8 @@ def process(self, *args, **kwargs): | |
else: | ||
availassets.append(asset) | ||
allsds.extend(sds) | ||
versions[asset] = int(re.findall('M.*\.00(\d)\.\d{13}\.hdf', sds[0])[0]) | ||
|
||
if not availassets: | ||
# some products aren't available for every day but this is trying every day | ||
VerboseOut('There are no available assets (%s) on %s for tile %s' | ||
|
@@ -312,7 +332,6 @@ def process(self, *args, **kwargs): | |
meta = self.meta_dict() | ||
meta['AVAILABLE_ASSETS'] = ' '.join(availassets) | ||
|
||
|
||
if val[0] == "landcover": | ||
fname = '%s_%s_%s.tif' % (bname, sensor, key) | ||
if os.path.lexists(fname): | ||
|
@@ -322,6 +341,8 @@ def process(self, *args, **kwargs): | |
|
||
|
||
if val[0] == "refl": | ||
if versions[asset] != 6: | ||
raise Exception('product version not supported') | ||
fname = '%s_%s_%s.tif' % (bname, sensor, key) | ||
img = gippy.GeoImage(sds[7:]) | ||
nodata = img[0].NoDataValue() | ||
|
@@ -337,6 +358,8 @@ def process(self, *args, **kwargs): | |
|
||
|
||
if val[0] == "quality": | ||
if versions[asset] != 6: | ||
raise Exception('product version not supported') | ||
fname = '%s_%s_%s.tif' % (bname, sensor, key) | ||
img = gippy.GeoImage(sds[:7]) | ||
nodata = img[0].NoDataValue() | ||
|
@@ -353,22 +376,29 @@ def process(self, *args, **kwargs): | |
|
||
# LAND VEGETATION INDICES PRODUCT | ||
if val[0] == "indices": | ||
|
||
VERSION = "2.0" | ||
meta['VERSION'] = VERSION | ||
sensor = 'MCD' | ||
fname = '%s_%s_%s' % (bname, sensor, key) | ||
|
||
refl = gippy.GeoImage(allsds) | ||
|
||
missing = 32767 | ||
|
||
redimg = refl[7].Read() | ||
nirimg = refl[8].Read() | ||
bluimg = refl[9].Read() | ||
grnimg = refl[10].Read() | ||
mirimg = refl[11].Read() | ||
swrimg = refl[12].Read() # formerly swir2 | ||
if versions[asset] == 6: | ||
redimg = refl[7].Read() | ||
nirimg = refl[8].Read() | ||
bluimg = refl[9].Read() | ||
grnimg = refl[10].Read() | ||
mirimg = refl[11].Read() | ||
swrimg = refl[12].Read() # formerly swir2 | ||
elif versions[asset] == 5: | ||
redimg = refl[0].Read() | ||
nirimg = refl[1].Read() | ||
bluimg = refl[2].Read() | ||
grnimg = refl[3].Read() | ||
mirimg = refl[4].Read() | ||
swrimg = refl[5].Read() # formerly swir2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a way to cut down on the cutpasting, with something like this: offset = {5: 0, 6: 7}[versions[asset]]
redimg, nirimg, bluimg, grnimg, mirimg, swrimg = [refl[offset + i].Read() for i in range(6)] What you wrote is super clear and easy to understand however, so I can see your way being more maintainable. (edit: Oops, forgot There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried both ways and went for clarity but I’m OK either ways.
|
||
else: | ||
raise Exception('product version not supported') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest telling the user which product version isn't supported, eg:
(edit: changed to a different exception type because usually |
||
|
||
redimg[redimg < 0.0] = 0.0 | ||
nirimg[nirimg < 0.0] = 0.0 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,8 @@ | |
from gips.data.core import Data | ||
from gips.mapreduce import MapReduce | ||
|
||
from pdb import set_trace | ||
|
||
|
||
class Inventory(object): | ||
""" Base class for inventories """ | ||
|
@@ -234,7 +236,7 @@ def map_reduce(self, func, numbands=1, products=None, readfunc=None, nchunks=100 | |
class DataInventory(Inventory): | ||
""" Manager class for data inventories (collection of Tiles class) """ | ||
|
||
def __init__(self, dataclass, spatial, temporal, products=None, fetch=False, **kwargs): | ||
def __init__(self, dataclass, spatial, temporal, products=None, fetch=False, update=False, **kwargs): | ||
""" Create a new inventory | ||
:dataclass: The Data class to use (e.g., LandsatData, ModisData) | ||
:spatial: The spatial extent requested | ||
|
@@ -250,12 +252,16 @@ def __init__(self, dataclass, spatial, temporal, products=None, fetch=False, **k | |
self.temporal = temporal | ||
self.products = dataclass.RequestedProducts(products) | ||
|
||
self.update = update | ||
|
||
print "datainventory" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this supposed to stay in? Looks like a stray debugging statement. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, there are also “from pdb import set_trace” statements, sorry.
|
||
|
||
if fetch: | ||
try: | ||
dataclass.fetch(self.products.base, self.spatial.tiles, self.temporal) | ||
dataclass.fetch(self.products.base, self.spatial.tiles, self.temporal, self.update) | ||
except Exception, e: | ||
raise Exception('Error downloading %s: %s' % (dataclass.name, e)) | ||
dataclass.Asset.archive(Repository.path('stage')) | ||
dataclass.Asset.archive(Repository.path('stage'), update=self.update) | ||
|
||
# find data | ||
self.data = {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
or
checks for truth so you don't need to do it explicitly:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, that makes sense.