예제 #1
0
def makeSDF(user, tagNames):
    compoundList = None
    print(" in makeSDF, given tag names: " + str(tagNames))
    compoundList = Compound.byTagNames(tagNames, user)

    sdf = u''
    for compound in compoundList:
        sdf = sdf + compound.sdffile_set.all()[0].sdffile.rstrip() \
            + '\n'
    return sdf
예제 #2
0
def checkCompoundsAjax(user, source_id, ids):
    """Pre-checks a list of IDs by sorting them into lists of acceptable and
    problematic IDs. Problematic compounds include those that already exist in
    the workbench, and those that do not have structure information available
    in the ChEMBL database."""

    if len(ids) == 0:
        raise Exception('Empty list of "ids".')

    results = list()

    results_accept = dict()
    results_accept['select'] = True
    results_accept['enable'] = True
    results_accept[
        'desc'] = "The following compounds can be added to your workbench."
    results_accept['ids'] = list()

    results_inWB = dict()
    results_inWB['select'] = False
    results_inWB['enable'] = True
    results_inWB[
        'desc'] = "The following compounds are already in your workbench. You may still import them by checking the box next to the compound. (Only the ChEMBL ID was checked for duplicates.)"
    results_inWB['ids'] = list()

    results_nostruct = dict()
    results_nostruct['select'] = False
    results_nostruct['enable'] = False
    results_nostruct[
        'desc'] = "The following compounds can't be imported to the workbench because compound structure information is missing from the current ChEMBL database. If you have this information, you may import these compounds manually (i.e. via SDF upload)."
    results_nostruct['ids'] = list()

    if source_id == 'chembl':
        ids_with_struct = get_chembl_ids_with_struct(ids)

        results_nostruct['ids'] = list(set(ids) - set(ids_with_struct))

        inWB = Compound.inWorkbench(user, ids_with_struct)
        for r in ids_with_struct:
            if r in inWB:
                results_inWB['ids'].append(r)
            else:
                results_accept['ids'].append(r)

        if len(results_accept['ids']) != 0:
            results.append(results_accept)
        if len(results_inWB['ids']) != 0:
            results.append(results_inWB)
        if len(results_nostruct['ids']) != 0:
            results.append(results_nostruct)

        return {'success': True, 'results': results}
    else:
        raise Exception('Unknown source_id: {}'.format(source_id))
예제 #3
0
def showCompoundGrid(request):

    # perform query for existing myCompounds

    matches = None
    givenTags = []
    allTags = Tag.allUserTagNames(request.user)

    if 'tags' in request.POST:
        givenTags = request.POST.getlist("tags")
    else:
        givenTags = ["all"]
    matches = Compound.byTagNames(givenTags, request.user)

    return render(request, 'compoundGrid.html',
                  dict(matches=matches, tags=allTags, currentTags=givenTags))
