Skip to content
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

add a new service called plantation mapping #6

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions landcover_viewer/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
'get-download-url',
'download-to-drive',
'get-stats',
'get-composite'
]

@csrf_exempt
Expand Down Expand Up @@ -93,6 +94,9 @@ def api(request):
elif action == 'get-stats':
data = core.get_stats(year=year, primitives=primitives)

elif action == 'get-composite':
data = core.get_composite(year=year)

elif action == 'download-to-drive':
session_get = request.session.get
if session_get('email') and session_get('sub') and session_get('credentials'):
Expand Down
35 changes: 25 additions & 10 deletions landcover_viewer/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class LandCoverViewer():

PROBABILITY_MAP = ee.ImageCollection('users/servirmekong/LandCover')

YEARLY_COMPOSITES = ee.ImageCollection('projects/servir-mekong/yearlyComposites')

# geometries
MEKONG_FEATURE_COLLECTION = ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw')
COUNTRIES_GEOM = MEKONG_FEATURE_COLLECTION.filter(ee.Filter.inList('Country',
Expand Down Expand Up @@ -176,7 +178,7 @@ def __init__(self, area_path, area_name, shape, geom, radius, center, version):
'color': '800080'
}
]

self.INDEX_CLASS = {}
for _class in self.LANDCOVERCLASSES:
self.INDEX_CLASS[int(_class['value'])] = _class['name']
Expand Down Expand Up @@ -205,7 +207,7 @@ def __init__(self, area_path, area_name, shape, geom, radius, center, version):
self.PRIMITIVES = [
PRIMITIVE_BARREN, PRIMITIVE_BUILTUP, PRIMITIVE_CANOPY, PRIMITIVE_CROPLAND, PRIMITIVE_DECIDUOUS,
PRIMITIVE_EPHEMERAL_WATER, PRIMITIVE_EVERGREEN, PRIMITIVE_EVERGREEN_BROADLEAF, PRIMITIVE_EVERGREEN_NEEDLELEAF,
PRIMITIVE_GRASS, PRIMITIVE_IMPERVIOUS, PRIMITIVE_IRRIGATED, PRIMITIVE_MANGROVE,
PRIMITIVE_GRASS, PRIMITIVE_IMPERVIOUS, PRIMITIVE_IRRIGATED, PRIMITIVE_MANGROVE,
PRIMITIVE_RICE, PRIMITIVE_SHRUB, PRIMITIVE_SNOW_ICE, PRIMITIVE_SURFACE_WATER, PRIMITIVE_TREE_HEIGHT
]
elif version and version == 'v2':
Expand Down Expand Up @@ -304,7 +306,7 @@ def __init__(self, area_path, area_name, shape, geom, radius, center, version):
'color': '51768e'
}
]

self.INDEX_CLASS = {}
for _class in self.LANDCOVERCLASSES:
self.INDEX_CLASS[int(_class['value'])] = _class['name']
Expand Down Expand Up @@ -432,7 +434,7 @@ def __init__(self, area_path, area_name, shape, geom, radius, center, version):
'color': '51768e'
}
]

self.INDEX_CLASS = {}
for _class in self.LANDCOVERCLASSES:
self.INDEX_CLASS[int(_class['value'])] = _class['name']
Expand Down Expand Up @@ -530,7 +532,7 @@ def get_primitive(self, index=0, year=2016, download=False):

primitive_img_coll = self.PRIMITIVES[index]

image_collection = primitive_img_coll.filterDate('%s-01-01' % year,
image_collection = primitive_img_coll.filterDate('%s-01-01' % year,
'%s-12-31' % year)
if image_collection.size().getInfo() > 0:
image = ee.Image(image_collection.mean())
Expand Down Expand Up @@ -574,7 +576,6 @@ def get_probability(self, year=2017, download=False):
'max': '100',
'palette': 'red,orange,yellow,green,darkgreen'
})

