from CCP4ReportParser import *

class privateer_report(Report):
  # Specify which gui task and/or pluginscript this applies to
  TASKNAME = 'privateer'
  CSS_VERSION = '0.1.0'

  def __init__(self,xmlnode=None,jobInfo={},**kw):
    Report. __init__(self,xmlnode=xmlnode,jobInfo=jobInfo,cssVersion=self.CSS_VERSION,**kw)
  
    import CCP4Utils,os
    imageFile = os.path.join(CCP4Utils.getCCP4I2Dir(), 'wrappers/privateer/script/pyranose_pseudorotational.svg' )
    background_pyranoses = os.path.join(CCP4Utils.getCCP4I2Dir(), 'wrappers/privateer/script/mercator_pyranoses.png' )
    
    results = self.addResults()
    results.append('The Cremer-Pople analysis (Cremer and Pople, 1975, JACS 97:1354-58) is used to determine sugar ring conformation. Below is a 2D plot of the conformational'+\
            ' parameters (Q, Phi, Theta for pyranoses; Q and Theta for furanoses) along with a depiction of the conformational sphere for pyranoses:')
    
#    chartFold = self.addFold(label='graphical representations', initiallyOpen=True)

    graph = results.addFlotGraph(title="graphical representations", select="//ValidationData", style="height:300px; width:385px; border:0px; float:right;" )
    graph.addData ( title="PhiPyranoses", select="Pyranose/SugarPhi" )
    graph.addData ( title="ThetaPyranoses", select="Pyranose/SugarTheta" )
    graph.addData ( title="PhiFuranoses", select="Furanose/SugarPhi" )
    graph.addData ( title="QFuranoses", select="Furanose/SugarQ" )
    graph.addData ( title="Pyranose", select="Pyranose/SugarRSCC" )
    graph.addData ( title="Furanose", select="Furanose/SugarRSCC" )
    graph.addData ( title="BfacPyranoses", select="Pyranose/SugarBFactor" )
    graph.addData ( title="BfacFuranoses", select="Furanose/SugarBFactor" )
    

########## Pyranose conformation ###########

    p = graph.addPlotObject()
    p.append( 'description', 'This graph is a 2D projection of the Cremer-Pople sphere, with chairs at the poles, boats '+\
              'and skew-boats at the equator, and envelopes and half-chairs elsewhere.') 
    p.append( 'title', 'Conformational landscape for pyranoses' )
    p.append( 'plottype', 'xy' )
    p.append( 'showlegend', 'false' )
    p.append ( 'background' ).text = background_pyranoses
    p.append( 'xintegral', 'true' )
    p.append( 'yintegral', 'true' )
    p.append( 'xlabel', 'Phi' )
    p.append( 'ylabel', 'Theta' )
    p.append( 'xrange', min = '0.0', max = '360.0' )
    p.append( 'yrange', rightaxis='false', max = '0', min = '180.0' )
    l = p.append( 'plotline', xcol = 1, ycol = 2 )
    l.append( 'colour', 'red' )
    l.append( 'linestyle', '.' )
#    l.append( 'symbolsize', '7' )
#    l.append( 'symbol', 'x' )


    pyranoses = self.xmlnode.select("//ValidationData/Pyranose")
    furanoses = self.xmlnode.select("//ValidationData/Furanose")


########## Furanose conformation VS Q ###########

    if furanoses != "" :
        p = graph.addPlotObject()
        p.append( 'title', 'Furanose conformation VS puckering amplitude' )
        p.append( 'description', 'A plot of conformation (Theta) VS puckering amplitude (Q). Q measures how much atoms separate from the mean ring plane.')
        p.append( 'plottype', 'xy' )
        p.append( 'showlegend', 'false' )
        p.append( 'xintegral', 'true' )
        p.append( 'yintegral', 'true' )
        p.append( 'xrange', min = '0.0', max = '360.0' )
        p.append( 'yrange', rightaxis='false', min = '0.0', max = '1.0' )
        l = p.append( 'plotline', xcol = 3, ycol = 4 )
        l.append( 'colour', 'blue' )
        l.append( 'linestyle', '.' )