예제 #4
0
def search(request):
    if request.method != 'POST':
        if 'smiles' in request.GET:
            smiles = urlunquote(request.GET['smiles'])
        else:
            smiles = ''
        context = {'smiles': smiles}
        return render(request, 'search.html', context)
    elif 'smiles' in request.POST:
        try:
            mol = smilesToMol(request.POST['smiles'])
        except:
            messages.error(request, 'Error: Invalid SMILES string!')
            return render(request, 'search.html')
    elif 'sdf' in request.POST:
        try:
            mol = chem.MolFromMolBlock(request.POST['sdf'],
                                       strictParsing=False)
            chem.SanitizeMol(mol)
            # assert mol != None
            if not mol:
                raise ValueError
        except ValueError:
            messages.error(request, 'Error: Invalid structure!')
            return render(request, 'search.html')

    querySmiles = chem.MolToSmiles(mol, isomericSmiles=True)

    assert 'cutoff' in request.POST
    minSim = float(request.POST['cutoff'])
    assert 0.0 <= minSim <= 1.0

    assert 'maxCompounds' in request.POST
    maxHits = int(request.POST['maxCompounds'])
    assert 0 < maxHits <= 1000

    assert 'searchDatabase' in request.POST
    assert request.POST['searchDatabase'] in {
        'reviewed',
        'all',
    }
    if request.POST['searchDatabase'] == 'reviewed':
        reviewedOnly = True
    else:
        reviewedOnly = False

    compoundHits = Compound.atomPairSearch(querySmiles,
                                           minSim=minSim,
                                           maxHits=maxHits,
                                           reviewedOnly=reviewedOnly)

    moduleHits = []
    for similarity, compound in compoundHits:
        if reviewedOnly:
            modules = list(
                Module.objects.filter(product=compound).filter(
                    subunit__cluster__reviewed=True))
        else:
            modules = list(Module.objects.filter(product=compound))
        if len(modules) == 0:
            continue
        hitDict = {
            'similarity': similarity,
            'smiles': compound.smiles,
            'modules': modules
        }

        moduleHits.append(hitDict)

    if len(moduleHits) == 0:
        messages.error(request, 'No hits - please refine query!')
        return render(request, 'search.html')

    context = {
        'querySmiles': urlquote(querySmiles),
        'moduleHits': moduleHits,
        'minSim': minSim,
        'maxHits': maxHits,
        'searchDatabase': reviewedOnly,
    }

    return render(request, 'result.html', context)
예제 #5
0
def search(request):
    if request.is_ajax():
        if 'application_id' in request.GET:
            form = getAppForm(request.GET['application_id'], request.user)()
            return HttpResponse(str(form))
        else:
            return HttpResponse("", status_code=404)
    elif request.method != 'POST':
        smi = ''
        if 'smi' in request.GET:
            smi = str(request.GET['smi'])
            smi = urlunquote(smi)
        allTags = Tag.allUserTagNames(request.user)

        fields = {}
        category = ApplicationCategories.objects.get(name="Search")
        apps = Application.objects.filter(category=category).exclude(
            name__exact="pubchemID2SDF")
        fields['application'] = ModelChoiceField(queryset=apps, empty_label='')
        form = type('%sForm' % 'choose application', (Form, ), fields)

        return render(request, 'search.html',
                      dict(mode='form', smi=smi, appsForm=form, tags=allTags))
    else:
        sdf = None
        smiles = None
        compid = u'query'
        form = None
        application = None
        application_id = None

        if 'application' in request.POST:
            application_id = request.POST['application']
            application = Application.objects.get(id=application_id)

        if 'tags' in request.POST:
            givenTags = request.POST.getlist("tags")
            compoundList = Compound.byTagNames(givenTags, request.user)
            if len(compoundList) == 0:
                messages.error(request,
                               "Error: No compounds found with selected tags")
            else:
                sdf = u''
                for compound in compoundList:
                    sdf = sdf + compound.sdffile_set.all()[0].sdffile.rstrip(
                    ) + '\n'
                smiles = sdf_to_smiles(sdf)
        elif 'smiles' in request.POST:
            input_mode = 'smiles-input'
            sdf = u''
            try:
                smiles = request.POST['smiles']
                sdf = smiles_to_sdf(smiles)
            except:
                messages.error(request, 'Error: Invalid SMILES string!')
                sdf = None
        elif 'sdf' in request.FILES:
            input_mode = 'sdf-upload'
            try:
                sdf = request.FILES['sdf']
                sdf = first_mol(sdf.read())
                smiles = sdf_to_smiles(sdf)
            except:
                print(traceback.format_exc())
                messages.error(request, 'Invalid SDF!')
                sdf = None
        elif 'sdf' in request.POST:
            if 'draw' in request.POST:
                input_mode = 'draw'
                sdf = request.POST['sdf'] + '$$$$'
                try:
                    smiles = sdf_to_smiles(sdf)
                    smiles = re.match(r"^(\S+)", smiles).group(1)
                    smiles = smiles + ' ' + compid
                    sdf = smiles_to_sdf(smiles)
                except:
                    print(traceback.format_exc())
                    messages.error(request, 'Invalid drawing!')
                    sdf = None
            else:
                try:
                    input_mode = 'sdf-input'
                    sdf = first_mol(request.POST['sdf'])
                    smiles = sdf_to_smiles(sdf)
                except:
                    print(traceback.format_exc())
                    messages.error(request, 'Invalid input SDF!')
                    sdf = None

        if application_id != None:
            AppFormSet = getAppForm(request.POST['application'], request.user)
            form = AppFormSet(request.POST)

        if form != None and form.is_valid():
            commandOptions, optionsList = parseToolForm(form)
        else:
            sdf = None
            messages.error(request, "Invalid form options!")
        if not sdf:
            print("no sdf found")
            return redirect(structure_search.views.search)
        smiles = re.search(r'(\S+)', smiles).group(1)
        smiles = urlquote(smiles)

        #print("command options: "+str(commandOptions))

        if application.name == "PubChem Fingerprint Search":
            newJob = createJob(request.user, application.name, optionsList,
                               commandOptions, sdf, smiles)
        elif application.name == "ChEMBL Fingerprint Search":
            newJob = createJob(request.user, application.name, optionsList,
                               commandOptions, sdf, smiles)
        elif application.name == "ChEMBL EI Search":
            newJob = createJob(request.user, application.name, optionsList,
                               commandOptions, sdf, smiles)

        time.sleep(1)
        return redirect(tools.views.view_job, job_id=newJob.id, resource='')
