Ejemplo n.º 1
0
def download_dip_rates(request, dataset_id):
    try:
        dataset = HTSDataset.objects.get(pk=dataset_id, deleted_date=None)
    except HTSDataset.DoesNotExist:
        raise Http404()

    _assert_has_perm(request, dataset, 'download_data')
    if not license_accepted(request, dataset):
        return _plain_response('You must accept the dataset license to '
                               'download this file')

    try:
        full_path = _generate_dip_rates(dataset)
    except NoDataException:
        return _plain_response('No data found for this request')

    output_filename = '{}_dip_rates.tsv'.format(dataset.name)

    return serve_file(request,
                      full_path,
                      rename_to=output_filename,
                      content_type='text/tab-separated-values')
Ejemplo n.º 2
0
def download_fit_params(request, dataset_id, stat_type):
    file_type = 'fit_params_{}_tsv'.format(stat_type)
    file_name = 'fit_params_{}_{}.tsv'.format(stat_type, dataset_id)
    file_type_protocol = 1
    param_names = {
        'dip': ('aa', 'aa_obs', 'emax', 'emax_rel', 'emax_obs', 'emax_obs_rel',
                'einf', 'ec50', 'ic50', 'hill'),
        'viability':
        ('aa', 'aa_obs', 'emax', 'emax_obs', 'einf', 'ec50', 'ic50', 'hill')
    }

    try:
        dataset = HTSDataset.objects.get(pk=dataset_id, deleted_date=None)
    except (HTSDataset.DoesNotExist, ValueError):
        return _plain_response('This dataset does not exist, or you do not '
                               'have permission to access it.')

    _assert_has_perm(request, dataset, 'download_data')
    if not license_accepted(request, dataset):
        return _plain_response('You must accept the dataset license to '
                               'download this file')

    mod_date = timezone.now()
    file = _cached_file(dataset, file_type, file_type_protocol)

    # Additional cache invalidation: curve fits were generated after the
    # cached file
    if file:
        if file.creation_date < CurveFitSet.objects.get(
                dataset_id=dataset_id, stat_type=stat_type).calculation_end:
            file = None

    if file:
        full_path = file.file.name
    else:
        try:
            # Fetch the DIP rates from the DB
            base_params = df_curve_fits(dataset.id,
                                        stat_type,
                                        drug_ids=None,
                                        cell_line_ids=None)
        except NoDataException:
            return _plain_response(
                'The requested parameter set does not exist for the '
                'specified dataset')

        # Fit Hill curves and compute parameters
        fp = fit_params_from_base(base_params,
                                  custom_ic_concentrations={50},
                                  custom_ec_concentrations={50},
                                  include_auc=False,
                                  include_aa=True,
                                  include_hill=True,
                                  include_emax=True,
                                  include_einf=True,
                                  include_response_values=False)
        fp.reset_index('dataset_id', drop=True, inplace=True)
        # Remove -ve AA values
        fp.loc[fp['aa'] < 0.0, 'aa'] = np.nan

        # Filter for the default list of parameters only
        fp = fp.filter(items=param_names[stat_type])

        full_path = os.path.join(settings.DOWNLOADS_ROOT, file_name)

        fp.to_csv(full_path, sep='\t')

        df, created = HTSDatasetFile.objects.get_or_create(
            dataset=dataset,
            file_type=file_type,
            defaults={
                'file_type_protocol': file_type_protocol,
                'file': full_path
            })
        if not created:
            df.file_type_protocol = file_type_protocol
            df.file = full_path
            df.creation_date = mod_date
            df.save()

    output_filename = '{}_{}_params.tsv'.format(dataset.name, stat_type)

    return serve_file(request,
                      full_path,
                      rename_to=output_filename,
                      content_type='text/tab-separated-values')
