Export plant health results

pull/782/head
Piero Toffanin 2020-01-17 14:55:37 -05:00
rodzic 692c9264b3
commit 59a746897b
5 zmienionych plików z 49 dodań i 48 usunięć

Wyświetl plik

@ -18,6 +18,7 @@ from .formulas import lookup_formula, get_algorithm_list
from .tasks import TaskNestedView
from rest_framework import exceptions
from rest_framework.response import Response
from worker.tasks import export_raster_index
ZOOM_EXTRA_LEVELS = 2
@ -410,21 +411,19 @@ class Tiles(TaskNestedView):
)
class Export(TaskNestedView):
def get(self, request, pk=None, project_pk=None):
def post(self, request, pk=None, project_pk=None):
"""
Export an orthophoto after applying a formula
"""
task = self.get_and_check_task(request, pk)
nodata = None
formula = self.request.query_params.get('formula')
bands = self.request.query_params.get('bands')
rescale = self.request.query_params.get('rescale')
formula = request.data.get('formula')
bands = request.data.get('bands')
# rescale = request.data.get('rescale')
if formula == '': formula = None
if bands == '': bands = None
if rescale == '': rescale = None
# if rescale == '': rescale = None
if not formula:
raise exceptions.ValidationError("You need to specify a formula parameter")
@ -437,17 +436,13 @@ class Export(TaskNestedView):
except ValueError as e:
raise exceptions.ValidationError(str(e))
if formula is not None and rescale is None:
rescale = "-1,1"
if nodata is not None:
nodata = np.nan if nodata == "nan" else float(nodata)
# if formula is not None and rescale is None:
# rescale = "-1,1"
url = get_raster_path(task, "orthophoto")
if not os.path.isfile(url):
raise exceptions.NotFound()
export_raster_index(url, expr, "/webodm/app/media/project/2/task/5392337b-cd3f-42ef-879d-b36149ef442f/assets/odm_orthophoto/export.tif")
return HttpResponse("OK")
celery_task_id = export_raster_index.delay(url, expr).task_id
return Response({'celery_task_id': celery_task_id})

Wyświetl plik

@ -49,7 +49,7 @@ class GetTaskResult(APIView):
return Response({'error': 'Task not ready'})
if file is not None:
filename = os.path.basename(file)
filename = request.query_params.get('filename', os.path.basename(file))
filesize = os.stat(file).st_size
f = open(file, "rb")

Wyświetl plik

@ -4,6 +4,8 @@ import '../css/LayersControlLayer.scss';
import Histogram from './Histogram';
import { Checkbox, ExpandButton } from './Toggle';
import Utils from '../classes/Utils';
import Workers from '../classes/Workers';
import ErrorMessage from './ErrorMessage';
import $ from 'jquery';
export default class LayersControlLayer extends React.Component {
@ -39,7 +41,8 @@ export default class LayersControlLayer extends React.Component {
bands: params.bands || "",
hillshade: params.hillshade || "",
histogramLoading: false,
exportLoading: false
exportLoading: false,
error: ""
};
this.rescale = params.rescale || "";
@ -79,6 +82,11 @@ export default class LayersControlLayer extends React.Component {
this.updateHistogramReq.abort();
this.updateHistogramReq = null;
}
if (this.exportReq){
this.exportReq.abort();
this.exportReq = null;
}
}
handleLayerClick = () => {
@ -188,9 +196,29 @@ export default class LayersControlLayer extends React.Component {
}
handleExport = e => {
this.setState({exportLoading: true});
this.setState({exportLoading: true, error: ""});
this.exportReq = $.ajax({
type: 'POST',
url: `/api/projects/${this.meta.task.project}/tasks/${this.meta.task.id}/orthophoto/export`,
data: this.getLayerParams()
}).done(result => {
if (result.celery_task_id){
Workers.waitForCompletion(result.celery_task_id, error => {
if (error) this.setState({exportLoading: false, error});
else{
this.setState({exportLoading: false});
Workers.downloadFile(result.celery_task_id, "odm_orthophoto_" + encodeURIComponent(this.state.formula) + ".tif");
}
});
}else if (result.error){
this.setState({exportLoading: false, error: result.error});
}else{
this.setState({exportLoading: false, error: "Invalid response: " + result});
}
}).fail(error => {
this.setState({exportLoading: false, error: JSON.stringify(error)});
});
}
render(){
@ -216,6 +244,8 @@ export default class LayersControlLayer extends React.Component {
colorMap={cmapValues}
onUpdate={this.handleHistogramUpdate} />
<ErrorMessage bind={[this, "error"]} />
{formula !== "" && algorithms ?
<div className="row form-group form-inline">
<label className="col-sm-3 control-label">Algorithm:</label>

Wyświetl plik

@ -4,6 +4,7 @@ import Storage from 'webodm/classes/Storage';
import L from 'leaflet';
import './ContoursPanel.scss';
import ErrorMessage from 'webodm/components/ErrorMessage';
import Workers from 'webodm/classes/Workers';
export default class ContoursPanel extends React.Component {
static defaultProps = {
@ -115,32 +116,6 @@ export default class ContoursPanel extends React.Component {
};
}
waitForCompletion = (taskId, celery_task_id, cb) => {
let errorCount = 0;
const check = () => {
$.ajax({
type: 'GET',
url: `/api/plugins/contours/task/${taskId}/contours/check/${celery_task_id}`
}).done(result => {
if (result.error){
cb(result.error);
}else if (result.ready){
cb();
}else{
// Retry
setTimeout(() => check(), 2000);
}
}).fail(error => {
console.warn(error);
if (errorCount++ < 10) setTimeout(() => check(), 2000);
else cb(JSON.stringify(error));
});
};
check();
}
addGeoJSONFromURL = (url, cb) => {
const { map } = this.props;
@ -197,7 +172,7 @@ export default class ContoursPanel extends React.Component {
data: data
}).done(result => {
if (result.celery_task_id){
this.waitForCompletion(taskId, result.celery_task_id, error => {
Workers.waitForCompletion(result.celery_task_id, error => {
if (error) this.setState({[loadingProp]: false, error});
else{
const fileUrl = `/api/plugins/contours/task/${taskId}/contours/download/${result.celery_task_id}`;
@ -214,7 +189,7 @@ export default class ContoursPanel extends React.Component {
this.setState({[loadingProp]: false});
}
}
});
}, `/api/plugins/contours/task/${taskId}/contours/check/`);
}else if (result.error){
this.setState({[loadingProp]: false, error: result.error});
}else{

Wyświetl plik

@ -151,6 +151,7 @@ def execute_grass_script(script, serialized_context = {}, out_key='output'):
@app.task
def export_raster_index(input, expression):
try:
logger.info("Exporting raster index {} with expression: {}".format(input, expression))
tmpfile = tempfile.mktemp('_raster_index.tif', dir=settings.MEDIA_TMP)
export_raster_index_sync(input, expression, tmpfile)
return {'file': tmpfile}