def GetMolPopoverTag(Mol): """Set up a popover window containing any additional information about molecule.""" if not OptionsInfo["Popover"]: return None # Set up data label and values... AvailableDataLabels = Mol.GetPropNames(includePrivate=False, includeComputed=False) DataContentLines = [] MaxDataCharWidth = OptionsInfo["PopoverTextWidth"] MaxDataDisplayCount = OptionsInfo["PopoverDataCount"] DataDisplayCount = 0 SkippedDataDisplay = False for DataLabel in AvailableDataLabels: DataDisplayCount += 1 if DataDisplayCount > MaxDataDisplayCount: SkippedDataDisplay = True break DataValue = "%s" % Mol.GetProp(DataLabel) DataValue = DataValue.strip() if MiscUtil.IsEmpty(DataValue): continue # Change any new lines to ; if re.search("(\r\n|\r|\n)", DataValue): DataValue = re.sub("(\r\n|\r|\n)", "; ", DataValue) DataValue = MiscUtil.TruncateText(DataValue, MaxDataCharWidth, "...") DataValue = MiscUtil.ReplaceHTMLEntitiesInText(DataValue) DataContent = "<b>%s</b>: %s" % (DataLabel, DataValue) DataContentLines.append(DataContent) if not len(DataContentLines): return None if SkippedDataDisplay: DataContent = "<b>... ... ...</b>" DataContentLines.append(DataContent) DataContent = "Showing 1 to %s of %s" % (MaxDataDisplayCount, len(AvailableDataLabels)) DataContentLines.append(DataContent) else: DataContent = "Showing 1 to %s of %s" % (DataDisplayCount, len(AvailableDataLabels)) DataContentLines.append(DataContent) DataContent = MiscUtil.JoinWords(DataContentLines, "<br/>") PopoverTag = """class="MolPopover" data-toggle="popover" data-html="true" data-trigger="click" data-placement="right" title="<span class='small'><b>Additional Information</b></span>" data-content="<span class='small'>%s</span>" """ % DataContent return PopoverTag
def WriteRGroups(Mols, RGroups, UnmatchedMolIndices): """Write out R groups""" Outfile = OptionsInfo["Outfile"] UnmatchedOutfile = OptionsInfo["UnmatchedOutfile"] RemoveUnmatchedMode = OptionsInfo["RemoveUnmatchedMode"] Compute2DCoords = OptionsInfo["OutfileParams"]["Compute2DCoords"] TextOutFileMode = OptionsInfo["TextOutFileMode"] TextOutFileDelim = OptionsInfo["TextOutFileDelim"] Quote = OptionsInfo["TextOutQuote"] SMILESIsomeric = OptionsInfo["OutfileParams"]["SMILESIsomeric"] SMILESKekulize = OptionsInfo["OutfileParams"]["Kekulize"] # Setup writers... Writer = None UnmatchedWriter = None if TextOutFileMode: Writer = open(Outfile, "w") if RemoveUnmatchedMode: UnmatchedWriter = open(UnmatchedOutfile, "w") else: Writer = RDKitUtil.MoleculesWriter(Outfile, **OptionsInfo["OutfileParams"]) if RemoveUnmatchedMode: UnmatchedWriter = RDKitUtil.MoleculesWriter( UnmatchedOutfile, **OptionsInfo["OutfileParams"]) if Writer is None: MiscUtil.PrintError("Failed to setup a writer for output fie %s " % Outfile) if RemoveUnmatchedMode: if UnmatchedWriter is None: MiscUtil.PrintError("Failed to setup a writer for output fie %s " % UnmatchedOutfile) if RemoveUnmatchedMode: MiscUtil.PrintInfo("\nGenerating files: %s %s..." % (Outfile, UnmatchedOutfile)) else: MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile) # Set up data keys and labels for core and R groups... RGroupsDataKeys = [] RGroupsDataLabels = [] CoreDataLabelPresent = False for DataLabel in sorted(RGroups): if re.match("^Core", DataLabel, re.I): CoreDataLabelPresent = True RGroupsDataKeys.append(DataLabel) RGroupsDataLabels.append("SMILES%s" % DataLabel) elif re.match("^R", DataLabel, re.I): RGroupsDataKeys.append(DataLabel) RGroupsDataLabels.append("SMILES%s" % DataLabel) else: MiscUtil.PrintWarning( "Ignoring unknown R group data label, %s, found during R group decomposition..." % DataLabel) if CoreDataLabelPresent: RGroupsCategoriesCount = len(RGroupsDataLabels) - 1 else: RGroupsCategoriesCount = len(RGroupsDataLabels) RGroupsMolUnmatchedCount = len(UnmatchedMolIndices) RGroupsMolMatchedCount = len(Mols) - RGroupsMolUnmatchedCount # Wite out headers for a text file... if TextOutFileMode: LineWords = ["SMILES", "Name"] if RemoveUnmatchedMode: Line = MiscUtil.JoinWords(LineWords, TextOutFileDelim, Quote) UnmatchedWriter.write("%s\n" % Line) LineWords.extend(RGroupsDataLabels) Line = MiscUtil.JoinWords(LineWords, TextOutFileDelim, Quote) Writer.write("%s\n" % Line) MolCount = 0 RGroupsResultIndex = -1 for MolIndex, Mol in enumerate(Mols): MolCount += 1 UnmatchedMol = False if MolIndex in UnmatchedMolIndices: UnmatchedMol = True if UnmatchedMol: RGroupsDataSMILES = [""] * len(RGroupsDataKeys) else: RGroupsResultIndex += 1 RGroupsDataSMILES = [ RGroups[RGroupsDataKey][RGroupsResultIndex] for RGroupsDataKey in RGroupsDataKeys ] if TextOutFileMode: # Write out text file including SMILES file... MolSMILES = Chem.MolToSmiles(Mol, isomericSmiles=SMILESIsomeric, kekuleSmiles=SMILESKekulize) MolName = RDKitUtil.GetMolName(Mol, MolCount) LineWords = [MolSMILES, MolName] if UnmatchedMol and RemoveUnmatchedMode: Line = MiscUtil.JoinWords(LineWords, TextOutFileDelim, Quote) UnmatchedWriter.write("%s\n" % Line) else: LineWords.extend(RGroupsDataSMILES) Line = MiscUtil.JoinWords(LineWords, TextOutFileDelim, Quote) Writer.write("%s\n" % Line) else: # Write out SD file... if Compute2DCoords: AllChem.Compute2DCoords(Mol) if UnmatchedMol and RemoveUnmatchedMode: UnmatchedWriter.write(Mol) else: for (Name, Value) in zip(RGroupsDataLabels, RGroupsDataSMILES): Mol.SetProp(Name, Value) Writer.write(Mol) if Writer is not None: Writer.close() if UnmatchedWriter is not None: UnmatchedWriter.close() MiscUtil.PrintInfo("\nTotal number of molecules: %d" % MolCount) MiscUtil.PrintInfo("Number of R group categories: %d" % RGroupsCategoriesCount) MiscUtil.PrintInfo( "Number of matched molecules containing core scaffold(s): %d" % RGroupsMolMatchedCount) MiscUtil.PrintInfo( "Number of unmatched molecules containing no core scaffold(s): %d" % RGroupsMolUnmatchedCount)
def WriteHTMLPageHeader(Writer, MolCount): """Write out HTML page header.""" ColCount = GetColCount(MolCount) # Exclude counter and structure columns from sorting and searching... if OptionsInfo["CounterCol"]: ColIndicesList = ["0"] ColVisibilityExcludeColIndicesList = ["0"] ColIndexOffset = 1 FreezeLeftColumns = "1" else: ColIndicesList = [] ColVisibilityExcludeColIndicesList = [] ColIndexOffset = 0 MaxDataColVisColCount = 25 for Index in range(0, ColCount): ColIndex = Index + ColIndexOffset ColIndicesList.append("%s" % ColIndex) if OptionsInfo["ColVisibility"]: if Index >= MaxDataColVisColCount: ColVisibilityExcludeColIndicesList.append("%s" %ColIndex) ColIndices = MiscUtil.JoinWords(ColIndicesList, ", ") if len(ColIndicesList) else "" ColVisibilityExcludeColIndices = MiscUtil.JoinWords(ColVisibilityExcludeColIndicesList, ", ") if len(ColVisibilityExcludeColIndicesList) else "" DataColVisibilityExclude = False if OptionsInfo["ColVisibility"]: if ColCount > MaxDataColVisColCount: DataColVisibilityExclude = True MiscUtil.PrintWarning("The number of data columns, %d, is quite large. Only first %d data columns will be available in column visibility pulldown." % (ColCount, MaxDataColVisColCount)) DisplayButtons = False if OptionsInfo["ColVisibility"]: if ColCount > 0: DisplayButtons = True FreezeCols = False if (OptionsInfo["CounterCol"] and OptionsInfo["ScrollX"]): FreezeCols = True Paging = "true" if OptionsInfo["Paging"] else "false" PageLength = "%d" % OptionsInfo["PageLength"] PagingType = "\"%s\"" % OptionsInfo["PagingType"] ScrollX = "true" if OptionsInfo["ScrollX"] else "false" ScrollY = "" if OptionsInfo["ScrollY"]: if re.search("vh$", OptionsInfo["ScrollYSize"]): ScrollY = "\"%s\"" % OptionsInfo["ScrollYSize"] else: ScrollY = "%s" % OptionsInfo["ScrollYSize"] # Start HTML header... Title = "Molecules table" if OptionsInfo["Header"] is None else OptionsInfo["Header"] Writer.write("""\ <!doctype html> <html lang="en"> <head> <title>%s</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap4.min.css"> """ % (Title)) if (FreezeCols): Writer.write("""\ <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/fixedcolumns/3.2.4/css/fixedColumns.bootstrap4.min.css"> """) if (OptionsInfo["KeysNavigation"]): Writer.write("""\ <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/keytable/2.3.2/css/keyTable.bootstrap4.min.css"> """) Writer.write("""\ <script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script> <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script> <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap4.min.js"></script> """) if (OptionsInfo["Popover"]): Writer.write("""\ <script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script> <script type="text/javascript" language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script> """) if DisplayButtons: Writer.write("""\ <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js"></script> <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.bootstrap4.min.js"></script> <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.colVis.min.js"></script> """) if (FreezeCols): Writer.write("""\ <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/fixedcolumns/3.2.4/js/dataTables.fixedColumns.min.js"></script> """) if (OptionsInfo["KeysNavigation"]): Writer.write("""\ <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/keytable/2.3.2/js/dataTables.keyTable.min.js"></script> """) # Intialize table using Bootstrap, DataTables and JQuery frameworks... Writer.write("""\ <script type="text/javascript" class="init"> $(document).ready(function() { """) if (OptionsInfo["Popover"]): Writer.write("""\ $('.MolPopover').popover(); """) Writer.write("""\ var MolsTable = $('#MolsTable').DataTable( { "columnDefs": [ { "orderable": false, "searchable": false, "targets": [%s] }, """ % (ColIndices)) if OptionsInfo["ColVisibility"]: Writer.write("""\ { "className": "noColVisCtrl", "targets": [%s] } """ % (ColVisibilityExcludeColIndices)) Writer.write("""\ ], """) # Set up dom for displaying button and other options... if OptionsInfo["ColVisibility"]: if OptionsInfo["Paging"]: Writer.write("""\ "dom": "<'row'<'col-sm-6'l><'col-sm-6'<'float-right'B>>>" + "<'row'<'col-sm-12'tr>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", """) else: Writer.write("""\ "dom": "<'row'<'col'<'float-right'B>>>" + "<'row'<'col-sm-12'tr>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", """) else: Writer.write("""\ "dom": "<'row'<'col'l>>" + "<'row'<'col-sm-12'tr>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", """) # if OptionsInfo["ColVisibility"]: # Set up buttons... Writer.write("""\ "buttons": [ { "extend": "colvis", "text": "Column visibility", "className": "btn btn-outline-light text-dark", "columns": ":not(.noColVisCtrl)", """) if not DataColVisibilityExclude: Writer.write("""\ "prefixButtons": [ "colvisRestore" ], """) Writer.write("""\ "columnText": function ( dt, colIndex, colLabel ) { return "Column " + (colIndex + 1); }, } ], """) # Write out rest of the variables for DataTables... if FreezeCols: Writer.write("""\ "fixedColumns": { "leftColumns": %s }, """ % (FreezeLeftColumns)) if (OptionsInfo["KeysNavigation"]): Writer.write("""\ "keys": true, """) Writer.write("""\ "pageLength": %s, "lengthMenu": [ [5, 10, 15, 25, 50, 100, 500, 1000, -1], [5, 10, 15, 25, 50, 100, 500, 1000, "All"] ], "paging": %s, "pagingType": %s, "scrollX": %s, "scrollY": %s, "scrollCollapse": true, "order": [], } ); """ % (PageLength, Paging, PagingType, ScrollX, ScrollY)) if OptionsInfo["CounterCol"]: Writer.write("""\ MolsTable.on( 'order.dt search.dt', function () { MolsTable.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, rowIndex) { cell.innerHTML = rowIndex + 1; } ); } ).draw(); """) # End of Javacscript code... Writer.write("""\ } ); </script> """) # Finish up HTML header... Writer.write("""\ </head> <body> <div class="container-fluid"> <br/> """)