def calculate(request, save_output=dummy_save): start = datetime.datetime.now() if request.method == 'GET': # FIXME: Add a basic form here to be able to generate the POST request. return HttpResponse('This should be accessed by robots, not humans.' 'In other words using HTTP POST instead of GET.') elif request.method == 'POST': data = request.POST impact_function_name = data['impact_function'] hazard_server = data['hazard_server'] hazard_layer = data['hazard'] exposure_server = data['exposure_server'] exposure_layer = data['exposure'] bbox = data['bbox'] keywords = data['keywords'] theuser = get_guaranteed_valid_user(request.user) plugin_list = get_plugins(impact_function_name) _, impact_function = plugin_list[0].items()[0] impact_function_source = inspect.getsource(impact_function) # Create entry in database calculation = Calculation(user=theuser, run_date=start, hazard_server=hazard_server, hazard_layer=hazard_layer, exposure_server='exposure_server', exposure_layer='exposure_layer', impact_function=impact_function_name, impact_function_source=impact_function_source, bbox=bbox, success=False) calculation.save() logger.info('Performing requested calculation') # Download selected layer objects logger.info('- Downloading hazard layer %s from %s' % (hazard_layer, hazard_server)) H = download(hazard_server, hazard_layer, bbox) logger.info('- Downloading exposure layer %s from %s' % (exposure_layer, exposure_server)) E = download(exposure_server, exposure_layer, bbox) # Calculate result using specified impact function logger.info('- Calculating impact using %s' % impact_function) impact_filename = calculate_impact(layers=[H, E], impact_function=impact_function) # Upload result to internal GeoServer logger.info('- Uploading impact layer %s' % impact_filename) result = save_output(impact_filename, title='output_%s' % start.isoformat(), user=theuser) logger.info('- Result available at %s.' % result.get_absolute_url()) calculation.layer = result.get_absolute_url() calculation.success = True calculation.save() output = calculation.__dict__ # json.dumps does not like datetime objects, # let's make it a json string ourselves output['run_date'] = 'new Date("%s")' % calculation.run_date # FIXME:This should not be needed in an ideal world ows_server_url = settings.GEOSERVER_BASE_URL + 'ows', output['ows_server_url'] = ows_server_url # json.dumps does not like django users output['user'] = calculation.user.username # Delete _state and _user_cache item from the dict, # they were created automatically by Django del output['_user_cache'] del output['_state'] jsondata = json.dumps(output) return HttpResponse(jsondata, mimetype='application/json')
def calculate(request, save_output=save_to_geonode): start = datetime.datetime.now() if request.method == 'GET': # FIXME: Add a basic form here to be able to generate the POST request. return HttpResponse('This should be accessed by robots, not humans.' 'In other words using HTTP POST instead of GET.') elif request.method == 'POST': data = request.POST impact_function_name = data['impact_function'] hazard_server = data['hazard_server'] hazard_layer = data['hazard'] exposure_server = data['exposure_server'] exposure_layer = data['exposure'] bbox = data['bbox'] keywords = data['keywords'] if request.user.is_anonymous(): theuser = get_valid_user() else: theuser = request.user # Create entry in database calculation = Calculation(user=theuser, run_date=start, hazard_server=hazard_server, hazard_layer=hazard_layer, exposure_server=exposure_server, exposure_layer=exposure_layer, impact_function=impact_function_name, success=False) try: # Input checks msg = 'This cannot happen :-)' assert isinstance(bbox, basestring), msg check_bbox_string(bbox) # Find the intersection of bounding boxes for viewport, # hazard and exposure. vpt_bbox = bboxstring2list(bbox) haz_bbox = get_metadata(hazard_server, hazard_layer)['bounding_box'] exp_bbox = get_metadata(exposure_server, exposure_layer)['bounding_box'] # Impose minimum bounding box size (as per issue #101). # FIXME (Ole): This will need to be revisited in conjunction with # raster resolutions at some point. min_res = 0.00833334 eps = 1.0e-1 vpt_bbox = minimal_bounding_box(vpt_bbox, min_res, eps=eps) haz_bbox = minimal_bounding_box(haz_bbox, min_res, eps=eps) exp_bbox = minimal_bounding_box(exp_bbox, min_res, eps=eps) # New bounding box for data common to hazard, exposure and viewport # Download only data within this intersection intersection = bbox_intersection(vpt_bbox, haz_bbox, exp_bbox) if intersection is None: # Bounding boxes did not overlap msg = ('Bounding boxes of hazard data, exposure data and ' 'viewport did not overlap, so no computation was ' 'done. Please try again.') logger.info(msg) raise Exception(msg) bbox = bboxlist2string(intersection) plugin_list = get_plugins(impact_function_name) _, impact_function = plugin_list[0].items()[0] impact_function_source = inspect.getsource(impact_function) calculation.impact_function_source = impact_function_source calculation.bbox = bbox calculation.save() msg = 'Performing requested calculation' logger.info(msg) # Download selected layer objects msg = ('- Downloading hazard layer %s from %s' % (hazard_layer, hazard_server)) logger.info(msg) H = download(hazard_server, hazard_layer, bbox) msg = ('- Downloading exposure layer %s from %s' % (exposure_layer, exposure_server)) logger.info(msg) E = download(exposure_server, exposure_layer, bbox) # Calculate result using specified impact function msg = ('- Calculating impact using %s' % impact_function) logger.info(msg) impact_filename = calculate_impact(layers=[H, E], impact_fcn=impact_function) # Upload result to internal GeoServer msg = ('- Uploading impact layer %s' % impact_filename) logger.info(msg) result = save_output(impact_filename, title='output_%s' % start.isoformat(), user=theuser) except Exception, e: #FIXME: Reimplement error saving for calculation logger.error(e) errors = e.__str__() trace = exception_format(e) calculation.errors = errors calculation.stacktrace = trace calculation.save() jsondata = json.dumps({'errors': errors, 'stacktrace': trace}) return HttpResponse(jsondata, mimetype='application/json')
def calculate(request, save_output=save_to_geonode): start = datetime.datetime.now() if request.method == 'GET': # FIXME: Add a basic form here to be able to generate the POST request. return HttpResponse('This should be accessed by robots, not humans.' 'In other words using HTTP POST instead of GET.') elif request.method == 'POST': data = request.POST impact_function_name = data['impact_function'] hazard_server = data['hazard_server'] hazard_layer = data['hazard'] exposure_server = data['exposure_server'] exposure_layer = data['exposure'] requested_bbox = data['bbox'] keywords = data['keywords'] if request.user.is_anonymous(): theuser = get_valid_user() else: theuser = request.user # Create entry in database calculation = Calculation(user=theuser, run_date=start, hazard_server=hazard_server, hazard_layer=hazard_layer, exposure_server=exposure_server, exposure_layer=exposure_layer, impact_function=impact_function_name, success=False) # Wrap main computation loop in try except to catch and present # messages and stack traces in the application try: # Get metadata haz_metadata = get_metadata(hazard_server, hazard_layer) exp_metadata = get_metadata(exposure_server, exposure_layer) # Determine common resolution in case of raster layers raster_resolution = get_common_resolution(haz_metadata, exp_metadata) # Get reconciled bounding boxes haz_bbox, exp_bbox, imp_bbox = get_bounding_boxes(haz_metadata, exp_metadata, requested_bbox) # Record layers to download download_layers = [(hazard_server, hazard_layer, haz_bbox), (exposure_server, exposure_layer, exp_bbox)] # Add linked layers if any FIXME: STILL TODO! # Get selected impact function impact_function = get_plugin(impact_function_name) impact_function_source = inspect.getsource(impact_function) # Record information calculation object and save it calculation.impact_function_source = impact_function_source calculation.bbox = bboxlist2string(imp_bbox) calculation.save() # Start computation msg = 'Performing requested calculation' logger.info(msg) # Download selected layer objects layers = [] for server, layer_name, bbox in download_layers: msg = ('- Downloading layer %s from %s' % (layer_name, server)) logger.info(msg) L = download(server, layer_name, bbox, raster_resolution) layers.append(L) # Calculate result using specified impact function msg = ('- Calculating impact using %s' % impact_function) logger.info(msg) impact_filename = calculate_impact(layers=layers, impact_fcn=impact_function) # Upload result to internal GeoServer msg = ('- Uploading impact layer %s' % impact_filename) logger.info(msg) result = save_output(impact_filename, title='output_%s' % start.isoformat(), user=theuser) except Exception, e: # FIXME: Reimplement error saving for calculation. # FIXME (Ole): Why should we reimplement? # This is dangerous. Try to raise an exception # e.g. in get_metadata_from_layer. Things will silently fail. # See issue #170 logger.error(e) errors = e.__str__() trace = exception_format(e) calculation.errors = errors calculation.stacktrace = trace calculation.save() jsondata = json.dumps({'errors': errors, 'stacktrace': trace}) return HttpResponse(jsondata, mimetype='application/json')