return {
'eeMapId': str(map_id['mapid']),
'eeMapToken': str(map_id['token'])
Expand Down Expand Up @@ -673,7 +674,7 @@ def download_to_drive(self,
print ('past %d seconds' % (i * settings.EE_TASK_POLL_FREQUENCY))
i += 1
time.sleep(settings.EE_TASK_POLL_FREQUENCY)

# Make a copy (or copies) in the user's Drive if the task succeeded
state = task.status()['state']
if state == ee.batch.Task.State.COMPLETED:
Expand All @@ -694,14 +695,14 @@ def download_to_drive(self,
'from_address': settings.EMAIL_HOST_USER,
'to_address': [user_email]
}

# send notification to user
send_email(email_data, html=True)

# create email object
email_data['to_address'] = user_email
email = Email.objects.create(**email_data)

# update export drive
ExportDrive.objects.filter(pk=export_id).update(
email = email,
Expand Down Expand Up @@ -741,3 +742,17 @@ def get_stats(self, year=2016, primitives=range(0, 21)):
return {self.INDEX_CLASS[int(float(k))]:float('{0:.2f}'.format(v)) for k,v in data.items()}

# =============================================================================
def get_composite(self, year=2017):

image = ee.Image(LandCoverViewer.YEARLY_COMPOSITES.filterDate('%s-01-01' % year, '%s-12-31' % year).first()).clip(self.geometry)

map_id = image.getMapId({
'min': 0,
'max': 6000,
'bands': 'swir1,nir,red'
})

return {
'eeMapId': str(map_id['mapid']),
'eeMapToken': str(map_id['token'])
}
3 changes: 2 additions & 1 deletion landcoverportal/settings_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
'landcover_viewer',
'myanmar_ipcc',
'myanmar_fra',
'plantation_mapping',
'main',
# Google Oauth
'django.contrib.sessions.middleware',
Expand Down Expand Up @@ -259,7 +260,7 @@
CMS_PLACEHOLDER_CONF = {}

MIGRATION_MODULES = {

}

THUMBNAIL_PROCESSORS = (
Expand Down
66 changes: 61 additions & 5 deletions landcoverportal/static/app/config/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,48 @@ var settings = {
'value': '9'
}
],
myanmarPlantationClasses: [
{
'name': 'Unknown',
'value': '0',
'color': '#6f6f6f'
},
{
'name': 'Surface water',
'value': '1',
'color': '#aec3d4'
},
{
'name': 'Forest',
'value': '2',
'color': '#152106'
},
{
'name': 'Urban and built up',
'value': '3',
'color': '#cc0013'
},
{
'name': 'Cropland',
'value': '4',
'color': '#8dc33b'
},
{
'name': 'Rubber',
'value': '5',
'color': '#3bc3b2'
},
{
'name': 'Palmoil',
'value': '6',
'color': '#800080'
},
{
'name': 'Mangrove',
'value': '7',
'color': '#111149'
}
],
serviceApplicationsCards: [{
'name': 'Regional Land Cover Monitoring System',
'description': 'The regional land cover monitoring system provides ' +
Expand Down Expand Up @@ -846,10 +888,10 @@ var settings = {
},
{
'name': 'Myanmar National Classification',
'description': 'SERVIR-Mekong and partners are collaborating and supporting ' +
'description': 'SERVIR-Mekong and partners are collaborating and supporting ' +
'the Forest Department of Myanmar to improve the land cover monitoring system ' +
'of Myanmar, which contributes for sustainable land use management. <br/>' +
'The national land cover product comprises of 11 classes (namely, ' +
'of Myanmar, which contributes for sustainable land use management. <br/>' +
'The national land cover product comprises of 11 classes (namely, ' +
'Closed Forest, Opened Forest, Other Wooded Land, Mangroves, Wetlands, ' +
'Snow and Ice, Cropland, Built up, Grassland, Surface Water and Others) ' +
'and is produced annually. These national land cover products are the ' +
Expand Down Expand Up @@ -909,13 +951,27 @@ var settings = {
'from 2006 and 2015 are products of this application.',
'url': 'https://code.earthengine.google.com/64330db9b75742d76777ce01fe131001',
'imageURL': 'images/solr.png'
},
{
'name': 'Plantations Mapping',
'description': 'The Dawna Tenasserim Landscape covers Kayin and Mon States, and ' +
'Tanintharyi Region in Myanmar. The area harbours one of the last large intact ' +
'forest landscapes in the region, which hosts a large number of ethnic groups, and ' +
'a wide variety of endangered wildlife such as elephants and tigers. The region is experiencing ' +
'numerous threats including rapid increase in agricultural land use and associated deforestation, ' +
'notably for rubber and palm oil, road and infrastructure development, and logging resulting in habitat ' +
'degradation and fragmentation. The Dawna Tenasserim plantation portal shows areas with cropland, rubber, ' +
'palmoil for 2017 and 2018. '+
'<br><i> Remote Sens. 2019, 11(7), 831; <a href="https://doi.org/10.3390/rs11070831">https://doi.org/10.3390/rs11070831</a> </i>',
'url': '/plantation/',
'imageURL': 'images/plantation-mapping.jpg'
}
]
};

/*var myanmarPrimitiveClasses = JSON.parse(JSON.stringify(settings.myanmarFRALandCoverClasses));
for (var i = 0; i <= myanmarPrimitiveClasses.length - 1; i++) {
delete myanmarPrimitiveClasses[i].color;
for (var i = 0; i <= myanmarPrimitiveClasses.length - 1; i++) {
delete myanmarPrimitiveClasses[i].color;
}

settings.myanmarPrimitiveClasses = myanmarPrimitiveClasses;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,12 @@

// Analysis Tool Control
$scope.toggleToolControl = function () {
if ($('#analysis-tool-control i').hasClass('fas fa-chart-pie control-gray-color')) {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie control-gray-color').addClass('fas fa-chart-pie');
$scope.showTabContainer = true;
} else {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie').addClass('fas fa-chart-pie control-gray-color');
if ($('#analysis-tool-control i').hasClass('fas fa-times')) {
$('#analysis-tool-control i').removeClass('fas fa-times').addClass('fas fa-chart-pie');
$scope.showTabContainer = false;
} else {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie').addClass('fas fa-times');
$scope.showTabContainer = true;
}
$scope.$apply();
};
Expand Down
102 changes: 88 additions & 14 deletions landcoverportal/static/app/controllers/landcover-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,17 @@
* Start with UI
*/

// Analysis Tool Control
$scope.toggleToolControl = function () {
if ($('#analysis-tool-control i').hasClass('fas fa-chart-pie control-gray-color')) {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie control-gray-color').addClass('fas fa-chart-pie');
$scope.showTabContainer = true;
} else {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie').addClass('fas fa-chart-pie control-gray-color');
$scope.showTabContainer = false;
}
$scope.$apply();
};
// Analysis Tool Control
$scope.toggleToolControl = function () {
if ($('#analysis-tool-control i').hasClass('fas fa-times')) {
$('#analysis-tool-control i').removeClass('fas fa-times').addClass('fas fa-chart-pie');
$scope.showTabContainer = false;
} else {
$('#analysis-tool-control i').removeClass('fas fa-chart-pie').addClass('fas fa-times');
$scope.showTabContainer = true;
}
$scope.$apply();
};


var analysisToolControlDiv = document.getElementById('tool-control-container');
Expand Down Expand Up @@ -802,7 +802,6 @@
// check to see if probability map exists
// does not exists for v1 products
if ($('#probability-map-container').length > 0) {

// Probability Map
// Probability opacity slider
$scope.probabilityOpacity = 1;
Expand Down Expand Up @@ -841,7 +840,8 @@
year: $scope.sliderYear,
shape: $scope.shape,
areaSelectFrom: $scope.areaSelectFrom,
areaName: $scope.areaName
areaName: $scope.areaName,
type: 'landcover'
};

LandCoverService.getProbabilityMap(parameters)
Expand Down Expand Up @@ -877,7 +877,81 @@
}

};
}
}