Ejemplo n.º 3
0
def ajax_get_plot(request, file_type='json'):
    if file_type == 'csv':
        permission_required = 'download_data'
    else:
        permission_required = 'view_plots'

    try:
        plot_type = request.GET['plotType']
        template = request.GET.get('theme', default_plotly_template)
        if template not in ALLOWED_TEMPLATES:
            return HttpResponse('Please select an allowed template',
                                status=400)

        dataset_id = int(request.GET['datasetId'])
        dataset2_id = request.GET.get('dataset2Id', None)
        if dataset2_id == "":
            dataset2_id = None
        if dataset2_id is not None:
            dataset2_id = int(dataset2_id)
        cell_line_id = request.GET.getlist('c')
        drug_id = request.GET.getlist('d')

        cell_line_id = [int(cl) for cl in cell_line_id]
        drug_ids = []
        for dr in drug_id:
            try:
                drug_ids.append(int(dr))
            except ValueError:
                drug_ids.append([int(d) for d in dr.split(",")])
        drug_id = drug_ids

        assay = request.GET.get('assayId')
        yaxis = request.GET.get('logTransform', 'None')

    except (KeyError, ValueError):
        raise Http404()

    try:
        dataset = HTSDataset.objects.get(pk=dataset_id)
    except HTSDataset.DoesNotExist:
        raise Http404()

    _assert_has_perm(request, dataset, permission_required)
    if not license_accepted(request, dataset):
        return HttpResponse(LICENSE_UNSIGNED.format(dataset.name), status=400)

    if plot_type == 'tc':
        if len(drug_id) != 1 or len(cell_line_id) != 1:
            return HttpResponse(
                'Please select exactly one cell line and '
                'drug for time course plot',
                status=400)

        try:
            df_data = df_doses_assays_controls(dataset=dataset,
                                               drug_id=drug_id,
                                               cell_line_id=cell_line_id,
                                               assay=assay)
        except NoDataException:
            return HttpResponse(
                'No data found for this request. This '
                'drug/cell line/assay combination may not '
                'exist.',
                status=400)
        if assay is None:
            assay = df_data.assays.index.get_level_values('assay')[0]

        overlay_dip_fit = request.GET.get('overlayDipFit', 'false') == 'true'

        if overlay_dip_fit and assay != df_data.dip_assay_name:
            return HttpResponse(
                'Can only overlay DIP rate on cell '
                'proliferation assays',
                status=400)

        plot_fig = plot_time_course(df_data,
                                    log_yaxis=yaxis == 'log2',
                                    assay_name=assay,
                                    show_dip_fit=overlay_dip_fit,
                                    subtitle=dataset.name,
                                    template=template)
    elif plot_type in ('drc', 'drpar'):
        if all(isinstance(d, int) for d in drug_id):
            plot_fig = _dose_response_plot(request, dataset, dataset2_id,
                                           permission_required, drug_id,
                                           cell_line_id, plot_type, template)
        else:
            if dataset2_id is not None:
                return HttpResponse(
                    'Please select a single dataset at a time to view drug '
                    'combination heat plots',
                    status=400)

            plot_fig = _drug_combination_heatmap(request, dataset, drug_id,
                                                 cell_line_id, template)

        if isinstance(plot_fig, HttpResponse):
            return plot_fig
    elif plot_type == 'qc':
        qc_view = request.GET.get('qcView', None)
        if qc_view == 'ctrldipbox':
            ctrl_dip_data = df_ctrl_dip_rates(dataset_id)
            if ctrl_dip_data is None:
                return HttpResponse(
                    'No control wells with DIP rates '
                    'available were detected in this '
                    'dataset.',
                    status=400)
            plot_fig = plot_ctrl_dip_by_plate(ctrl_dip_data, template=template)
        elif qc_view == 'ctrlcellbox':
            # Try to fetch from cache
            cache_key = f'dataset_{dataset_id}_plot_ctrlcellbox'
            cur_plotver = 1
            plot_cached = cache.get(cache_key)
            if plot_cached:
                plot_fig = plot_cached['plot_fig']
            if plot_cached is None or plot_cached['dataset_last_modified'] < dataset.modified_date or \
                    plot_cached['plot_version'] < cur_plotver:
                # Create plot
                groupings = dataset_groupings(dataset)
                if not groupings['singleTimepoint']:
                    return HttpResponse(
                        'This plot type is only available for '
                        'single time-point datasets',
                        status=400)
                try:
                    df_data = df_control_wells(dataset_id=dataset, assay=assay)
                except NoDataException:
                    return HttpResponse('No data found for this request.',
                                        status=400)
                if (df_data['value'] == 100.0).all():
                    return HttpResponse(
                        'The raw data for this dataset is given as relative viability, so no control '
                        'wells are available',
                        status=400)

                plot_fig = plot_ctrl_cell_counts_by_plate(
                    df_data, subtitle=dataset.name, template=template)

                # Push to cache
                cache.set(
                    cache_key, {
                        'dataset_last_modified': dataset.modified_date,
                        'plot_version': cur_plotver,
                        'plot_fig': plot_fig
                    })

        elif qc_view == 'dipplatemap':
            plate_id = request.GET.get('plateId', None)
            try:
                plate_id = int(plate_id)
            except ValueError:
                return HttpResponse('Integer plateId required', status=400)
            pl_data = ajax_load_plate(request,
                                      plate_id,
                                      return_as_platedata=True,
                                      use_names=True)
            plot_fig = plot_plate_map(pl_data,
                                      color_by='dip_rates',
                                      template=template)
        else:
            return HttpResponse('Unimplemented QC view: {}'.format(qc_view),
                                status=400)
    else:
        return HttpResponse('Unimplemented plot type: %s' % plot_type,
                            status=400)

    as_attachment = request.GET.get('download', '0') == '1'

    if file_type == 'json':
        j = json.dumps(plot_fig, cls=PlotlyJSONEncoder)
        response = HttpResponse(j, content_type='application/json')
    elif file_type == 'csv':
        response = HttpResponse(plotly_to_dataframe(plot_fig).to_csv(),
                                content_type='text/csv')
    elif file_type == 'html':
        template = 'plotly_plot{}.html'.format(
            '_standalone' if as_attachment else '')
        context = {
            'data': json.dumps(plot_fig, cls=PlotlyJSONEncoder),
            'page_title': strip_tags(plot_fig['layout']['title']['text'])
        }
        if as_attachment:
            context['plotlyjs'] = get_plotlyjs()
        response = render(request, template, context)
    else:
        return HttpResponse('Unknown file type: %s' % file_type, status=400)

    if as_attachment:
        try:
            title = plot_fig['layout']['title']['text']
        except KeyError:
            title = 'Plot'
        response['Content-Disposition'] = \
            'attachment; filename="{}.{}"'.format(strip_tags(title), file_type)

    return response