########## Conformation VS RSCC ###########

    p = graph.addPlotObject()
    p.append( 'title', 'Conformation VS Real Space Correlation Coefficient' )
    p.append( 'plottype', 'xy' )
    p.append( 'description', 'Here you can see how sugars in the different conformations match the electron density.')

    if furanoses != "" :
        p.append( 'showlegend', 'true' )
    else :
        p.append( 'showlegend', 'false' )
   
    p.append( 'xintegral', 'true' )
    p.append( 'yintegral', 'true' )
    p.append( 'xrange', min = '0.0', max = '360.0' )
    p.append( 'yrange', rightaxis='false', min = '0.0', max = '1.0' )
   
    if furanoses != "" :
        p.append( 'yrange', rightaxis='true',  min = '0.0', max = '1.0' )
   
    l = p.append( 'plotline', xcol = 2, ycol = 5 )
    l.append( 'colour','red' )
    l.append( 'linestyle', '.' )
    
    if furanoses != "" :
        l = p.append( 'plotline', xcol = 3, ycol = 6, rightaxis='true')
        l.append('colour','blue')
        l.append( 'linestyle', '.' )


########## B-factor VS RSCC ###########

    p = graph.addPlotObject()
    p.append( 'title', '<B-factor> VS Real Space Correlation Coefficient' )
    p.append( 'plottype', 'xy' )
    
    if furanoses != "" :
        p.append( 'showlegend', 'true' )
    else :
        p.append( 'showlegend', 'false' )
   
    p.append( 'xintegral', 'true' )
    p.append( 'yintegral', 'true' )
    p.append( 'yrange', rightaxis='false', min = '0.0', max = '1.0' )
   
    if furanoses != "" :
        p.append( 'yrange', rightaxis='true' , min = '0.0', max = '1.0' )
    
    l = p.append( 'plotline', xcol = 7, ycol = 5 )
    l.append('colour','red')
    l.append( 'linestyle', '.' )
    
    if furanoses != "" :
        l = p.append( 'plotline', xcol = 8, ycol = 6 )
        l.append( 'colour', 'blue' )
        l.append( 'linestyle', '.' )

    htmlCode = '<img src="' + imageFile + '" alt="Diagram" style="width:250px; height:250px; margin-top:20px;" />'

    results.append(htmlCode)

    results.append('<br/>') 
    clearingDiv = results.addDiv(style="clear:both;")


########## Glycan structures ########
    trees = self.xmlnode.select ( "//ValidationData/Glycan" )
    
    if trees != "" : 
        treesFold = results.addFold ( label="N- and O-glycan structure 2D descriptions", initiallyOpen=False ) 

        index = 0 
        chain = 'empty'

        treesFold.append ( 'Below are graphical plots of the detected glycan trees. Placing your mouse pointer' +\
                          ' over any of the sugars will display a tooltip containing its residue name and number from the PDB file.' )
        directory = jobInfo['fileroot']
        for glycan in self.xmlnode.xpath ( "//ValidationData/Glycan/GlycanSVG" ) :
        
            if chain != self.xmlnode.xpath ( "//ValidationData/Glycan/GlycanChain" )[index].text :
                chain = self.xmlnode.xpath ( "//ValidationData/Glycan/GlycanChain" )[index].text
                treesFold.append ( '<p style="font-size:130%; padding:2px; margin-top:20px; margin-bottom:0px; font-weight:bold; margin-left:15px; clear:both"> Chain ' + chain + '</p>' )
                chaindiv = treesFold.addDiv(style="border-width: 1px; padding-top: 10px; padding-bottom:10px; border-color:black; border-style:solid; border-radius:15px;")
#                treesFold.append ( '<p style="background-color:rgb(145,203,219); padding:2px;' +\
#                        'margin-top:20px; margin-bottom:12px; clear:both"> Chain ' + chain + '</p>' )
            index = index + 1

            svg_filename = os.path.join ( directory, glycan.text )
            
            svg_file = open(svg_filename, 'r')
            svg_string = svg_file.read()
            svg_file.close()
            #chaindiv.append ('<div style="float:right; padding-top: 5px; padding-bottom: 5px; margin-right:30px;>' + svg_string + '</div>' )
            svg_div = chaindiv.addDiv ( style="float:right; padding-right:10px; " )
            svg_div.append ( svg_string )

#        treeshtmlCode = '<img src="' + treesName + '" alt="Diagram" />'#width="415" height="183" />'
#        treesFold.append ( treeshtmlCode )
            chaindiv.append ( '<div style="clear:both" />' )   

        treesFold.append ( '<div style="clear:both; margin-bottom:30px;" />' )   