$scope.compositeOpacity = 1;
$scope.showCompositeOpacityController = true;
/* slider init */
$scope.compositeSlider = $('#composite-opacity-slider').slider({
formatter: function (value) {
return 'Opacity: ' + value;
},
tooltip: 'none'
})
.on('slideStart', function (event) {
$scope.compositeOpacity = $(this).data('slider').getValue();
})
.on('slideStop', function (event) {
var value = $(this).data('slider').getValue();
if (value !== $scope.compositeOpacity) {
$scope.compositeOpacity = value;
$scope.overlays.compositemap.setOpacity(value);
}
});

$scope.togglecompositeOpacityController = function () {
var checked = $('#composite-map-checkbox').prop('checked');
if (checked) {
$scope.showCompositeOpacityController = true;
} else {
$scope.showCompositeOpacityController = false;
}
};

$scope.showCompositeMap = function () {
$scope.togglecompositeOpacityController();
$timeout(function () {
var parameters = {
year: $scope.sliderYear,
shape: $scope.shape,
areaSelectFrom: $scope.areaSelectFrom,
areaName: $scope.areaName,
type: 'landcover'
};

LandCoverService.getCompositeMap(parameters)
.then(function (data) {
MapService.removeGeoJson(map);
MapService.clearLayer(map, 'compositemap');
var mapType = MapService.getMapType(data.eeMapId, data.eeMapToken, 'compositemap');
var checked = $('#composite-map-checkbox').prop('checked');
loadMap('compositemap', mapType);
if (checked) {
$timeout(function () {
showInfoAlert('Showing Yearly Composite Layer for ' + $scope.sliderYear);
}, 5500);
$scope.showCompositeLayer = true;
} else {
$scope.overlays.compositemap.setOpacity(0);
}
}, function (error) {
showErrorAlert(error.error);
console.log(error);
});
}, 15000);
};

$scope.toggleCompositeMap = function () {
var checked = $('#composite-map-checkbox').prop('checked');
if (checked) {
$scope.showCompositeOpacityController = true;
$scope.overlays.compositemap.setOpacity($scope.compositeOpacity);
} else {
$scope.showCompositeOpacityController = false;
$scope.overlays.compositemap.setOpacity(0);
}

};

});

Expand Down
Loading