Ejemplo n.º 4
0
def ajax_load_plate(request,
                    plate_id,
                    extra_return_args=None,
                    return_as_platedata=False,
                    use_names=False):
    if not request.user.is_authenticated and settings.LOGIN_REQUIRED:
        return JsonResponse({}, status=401)

    try:
        p = Plate.objects.filter(id=plate_id).select_related('dataset').get()
    except Plate.DoesNotExist:
        raise Http404()

    _assert_has_perm(request, p.dataset, 'view_plate_layout')
    if not license_accepted(request, p.dataset):
        return HttpResponse(LICENSE_UNSIGNED.format(p.dataset.name),
                            status=400)

    field_ext = '__name' if use_names else '_id'

    # Blank well data
    wells = []
    for cl in range(p.num_wells):
        wells.append({
            'cellLine': None,
            'drugs': AutoExtendList(),
            'doses': AutoExtendList(),
            'dipRate': None
        })

    # Populate cell lines
    cl_query = Well.objects.filter(plate_id=plate_id).values(
        'well_num', 'cell_line' + field_ext)
    for w in cl_query:
        wells[w['well_num']]['cellLine'] = w['cell_line' + field_ext]

    # Populate drugs
    drugs = WellDrug.objects.filter(well__plate_id=plate_id).values(
        'well__well_num', 'drug' + field_ext, 'order', 'dose')
    for dr in drugs:  # prefetched above
        wells[dr['well__well_num']]['drugs'][dr['order']] = dr['drug' +
                                                               field_ext]
        wells[dr['well__well_num']]['doses'][dr['order']] = dr['dose']

    # Populate DIP rates
    for ws in WellStatistic.objects.filter(well__plate_id=plate_id,
                                           stat_name='dip_rate').values(
                                               'well__well_num', 'value'):
        # Need to remove NaNs for proper JSON support
        wells[ws['well__well_num']]['dipRate'] = ws['value'] if \
            ws['value'] is not None and not math.isnan(ws['value']) else None

    plate = {
        'datasetName': p.dataset.name,
        'plateId': p.id,
        'plateName': p.name,
        'numCols': p.width,
        'numRows': p.height,
        'wells': wells
    }

    if return_as_platedata:
        return PlateData.from_dict(plate)

    return_dict = {'success': True, 'plateMap': plate}
    if extra_return_args is not None:
        return_dict.update(extra_return_args)

    return JsonResponse(return_dict)