예제 #6
0
def newTS(request):
    # Default local variables
    query_submit = False
    message = None
    annotation_info = None
    annotation_matches = None
    drugind_json = None
    activity_info = None
    activity_matches = None
    allTags = Tag.allUserTagNames(request.user)
    compoundDbs = readSources("unichem")
    proteinDbs = readSources("uniprot")
    defaultCompoundDb = "1"
    defaultProteinDb = "ACC+ID"
    groupingCol = 0
    similarityJobs = [(job.id, str(job)) for job in Job.objects.filter(
        user=request.user, application__category_id=5)]

    # Default GET request variables
    id_type = 'compound'
    ids = list()
    include_activity = False
    source_id = 1
    similarity_job_id = -1

    # Retrieve GET request variables
    if 'id_type' in request.GET:
        id_type = request.GET['id_type']
    if 'ids' in request.GET:
        if id_type == 'homolog-target':
            ids = request.GET.getlist('ids')
        else:
            ids = list(request.GET['ids'].split())
    if 'include_activity' in request.GET:
        include_activity = True
    if 'tags' in request.GET:
        for c in [
                compound.cid for compound in Compound.byTagNames(
                    request.GET.getlist("tags"), request.user)
        ]:
            ids.append(c)
    if 'source_id' in request.GET:
        source_id = request.GET['source_id']
    if 'similarity_job_id' in request.GET:
        similarity_job_id = int(request.GET['similarity_job_id'])

    # Generate content
    try:
        idMapping = {}
        if id_type == 'compound' and source_id != '1':
            idMapping = mapToChembl(ids, source_id)
            ids = list(idMapping.keys())
        elif id_type == 'target' and source_id != 'ACC':
            idMapping = mapToUniprot(ids, source_id)
            ids = list(idMapping.keys())
        elif id_type == 'homolog-target':
            #full_ids = ids # Full context for homolog handling
            #ids = [ i.split(',')[2] for i in full_ids ] # Bare Accession IDs for old target-search

            # Context dictionary for homolog handling
            # ex:
            # homolog_context = {
            #     'P29274': {'paralog': 'P30542'},
            #     'P29275': {'paralog': 'P30542'},
            #     'P0DMS8': {'paralog': 'P30542'},
            #     }
            homolog_context = dict()
            for i in ids:
                [relation, src_id, homolog_id] = i.split(',')
                if homolog_id not in homolog_context.keys():
                    homolog_context[homolog_id] = dict()
                if src_id == homolog_id:
                    continue  # Don't bother with "X is a homolog of X"
                if relation not in homolog_context[homolog_id].keys():
                    homolog_context[homolog_id][relation] = set()
                homolog_context[homolog_id][relation].add(src_id)

            ids = list(homolog_context.keys()
                       )  # Bare Accession IDs for old target-search

            # Prepare homolog relation descriptions
            homolog_desc = dict()
            for homolog_id, relations in homolog_context.items():
                desc_parts = list()
                for relation, src_ids in sorted(relations.items()):
                    desc_parts.append("{} of {}".format(
                        relation, ', '.join(sorted(list(src_ids)))))
                homolog_desc[homolog_id] = '; '.join(desc_parts)

        if len(ids) != 0:
            query_submit = True
            queryIdCol = {
                "id": "query_id",
                "sql": None,
                "table": "Query ID",
                "name": "Query ID",
                "desc": "Original compound ID prior to ChEMBL conversion",
                "visible": True,
            }
            headerTextCol = {
                "id": "header_text",
                "sql": None,
                "table": "Header Text",
                "name": "Header Text",
                "desc":
                "Description text to show in row-group headers (i.e. source query IDs, translations, etc.)",
                "visible": False,
            }
            originalQueryCol = {
                "id": "original_query_id",
                "sql": None,
                "table": "Original Query ID",
                "name": "Original Query ID",
                "desc":
                "The compound that the current query compound was originally derived from, based on similarity",
                "visible": True,
            }

            myAnnotationSearch = AnnotationWithDrugIndSearch(id_type, ids)
            annotation_info = myAnnotationSearch.table_info
            annotation_matches = myAnnotationSearch.get_grouped_results()

            drugind_json = drugIndicationData(myAnnotationSearch.drugind_objs)

            # Exclude ActivitySearch from search-by-target by default
            if id_type in ['target', 'homolog-target'
                           ] and not include_activity:
                activity_info = None
                activity_matches = None
            else:
                myActivitySearch = ActivitySearch(id_type, ids)
                activity_info = myActivitySearch.table_info
                activity_matches = myActivitySearch.get_grouped_results()

            if len(idMapping) != 0:
                groupingCol += 1
                addMappedQueryColumn(idMapping, queryIdCol, annotation_info,
                                     annotation_matches, activity_info,
                                     activity_matches)

            if similarity_job_id != -1:
                similarityMapping = readSimilarityMappingData(
                    request.user, similarity_job_id)
                if len(
                        idMapping
                ) != 0:  # need to compose our mapping with previous mapping
                    similarityMapping = composeMaps(idMapping,
                                                    similarityMapping)
                #print("similarity mapping: \n"+str(similarityMapping))
                if len(similarityMapping) != 0:
                    groupingCol += 1
                    addMappedQueryColumn(similarityMapping, originalQueryCol,
                                         annotation_info, annotation_matches,
                                         activity_info, activity_matches)

            #if similarity_job_id != -1, then read job_<similarity_job_id>
            # map chembl id (2nd column) back to the original compound id (first column)
            # insert new column to show original compound id.

        if ts_paralog_cache():
            homolog_type_value = 'paralog-cache'
        else:
            homolog_type_value = 'paralog'

    except Exception as e:
        print("exception in newTS:", sys.exc_info())
        traceback.print_tb(sys.exc_info()[2])
        message = str(e)

    context = {
        'query_submit': query_submit,
        'message': message,
        'id_type': id_type,
        'annotation_info': annotation_info,
        'annotation_matches': annotation_matches,
        'drugind_json': json.dumps(drugind_json),
        'activity_info': activity_info,
        'activity_matches': activity_matches,
        'tags': allTags,
        'compoundDbs': compoundDbs,
        'defaultCompoundDb': defaultCompoundDb,
        'proteinDbs': proteinDbs,
        'defaultProteinDb': defaultProteinDb,
        'groupingCol': groupingCol,
        'similarityJobs': similarityJobs,
        'homolog_type_value': homolog_type_value,
    }

    return render(request, 'targetsearch/new_ts.html', context)
예제 #7
0
def countCompoundsWithTags(request, tags):
    return HttpResponse(
        Compound.byTagNames(tags.split(","), request.user).count())