######### Detailed validation data ######

    tableFold = results.addFold(label='Detailed monosaccharide validation data', initiallyOpen=True)

    if pyranoses != "" :
 
        tableFold.append( 'Validation results for pyranose sugars: <br/>' )
        table1 = tableFold.addTable(select="//ValidationData/Pyranose")

        for title,select in [ [ "Name" ,"SugarName" ],
                              [ "Chain"  , "SugarChain" ],
                              [ "Q<sup>1</sup>" , "SugarQ"],
                              [ "Phi" , "SugarPhi" ],
                              [ "Theta" , "SugarTheta" ],
                              [ "Anomer" , "SugarAnomer" ],
                              [ "D/L<sup>2</sup>", "SugarHand" ],
                              [ "Conformation" ,"SugarConformation" ],
                              [ "RSCC<sup>3</sup>" , "SugarRSCC" ],
                              [ "&lt;Bfactor&gt;", "SugarBFactor" ],
                              [ "Diagnostic" , "SugarDiagnostic" ] ] :

            table1.addData(title=title,select=select)
    
    if furanoses != "" :

        tableFold.append( 'Validation results for furanose sugars: <br/>' )
        table2 = tableFold.addTable(select="//ValidationData/Furanose")
    
        for title,select in [ [ "Name" ,"SugarName" ],
                            [ "Chain"  , "SugarChain" ],
                            [ "Q" , "SugarQ"],
                            [ "Phi" , "SugarPhi" ],
                            [ "Anomer" , "SugarAnomer" ],
                            [ "D/L", "SugarHand" ],
                            [ "Conformation" ,"SugarConformation" ],
                            [ "RSCC" , "SugarRSCC" ],
                            [ "&lt;Bfactor&gt;", "SugarBFactor" ],
                            [ "Diagnostic" , "SugarDiagnostic" ] ] :
        
            table2.addData(title=title,select=select)

    tableFold.append('<sup>1</sup>Q is the total puckering amplitude, measured in Angstroems.<br/>'+\
                '<sup>2</sup>Whenever N is displayed in the D/L column, it means that Privateer has been unable to determine the handedness based solely on the structure.<br/>'+\
        '<sup>3</sup>RSCC, short for Real Space Correlation Coefficient, measures the agreement between model and positive omit density. A RSCC below 0.8 is tipically considered poor.')
    

############ Summary ##############


    summaryFold = self.addFold ( label='Summary and information for Table 1', initiallyOpen=True )
    
    ngeom = nconf = nanom = ndl = nq = 0

    for diagnostics in self.xmlnode.xpath("//ValidationData/Pyranose/SugarDiagnostic") :
        ngeom += diagnostics.text.count ( "geometry" )
        nconf += diagnostics.text.count ( "mistaken" )
        nanom += diagnostics.text.count ( "anomer" )
        ndl   += diagnostics.text.count ( "configuration" )
        nq    += diagnostics.text.count ( "Q=" )

    for diagnostics in self.xmlnode.xpath("//ValidationData/Furanose/SugarDiagnostic") :
        ngeom += diagnostics.text.count ( "geometry" )
        nconf += diagnostics.text.count ( "mistaken" )
        nanom += diagnostics.text.count ( "anomer" )
        ndl   += diagnostics.text.count ( "configuration" )
        nq    += diagnostics.text.count ( "Q=" )

    tableSummary = summaryFold.addTable ( transpose=True )
    #tableSummary.addData ( title = "Check ring geometry", data = [ ngeom ] )
    tableSummary.addData ( title = "Stereochemical problems", data = [ nanom + ndl ] )
    tableSummary.addData ( title = "Unphysical puckering amplitude", data = [ nq ] )
    tableSummary.addData ( title = "In unlikely ring conformation", data = [ nconf ] )

#    svgFile = '<svg width="100" height="100"><circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /></svg>'

#    results.append(svgFile)

    totalIssues = ngeom + nconf + nanom + ndl + nq
    
    if totalIssues > 0 :
        summaryFold.append ( "There are " + str(totalIssues) + " issues with your model, and they may need correcting. <br/>" ) 
        summaryFold.append ( "Please select 'Manual model rebuilding' at the bottom of this window, so Coot can guide you through all the problems raised.<br/>" ) 
    else :
        summaryFold.append ( "No issues were found while analysing the data." ) 
    
    self.addTaskReferences()


#    def unescape(s):
#        s = s.replace("&lt;", "<")
#        s = s.replace("&gt;", ">")
#        s = s.replace("&amp;", "&")
#        return s

if __name__ == "__main__":
  import sys
  privateer_report(xmlFile=sys.argv[1],jobId=sys.argv[2])


