diff --git a/beat/web/plotters/views.py b/beat/web/plotters/views.py index 9cc7df14f2c8e441046439b13be0240d36b9bcf8..32fc2d41e61b690c60296617fcf6c75e09dfe2ab 100644 --- a/beat/web/plotters/views.py +++ b/beat/web/plotters/views.py @@ -450,6 +450,138 @@ def plot_sample(request): #---------------------------------------------------------- +def plot_sample_with_params(request): + """Plots sample data given as input plotter/plotterparameter/sample data + + This view receives a single data payload with a GET or POST request + containing multiple keys. + We'll cycle through (with :py:func:`itertools.cycle`) them to recover a + dictionary like this:: + + { + 'user/user/toolchain/1/label': { + "analyzer": "my_analysis", + "output" : "my_plot" + }, + 'user/user/toolchain/1/another': { + "analyzer": "my_analysis", + "output" : "my_plot" + }, + 'user/user/toolchain/3/xxx': { + "analyzer": "the_greatest_analysis", + "output" : "scatter" + } + } + + A single ``plotter``, if passed, should reference the plotter to use. It + may be omitted, in which case we use the default plotter for the first + experiment in the list. + + + Returns: + + A response with a single image inside, following the plotter + specifications. + + """ + + if request.GET: use = request.GET + elif request.POST: use = request.POST + else: + return HttpResponseBadRequest('This view must be called with either a GET or POST request') + + keywords = [ + 'experiment', + 'experiment[]', + 'analyzer', + 'analyzer[]', + 'output', + 'output[]', + 'plotter', + #'parameter', + 'report_number', + ] + + extra_parameters = {} + for key in [k for k in use.keys() if k not in keywords]: + extra_parameters[key] = '&'.join(use.getlist(key)) + + # Get the plotter and parameter, resolve if empty + final_plotter = None #use the default + #user_parameter = None #use the default + corefmt = None + + if 'plotter' in use: + username, name, version = use['plotter'].split('/') + try: + final_plotter = Plotter.objects.get(author__username=username, + name=name, version=version) + except Plotter.DoesNotExist as e: + message = "Plotter `%s' is not accessible" % \ + '/'.join((username, name, version)) + logger.warn(message) + return HttpResponseBadRequest(message) + + # Collect the data for the plot, check compatibility + default = None + + # check compatibility, fill up defaults + if default is None: + default = DefaultPlotter.objects.filter(plotter=final_plotter) + + if not default and not final_plotter: + message = 'No plotter specified and no default for plot format %s' % final_plotter.fullname() + return HttpResponseBadRequest(message) + + default = default[0] #get the first and only + + # set defaults, if specific values have not already been set + if not final_plotter: final_plotter = default.plotter + + if corefmt is None: #loads it once + corefmt = final_plotter.core_format() + + ## loads the data, for that particular result + parsed = simplejson.loads(use['sample_data']) + sample_data = corefmt.type().from_dict(parsed, casting='unsafe') + + # checks the plotter is valid + core_plotter = final_plotter.core() + if not core_plotter.valid: + message = 'Plotter %s is invalid' % final_plotter.fullname() + return HttpResponseBadRequest(message) + + + # resolves parameters, in order of priority + final_parameters = {} + if default.parameter: #fills-up defaults for the type + final_parameters.update(simplejson.loads(default.parameter.data)) + #get dynamic plotter params + final_parameters.update(simplejson.loads(use['dynamic_params'])) + if extra_parameters: #fills-up defaults specified on the query + final_parameters.update(extra_parameters) + + extra_parameters.setdefault('content_type', 'image/png') #in case not set + + # for HTML display, you need to set this correctly + do_b64_encode = bool(extra_parameters.get('base64', False)) + + # we filter out parameters we can't handle + for key in final_parameters.keys(): + if key not in core_plotter.parameters: del final_parameters[key] + + runnable= core_plotter.runner() + runnable.setup(final_parameters) + assert runnable.ready + data_to_plot = [('sample_plot', sample_data)] + fig = runnable.process(data_to_plot) + if do_b64_encode: fig = base64.b64encode(fig) + return HttpResponse(fig, content_type=final_parameters['content_type']) + + +#---------------------------------------------------------- + + def view(request, author, name, version=None): """Shows the algorithm. The Web API is used to retrieve the details about the algorithm and check the accessibility.