

import os,sys,math
from CCP4ReportParser import *

class ctruncate_report(Report):
    TASKNAME='ctruncate'
    def __init__(self,xmlnode=None,jobInfo={},jobStatus=None,**kw):
        Report.__init__(self,xmlnode=xmlnode,jobInfo=jobInfo,jobStatus=None,**kw)
        # print 'ctruncate_report 1'
        
        # 'nooutput' mode would be used by another report class that wanted
        # to use some method(s) from this class for its own report
        if jobStatus is not None and jobStatus.lower() == 'nooutput':
            return
        
        try:
          fail = self.Errors(self)
        except:
          fail = False

        if len(jobInfo['outputfiles'])>0:
            self.addText(text='Intensity data has been converted to structure factors')
        else:
            self.addText(text='No  structure factor data has been created')

        if fail == False:
            self.addWarnings(self)
            self.addReflectionData(self)
            self.addQuality(self)
            self.addAnomalous(self)
            self.addNCS(self)
            self.addAnisotropy(self)
            self.addIceRings(self)
            self.addTwin(self)
            self.addCtruncateGraphs(self)

    def keyText(self, parent):
        # The most important warnings for the Aimless pipeline
        self.addWarningTwin(parent)
        self.addWarningTNCS(parent)
        self.addWarningAnisotropy(parent)
        self.addWarningQuality(parent)
        self.addWarningWilson(parent)
        self.addWarningIce(parent)

    def addWarningWilson(self,parent,check=False):
        if self.xmlnode.haspath("//CTRUNCATE//DataStatistics/Comment[@id='CompletenessQuality']"):
            badrings = False;
            x = self.xmlnode.select("//CTRUNCATE//OutlierRingsAnalysis/present")
            if check:
                if x.strip() != "no": 
                    return False
                return True
            if x.strip() != "no":
                if self.xmlnode.haspath("//CTRUNCATE//OutlierRingsAnalysis/percentage"):
                    y = float(self.xmlnode.select("//CTRUNCATE//OutlierRingsAnalysis/percentage"))
                    if y > 3.0:
                        parent.append("<p><b><font color='red'>Warning: Severe deviation from Wilson plot, "+str(y)+"% of bins deviate, please look at it</font></b></p>")
                    else:
                        parent.append("<p><b><font color='orange'>Warning: Some deviation from Wilson plot, "+str(y)+"% of bins deviate, please look at it</font></b></p>")
                else:
                    parent.append("<p><b><font color='red'>Warning: Deviation in WIlson plot, please look at it</font></b></p>")
                return True
        elif check:
            return False

            
    def addWarningQuality(self,parent,check=False):
        if self.xmlnode.haspath("//CTRUNCATE//DataStatistics/Comment[@id='CompletenessQuality']"):
            x = self.xmlnode.select("//CTRUNCATE//DataStatistics/Comment[@id='CompletenessQuality']")
            if check:
                # Just check for problem and return True if there is
                if ("poor" in x.text) or "some" in x.text:
                    return True
                return False

            if "poor" in x.text:
                parent.append("<p><b><font color='red'>Warning:"+x.text+"</font></b></p>")
            elif "some" in x.text:
                parent.append("<p><b><font color='orange'>Warning:"+x.text+"</font></b></p>")
            else:
                parent.append("<p><b><font color='green'>"+x.text+"</font></b></p>")
        elif check:
            return False

    def addWarningTNCS(self,parent,check=False):
        if check:
            # Just check for problem and return True if there is
            if self.xmlnode.haspath('//CTRUNCATE//translationalNCS/detected'):
                if self.xmlnode.select('//CTRUNCATE//translationalNCS/detected') != "No":
                    return True
            return False

        if self.xmlnode.haspath('//CTRUNCATE//translationalNCS/detected'):
            if self.xmlnode.select('//CTRUNCATE//translationalNCS/detected') != "No":
                s = 'Warning: Possible translational non-crystallographic symmetry at<br/>'
                peaks = self.xmlnode.xpath('//CTRUNCATE//translationalNCS/PeakList')
                #print "peaks", peaks, type(peaks)
                coordinates = []
                Qscores = []
                peakRatios = []
                for peak in peaks:
                    #print "peak",peak, type(peak)
                    coordinates.append(peak.select('Peak/coordinate'))
                    Qscores.append(peak.select('Peak/Q-score'))
                    peakRatios.append(peak.select('Peak/height'))
                first = True
                for cdQ in zip(coordinates, Qscores, peakRatios):
                    if not first:
                        s += ', at '
                        first = False
                    s += 'coordinate ('+cdQ[0]+'), chance probability '+cdQ[1]+\
                         ', height '+cdQ[2]+' of origin'

                parent.append("<p><b><font color='red'>"+s+"</font></b></p>")
            else:
                parent.append(
                    "<p><b><font color='green'>No evidence of possible translational non-crystallographic symmetry</font></b></p>")

    def addWarningTwin(self,parent,check=False):
        if check:
            # Just check for problem and return True if there is
            if self.xmlnode.haspath('//CTRUNCATE//L-test/Twinned'):
                if self.xmlnode.select('//CTRUNCATE//L-test/Twinned') != "No":
                    return True
            return False

        if self.xmlnode.haspath('//CTRUNCATE//L-test/Twinned'):
            alphaBritton = 0.0
            alphaHtest = 0.0
            if self.xmlnode.haspath('//CTRUNCATE//TwinOps'):
                oplist = self.xmlnode.xpath("//CTRUNCATE//TwinOps/Operator")
                if len(oplist)>0:
                    # Twin fraction estimate from ML-Britton
                    alist = []
                    y = self.xmlnode.xpath("//CTRUNCATE//ML-Britton/TwinFraction")
                    for x in y:
                        alist.append(x.select('.'))
                    alphaBritton = max(alist)
                    # Twin fraction estimate from H-test
                    alist = []
                    y = self.xmlnode.xpath("//CTRUNCATE//H-test/TwinFraction")
                    for x in y:
                        alist.append(x.select('.'))
                    alphaHtest = max(alist)
                        
            if self.xmlnode.select('//CTRUNCATE//L-test/Twinned') != "No":
                if alphaBritton > 0.1 or alphaHtest > 0.1:
                    s = 'Warning: Possible twinning, twin fraction estimates from Britton plot '+\
                        alphaBritton+', from H-test '+alphaHtest
                    parent.append("<p><b><font color='red'>"+s+"</font></b></p>")
                else:
                    alphaLtest = self.xmlnode.xpath("//CTRUNCATE//L-test/TwinFraction")[0].text
                    s = 'Warning: Possibly twinned and merged in a higher symmetry than the true spacegroup'
                    s += ', twin fraction estimate from L-test ' + alphaLtest
                    parent.append(
                        "<p><b><font color='red'>"+s+"</font></b></p>")
            else:
                parent.append("<p><b><font color='green'>No evidence of twinning</font></b></p>")

    def addWarningAnisotropy(self,parent,check=False):
        if self.xmlnode.haspath('//CTRUNCATE//AnisotropyAnalysis'):
            if self.xmlnode.haspath('//CTRUNCATE//AnisotropyAnalysis/Eigenvalue'):
                paths = self.xmlnode.xpath('//CTRUNCATE//AnisotropyAnalysis/Eigenvalue')
                y = []
                for x in paths:
                    y.append(x.select('.'))
                ratio = min(list(map(float,y)))/max(list(map(float,y)))
                if check:
                    # Just check for problem and return True if there is
                    if ratio < 0.9:
                        return True
                    return False

                if ratio > 0.9:
                    parent.append("<p><b><font color='green'>Little or no anisotropy detected</font></b></p>")
                elif ratio > 0.5:
                    parent.append("<p><b><font color='orange'>Warning: Some anisotropy detected. This may have an effect on statistics.</font></b></p>")
                else:
                    parent.append("<p><b><font color='red'>Warning: data are highly anisotropic.</font></b></p>")

            elif (self.xmlnode.haspath('//CTRUNCATE//AnisotropyAnalysis/Comment')):
                message = self.xmlnode.select('//CTRUNCATE//AnisotropyAnalysis/Comment')
                #print "message", message
                parent.append(message)

        elif check:
            return False

    def addWarningIce(self,parent,check=False):
        if self.xmlnode.haspath('//CTRUNCATE//IceRingsAnalysis'):
            ringslist = self.xmlnode.xpath('//CTRUNCATE//IceRingsAnalysis/Ring/Reject')
            #better in xml
            icerings = False
            for x in ringslist:
                y = x.select('.')
                if y.strip() != "no": icerings = True

            if check:
                # Just check for problem and return True if there is
                if icerings is True:
                    return True
                return False

            if icerings is True:
                parent.append("<p><b><font color='red'>Warning: Possible ice rings found.</font></b></p>")
            else:
                parent.append("<p><b><font color='green'>No ice rings found.</font></b></p>")
        elif check:
            return False

    def addWarningAnomalous(self,parent,check=False):
        if self.xmlnode.haspath("//CTRUNCATE//AnomStatistics/Comment[@id='AnomResult']"):
            x=self.xmlnode.select("//CTRUNCATE//AnomStatistics/Comment[@id='AnomResult']")
            if "Warning" in x.text:
                parent.append("<p><b><font color='red'>"+x.text+"</font></b></p>")
            elif "Some" in x.text:
                parent.append("<p><b><font color='orange'>"+x.text+"</font></b></p>")
            else:
                parent.append("<p><b><font color='green'>"+x.text+"</font></b></p>")
        elif self.xmlnode.haspath("//CTRUNCATE//AnomStatistics/ResolutionRange[@id='Measurability Limit']"):
            f = self.xmlnode.select("//CTRUNCATE/AnomStatistics/ResolutionRange[@id='Measurability Limit']")
            xmax = float(f.select('max'))
            xmin = float(f.select('min'))
            f = self.xmlnode.select("//CTRUNCATE/AnomStatistics/ResolutionRange[@id='Signal to Noise Ratio']")
            ymax = float(f.select('max'))
            ymin = float(f.select('min')) 
            if math.isnan(xmin) or math.isnan(ymin):
                parent.append("<p><b><font color='red'>Warning: no anomalous signal.</font></b></p>")
            elif xmin == xmax and ymin == ymax:
                parent.append("<p><b><font color='red'>Warning: no anomalous signal.</font></b></p>")
            elif xmin > 10 and xmax < 3  and  ymin > 10 and ymax < 3:
                parent.append("<p><b><font color='green'>Significant anomalous signal to high resoluiton.</font></b></p>")
            elif  xmin > 10 and xmax < 5  and  ymin > 10 and ymax < 5:
                parent.append("<p><b><font color='green'>Significant anomalous signal to medium resoluiton.</font></b></p>")
            elif ( xmin > 10 and xmax < 5 ) or ( ymin > 10 and ymax < 5 ):
                parent.append("<p><b><font color='orange'>Inconsistent results, there may be some anomalous signal.</font></b></p>")
            elif xmin < 5 or ymin < 5:
                parent.append("<p><b><font color='red'>Warning: NO anomalous signal. Anomalous signal is probably artefact of noise at high resolution.</font></b></p>")
            else:
                parent.append("<p><b><font color='orange'>Some anomalous signal at intermediate resolution.  Low resolution signal missing.</font></b></p>")

    def addWarnings(self, parent):
        #summary and warnings
        wDiv = parent.addDiv(style="border-width: 1px; border-color: black; clear:both; margin:0px; padding:0px;")
        wDiv.addText(text="Summary",style="font-size:130%;text-align:left")
        #eg tNCS
        self.addWarningQuality(wDiv)
        self.addWarningWilson(wDiv)
        self.addWarningTNCS(wDiv)
        self.addWarningTwin(wDiv)
        self.addWarningAnisotropy(wDiv)
        self.addWarningIce(wDiv)
        self.addWarningAnomalous(wDiv)
            
    def CtruncateLtest(self, parent):
        # A GraphGroup is a group of graphs displayed in the same graph viewer widget
        graphgroup = parent.addFlotGraphGroup(style="width:300px;  height:300px;margin: 0 auto;border:0px solid blue;")
        # Add a Graph to the GraphGroup - add a table of data and plot instructions to the graph
        # Loop over all Graph tables in the program output and add to the GraphGroup
        # The plotting instructions are provided as xml text
        graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='L-test']")
        #print "CtruncateLtest", self.xmlnode
        #print "CtruncateLtest", graphlist
        for thisgraph in graphlist:
            graph = graphgroup.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
            graph = graph.addPimpleData(xmlnode=thisgraph)

    def CtruncateWilson(self, parent):
        # A GraphGroup is a group of graphs displayed in the same graph viewer widget
        graphgroup = parent.addFlotGraphGroup(style="width:300px;  height:300px;margin: 0 auto;border:0px solid blue;")
        # Add a Graph to the GraphGroup - add a table of data and plot instructions to the graph
        # Loop over all Graph tables in the program output and add to the GraphGroup
        # The plotting instructions are provided as xml text
        graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='WilsonB']")
        for thisgraph in graphlist:
            graph = graphgroup.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
            graph = graph.addPimpleData(xmlnode=thisgraph)

    def addCtruncateReport(self, parent):
        reportDivHeader = parent.addDiv(style="font-size:120%;")
        reportDivHeader.append('<span style="font-style: bold">Detailed reports on intensity statistics etc</span><br/>')
        #reportDivHeader.append('<a href="#twinreport">* Twinning</a><br/>')
        #reportDivHeader.append('<a href="#dataqualityreport">* Data quality</a><br/>')
        #reportDivHeader.append('<a href="#ncsreport">* Non-crystallographic symmetry</a><br/>')
        #reportDivHeader.append('<a href="#anomalousreport">* Anomalous signal</a><br/>')
        #reportDivHeader.append('<a href="#anisotropyreport">* Anisotropy</a><br/>')
        #reportDivHeader.append('<a href="#iceringsreport">* Ice rings</a><br/>')

        reportDiv = parent.addDiv()
        self.addTwin(reportDiv)
        self.addQuality(reportDiv)
        self.addNCS(reportDiv)
        self.addAnomalous(reportDiv)
        self.addAnisotropy(reportDiv)
        self.addIceRings(reportDiv)

    def addReflectionData(self,parent=None):
        #parent.append('<a name="reflectiondata"></a>')
        startopen = True
        fold = parent.addFold(label="Details of reflection data",
                              brief='InputData',initiallyOpen=startopen)
        fold.addText(text="Summary of input reflection data",style="font-size:130%;text-align:center")
        fold.append("<br/>")
        f = self.xmlnode.xpath('//CTRUNCATE//ReflectionFile')
        fold.append("<b>File:</b> "+f[0].get("name"))
        fold.append("<b>Crystal/Dataset:</b> "+f[0].select('CrystalDatasetId'))
        fold.append("<b>Cell:</b> "+f[0].select('cell/a')+", "+f[0].select('cell/b')+", "+f[0].select('cell/c')+", "+f[0].select('cell/alpha')+", "+f[0].select('cell/beta')+", "+f[0].select('cell/gamma'))
        fold.append("<b>Spacegroup:</b> "+f[0].select('SpacegroupName'))
        fold.append("<p><b>Reflection data summary:</b></p>")
        table = fold.addTable( select = "//CTRUNCATE//ReflectionData", transpose=False )
        for title,select in [ [ "Data type", "ReflectionDataType" ],
                             [ "Min resolution", "ResolutionLow"],
                             [ "Max resolution", "ResolutionHigh" ],
                             [ "Nreflections", "NumberReflections" ],
                             [ "NObservations", "NumberObservations" ],
                             [ "NCentric", "NumberCentric" ] ]:
            table.addData( title=title , select = select )
        
        fold.append("<p><b>Maximum indices in reflection data:</b></p>")
        path=self.xmlnode.xpath('//CTRUNCATE//ReflectionData/ReflectionIndexMax')
        table1 = fold.addTable( select = "//CTRUNCATE//ReflectionData", transpose=False )
        tablist = []
        for x in path:
            tablist.append(x.select('@id'))
        table1.addData(title='Direction',data=tablist)
        taglist = \
            [["Index (file)", "FileReflectionIndexMax/Index"],
             ["Max Resolution (file)", "FileReflectionIndexMax/Resolution"],
             ["Index (P1)", "ReflectionIndexMax/Index"],
             ["Max Resolution (P1)", "ReflectionIndexMax/Resolution"]]
        for title,select in taglist:
            table1.addData( title=title, select=select)


    def addNCS(self, parent=None):
        if self.xmlnode.haspath('//CTRUNCATE//translationalNCS'):
            #parent.append('<a name="ncsreport"></a>')
            startopen = self.addWarningTNCS(parent, check=True)
            path=self.xmlnode.xpath('//CTRUNCATE//translationalNCS')
            fold = parent.addFold(label="tNCS",initiallyOpen=startopen)
            fold.addText(text='tNCS',style="font-size:130%;")
            x = self.xmlnode.select("//Comment[@id='tncs']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            x = self.xmlnode.select("//Comment[@id='tncsExplain']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            x = self.xmlnode.select("//Reference[@id='tncsExplain']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            if path[0].select('detected') != "No": fold.append("<p><b>Warning:</b> flat prior used for truncate procedure</p>")
            
    def addAnisotropy(self, parent=None):
        if self.xmlnode.haspath('//CTRUNCATE//AnisotropyAnalysis') and \
               self.xmlnode.haspath("//Comment[@id='AnisotropyResult']"):
            #parent.append('<a name="anisotropyreport"></a>')
            startopen = self.addWarningAnisotropy(parent, check=True)
            path=self.xmlnode.xpath('//CTRUNCATE//AnisotropyAnalysis')
            fold = parent.addFold(label="Anisotropy analysis",brief="Anisotropy",
                                  initiallyOpen=startopen)
            fold.addText(text='Anisotropy Analysis',style="font-size:130%;")
            x = self.xmlnode.select("//Comment[@id='AnisotropyResult']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            #fold.append("Anisotropy will be corrected for in the truncation procedure.")
            if self.xmlnode.haspath('//CTRUNCATE//AnisotropyAnalysis/BAniso'):
                fold.append("<p><b>ML Anisotropy matrices:</b></p>")
                aDiv = fold.addDiv(style="width:50%;float:left;border-width: 0px; border-color: black;text-align:left; margin:0px; padding:0px;")
                bDiv = fold.addDiv(style="width:50%;float:left;border-width: 0px; border-color: black;text-align:left; margin:0px; padding:0px;")
                #aDiv.append("<p><b>Anisotropy eigenvalues:</b></p>"+path[0].select("Eigenvalue[@id='0']").text+" "+path[0].select("Eigenvalue[@id='1']").text+" "+path[0].select("Eigenvalue[@id='2']").text)
                result = path[0].select("BAniso/Orthogonal")
                list = result.split()
                list.insert(6,'<br/>')
                list.insert(3,'<br/>')
                aDiv.append("<p><b>Anisotropy B matrix:</b></p>"+"  ".join(str(x) for x in list))
                result = path[0].select("UAniso[@id='obs']/Orthogonal")
                list = result.text.split()
                list.insert(6,'<br/>')
                list.insert(3,'<br/>')
                bDiv.append("<p><b>Anisotropy U matrix:</b></p>"+"  ".join(str(x) for x in list))
                fold.append("<p><b>Eigenvalues and Eigenvectors of anisotropy matrix</b></p>")
                table = fold.addTable( select = "//CTRUNCATE//AnisotropyAnalysis", transpose=False )
                taglist = \
                    [["Eigenvalue", "Eigenvalue"],
                     ["Eigenvector", "EigenVector"]]
                for title,select in taglist:
                    table.addData( title=title, select=select)
                fold.append("<p><b>Directional plots:</b></p>")
                x = self.xmlnode.select("//Comment[@id='YorgoModisPlot']")
                graphlist = self.xmlnode.xpath("CCP4Table[@id='AnisotropyAnalysis']")
    #not stable, so should use graph-aniso as grouID
                graph = fold.addFlotGraph( xmlnode=graphlist[0], title=graphlist[0].get("title") )
                graph = graph.addPimpleData(xmlnode=graphlist[0])
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                result = path[0].select("UAniso[@id='correction']/Orthogonal")
                list = result.text.split()
                list.insert(6,'<br/>')
                list.insert(3,'<br/>')
                fold.append("<p><b>Anisotropic correction:</b></p>"+"  ".join(str(x) for x in list))
                fold.append("<p>This will be used in the remaining statistics calculations.</p>")
                #fold.append("<p><font color='red'>effect of correction on data.</font></p>")


    def addQuality(self, parent=None):
        #completeness table name...
        #parent.append('<a name="dataqualityreport"></a>')
        startopen = self.addWarningQuality(parent, check=True)
        fold = parent.addFold(label="Data quality",brief="Quality",initiallyOpen=startopen)
        fold.addText(text='Data quality',style="font-size:130%;")
        if self.xmlnode.haspath('//CTRUNCATE//DataStatistics/ResolutionRange'):
            path=self.xmlnode.xpath('//CTRUNCATE//DataStatistics/ResolutionRange')
            fold.append("<p><b>Resolution range statistics:</b></p>")
            table = fold.addTable( select = "//CTRUNCATE//DataStatistics/ResolutionRange", transpose=False, style="margin: 0 auto;border:1px solid orange;" )
            tablist = []
            for x in path:
                tablist.append(x.select('@title'))
            table.addData(title='Statistic',data=tablist)
            if self.xmlnode.haspath('//CTRUNCATE//DataStatistics/ResolutionRange/percentage'):
                taglist = \
                    [["Min Resolution", "min"], ["Max Resolution", "max"], ["Percentage refln","percentage"]]
                for title,select in taglist:
                    table.addData( title=title, select=select) 
            else: 
                taglist = \
                    [["Min Resolution", "min"], ["Max Resolution", "max"]]
                for title,select in taglist:
                    table.addData( title=title, select=select)
            x1 = self.xmlnode.select("//CTRUNCATE//DataStatistics/Comment[@id='CompletenessReso']")
            x2 = self.xmlnode.select("//CTRUNCATE//DataStatistics/Comment[@id='Completeness3']")
            x3 = self.xmlnode.select("//CTRUNCATE//DataStatistics/Comment[@id='ActiveRange']")
            fold.append("<p><font color='purple'>"+x1.text+" "+x2.text+"<ul>"+x3.text+"</ul></font></p>")
        if self.xmlnode.haspath("//CTRUNCATE//CCP4Table[@id='completeness']"):
            fold.append("<p><b>Completeness and R-standard plots</b></p>")
            graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='completeness']")
            #not stable, so should use graph-aniso as groupID
            graph = fold.addFlotGraph( xmlnode=graphlist[0], title=graphlist[0].get("title") )
            graph = graph.addPimpleData(xmlnode=graphlist[0])
            x = self.xmlnode.findtext("DataStatistics//Comment[@id='Completeness']")
            x = x.replace("<", "&lt;");
            x = x.replace(">", "&gt;");
            fold.append("<p><font color='purple'>"+x+"</font></p>")
        if self.xmlnode.haspath("//CTRUNCATE//DataStatistics/LowResoCompleteness"):
            fold.append("<p><b>Low Resolution Completeness</b></p>")
            table = fold.addTable( select = "//CTRUNCATE//DataStatistics/LowResoCompleteness", transpose=False, style="margin: 0 auto;border:1px solid orange;" )
            resolist1 = self.xmlnode.xpath("//CTRUNCATE//DataStatistics/LowResoCompleteness/ResolutionRange/min")
            resolist2 = self.xmlnode.xpath("//CTRUNCATE//DataStatistics/LowResoCompleteness/ResolutionRange/max")
            complist1 = self.xmlnode.xpath("//CTRUNCATE//DataStatistics/LowResoCompleteness/Completeness")
            complist2 = self.xmlnode.xpath("//CTRUNCATE//DataStatistics/LowResoCompleteness/nObs")
            complist3 = self.xmlnode.xpath("//CTRUNCATE//DataStatistics/LowResoCompleteness/nTot")
            resotab = []
            comptab = []
            for x,y in zip(resolist1,resolist2):
                resotab.append(x.select(".")+" - "+y.select(".") )
            for x,y,z in zip(complist1,complist2,complist3):
                comptab.append(x.select(".")+"  ["+y.select(".")+" : "+z.select(".")+"]" )
            table.addData(title='Resolution',data=resotab)
            table.addData(title='Completeness',data=comptab)
            x = self.xmlnode.select("//CTRUNCATE//DataStatistics/Comment[@id='CompletenessLow']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")

        if self.xmlnode.haspath('//CTRUNCATE//DataStatistics/WilsonB'):
            path=self.xmlnode.xpath('//CTRUNCATE//DataStatistics/WilsonB')
            fold.append("<p><b>Wilson scaling:</b></p>")
            fold.append("<p><font color='purple'>Estimate of overall wilson B-factor: "+self.xmlnode.select('//CTRUNCATE//DataStatistics/WilsonB')+" A^(-2)</font></p>")
            fold.append("<p><font color='purple'>Estimate wilson scale factor: "+self.xmlnode.select('//CTRUNCATE//DataStatistics/WilsonScale')+"</font></p>")
            x = self.xmlnode.select("//Comment[@id='WilsonB']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            if self.xmlnode.haspath("//CTRUNCATE//CCP4Table[@id='WilsonB']"):
                graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='WilsonB']")
                #not stable, so should use graph-aniso as grouID
                graph = fold.addFlotGraph( xmlnode=graphlist[0], title=graphlist[0].get("title") )
                graph = graph.addPimpleData(xmlnode=graphlist[0])
            x = self.xmlnode.select("//Comment[@id='WilsonPlot']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            x = self.xmlnode.select("//Reference[@id='Best']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            #fold.append("<p><font color='red'>ML calc<br/>outlier reflections</font></p>")

        if self.xmlnode.haspath('//CTRUNCATE//OutlierRingsAnalysis'):
            fold.append("<p><b>Check for bad rings:</b></p>")
            badrings = False;
            x = self.xmlnode.select("//CTRUNCATE//OutlierRingsAnalysis/present")
            if x.strip() != "no": badrings = True
            
            if badrings is True:
                if self.xmlnode.haspath("//CTRUNCATE//OutlierRingsAnalysis/percentage"):
                    y = float(self.xmlnode.select("//CTRUNCATE//OutlierRingsAnalysis/percentage"))
                    fold.append("<p>Possible bad resolution rings found, consisting of "+str(y)+"% of bins. Data in these may be of lower quality.</p>")
                else:
                    fold.append("<p>Possible bad resolution rings found. Data in these may be of lower quality.</p>")
                table = fold.addTable( select = "//CTRUNCATE//OutlierRingsAnalysis", transpose=False, style="margin: 0 auto;border:1px solid orange;" )
                taglist = \
                        [["Resolution", "Ring/Resolution"],
                         ["Imean", "Ring/Imean"],
                         ["Z-score", "Ring/Z-score"],
                         ["Completeness", "Ring/Completeness"],
                         ["Ave. Completeness", "Ring/ExpectCompleteness"]]
                for title,select in taglist:
                    table.addData( title=title, select=select)

            else:
                fold.append("<p>No issues found.</p>")
            
            x = self.xmlnode.select("//Comment[@id='OutlierRingsAnalysis']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")

        #if self.xmlnode.haspath("//CTRUNCATE//CCP4Table[@id='acentricMoments']"):
            #fold.append("<p><b>Moments plots</b></p>")
            #x = self.xmlnode.select("//Comment[@id='MomentsReso']")
            #fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            #fold.append("<p><font color='red'>Moments graphs are too truncated and do not have values</font></p>")
            #graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='acentricMoments']")
            #not stable, so should use graph-aniso as grouID
            #graph = fold.addFlotGraph( xmlnode=graphlist[0], title=graphlist[0].get("title") )
            #graph = graph.addPimpleData(xmlnode=graphlist[0])


    def addAnomalous(self, parent=None):
        if self.xmlnode.haspath('//CTRUNCATE//AnomStatistics'):
            #parent.append('<a name="anomalousreport"></a>')
            startopen = False
            fold = parent.addFold(label="Anomalous",initiallyOpen=startopen)
            fold.addText(text='Anomalous signal',style="font-size:130%;")
            #fold.append("<p><font color='red'>Use resolution range to comment on anom signal</font></p>")
            path=self.xmlnode.xpath('//CTRUNCATE//AnomStatistics/ResolutionRange')
            fold.append("<p><b>Anomalous signal statistics:</b></p>")
            table = fold.addTable( select = "//CTRUNCATE/AnomStatistics/ResolutionRange", transpose=False, style="margin: 0 auto;border:1px solid orange;" )
            tablist = []
            for x in path:
                tablist.append(x.select('@id'))
            table.addData(title='Statistic',data=tablist)
            taglist = \
                [["Min Resolution", "min"],
                 ["Max Resolution", "max"]]
            for title,select in taglist:
                table.addData( title=title, select=select)
            if self.xmlnode.haspath("//CTRUNCATE//AnomStatistics/Comment[@id='Anom']"):
                x=self.xmlnode.select("//CTRUNCATE//AnomStatistics/Comment[@id='Anom']")
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                fold.append("<p><font color='green'>The resolution limits are derived from I/sigI of 1.2 for the signal to noise, and measurability above 5%.</font></p>")
            if self.xmlnode.haspath("//CTRUNCATE//AnomStatistics/Comment[@id='AnomResult']"):
                x=self.xmlnode.select("//CTRUNCATE//AnomStatistics/Comment[@id='AnomResult']")
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                x=self.xmlnode.select("//CTRUNCATE//AnomStatistics/Comment[@id='AnomDescription']")
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            if self.xmlnode.haspath("//CTRUNCATE//CCP4Table[@id='anomalous intensity plot']"):
                graphlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='anomalous intensity plot']")
                #not stable, so should use graph-aniso as groupID
                graph = fold.addFlotGraph( xmlnode=graphlist[0], title=graphlist[0].get("title") )
                graph = graph.addPimpleData(xmlnode=graphlist[0])


    def addIceRings(self, parent=None):
        if self.xmlnode.haspath('//CTRUNCATE//IceRingsAnalysis'):
            #parent.append('<a name="iceringsreport"></a>')
            startopen = self.addWarningIce(parent, check=True)
            fold = parent.addFold(label="Ice Rings",initiallyOpen=startopen)
            fold.addText(text='Ice Rings',style="font-size:130%;")
            icerings = False;
            ringslist = self.xmlnode.xpath('//CTRUNCATE//IceRingsAnalysis/Ring/Reject')
            #better in xml
            for x in ringslist:
                y = x.select('.')
                if y.strip() != "no": icerings = True
            
            if icerings is True:
                fold.append("<p>Possible ice rings found. Data in these may be of lower quality.</p>")
                fold.append("Ice rings will be ignored in the truncate procedure.")
            else:
                fold.append("<p>No ice rings found.</p>")
            
            table = fold.addTable( select = "//CTRUNCATE//IceRingsAnalysis", transpose=False, style="margin: 0 auto;border:1px solid orange;" )
                    
            #tablelist = self.xmlnode.xpath("Ring")
            taglist = \
                    [["Resolution", "Ring/Resolution"],
                     ["Ice Ring", "Ring/Reject"],
                     ["Imean", "Ring/Imean"],
                     ["Z-score", "Ring/Z-score"],
                     ["Completeness", "Ring/Completeness"],
                     ["Ave. Completeness", "Ring/ExpectCompleteness"]]
            for title,select in taglist:
                table.addData( title=title, select=select)
            x = self.xmlnode.select("//Comment[@id='IceRingsAnalysis']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")

    def addTwin(self, parent=None):
        if self.xmlnode.haspath('//CTRUNCATE//Twinning'):
            #parent.append('<a name="twinreport"></a>')
            # Should this be initially open?
            startopen = self.addWarningTwin(parent, check=True)
            fold = parent.addFold(label="Twinning statistics",
                                  brief="Twinning",initiallyOpen=startopen)
            fold.addText(text='Twinning statistics',style="font-size:130%;")
            x=self.xmlnode.select("//CTRUNCATE//Twinning/Comment[@id='TwinningSummary']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            x1 = x.text
            y1 = x1.strip()
            if len(y1) > 0 and y1[0] != "N": fold.append("<p><b>Warning:</b> flat prior used for truncate procedure</p>")
            if self.xmlnode.haspath('//CTRUNCATE//L-test'):
                fold.append("<p><b>Global twinning estimates:</b></p>")
                x=self.xmlnode.select("//CTRUNCATE//Twinning/Comment[@id='TwinningGlobal']")
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                table=fold.addTable()
                testtab = []
                resulttab = []
                scoretab = []
                alphatab = []
                if self.xmlnode.haspath('//CTRUNCATE//L-test'):
                    testtab.append('L-test')
                    resulttab.append(self.xmlnode.select('//CTRUNCATE//L-test/Twinned'))
                    scoretab.append(self.xmlnode.select('//CTRUNCATE//L-test/Result'))
                    alphatab.append(self.xmlnode.select('//CTRUNCATE//L-test/TwinFraction'))
                table.addData(title='Test',data=testtab)
                table.addData(title='Twinnned?',data=resulttab)
                table.addData(title='Score',data=scoretab)
                table.addData(title='alpha',data=alphatab)
                    
                x = self.xmlnode.select("//Comment[@id='L-test']")
                fold.append("<p>"+x.text+"</p>")
                    
        if self.xmlnode.haspath('//CTRUNCATE//TwinOps'):
            fold.append("<p><b>Operator based twinning estimates:</b></p>")
            if self.xmlnode.haspath("//CTRUNCATE//Rtwin"):
                x = self.xmlnode.findtext("Twinning//Comment[@id='TwinningOperatorBased']")
                x = x.replace("<", "&lt;");
                x = x.replace(">", "&gt;");
                fold.append("<p><font color='purple'>"+x+"</font></p>")
                oplist = self.xmlnode.xpath("//CTRUNCATE//TwinOps/Operator")
                if len(oplist)>0:
                    rtwinlist = self.xmlnode.xpath("//CTRUNCATE//Rtwin")
                    rhlist = self.xmlnode.xpath("//CTRUNCATE//H-test")
                    rmllist = self.xmlnode.xpath("//CTRUNCATE//ML-Britton")
                    table=fold.addTable()
                    optab = []
                    rtwintab = []
                    rhtab = []
                    rmltab = []
                    for x in rtwinlist:
                        #optab.append(x.get("operator") )
                        optab.append(x.select("@operator"))
                        rtwintab.append(x.select(".") )
                    for x in rhlist:
                        rhtab.append(x.select('TwinFraction'))
                    for x in rmllist:
                        rmltab.append(x.select('TwinFraction'))
                    table.addData(title='Operator',data=optab)
                    table.addData(title='Rtwin</br>score',data=rtwintab)
                    table.addData(title='H-test</br>Twin Fraction',data=rhtab)
                    table.addData(title='ML-Britton</br>Twin Fraction',data=rmltab)
            else:
                fold.append("<p>"+self.xmlnode.select("//Comment[@id='TwinOps']").text+"</p>")

        if self.xmlnode.haspath('//CTRUNCATE//Twinning'):
            fold.append("<p><b>Twinning plots based on global statistics</b></p>")
            fold.append("<p><b><i>L-test</i></b></p>")
            ltestlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='L-test']")
            for thisgraph in ltestlist:
                graph = fold.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                graph = graph.addPimpleData(xmlnode=thisgraph)
            x = self.xmlnode.select("//Comment[@id='LTestDesc']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            x = self.xmlnode.select("//Reference[@id='LTest']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            fold.append("<p><b><i>N(Z) plot</i></b></p>")
            #problem is have amplitudes too
            cumullist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='Cumulative intensity distribution']")
            for thisgraph in cumullist:
                graph = fold.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                graph = graph.addPimpleData(xmlnode=thisgraph)
                x = self.xmlnode.select("//Comment[@id='NZ']")
                fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            #fold.append("<p><font color='red'>any stats</font></p>")
            if self.xmlnode.haspath('//CTRUNCATE//Twinning/Moments'):
                fold.append("<p><b><i>Wilson ratios and moments plot</i></b></p>")
                aDiv = fold.addDiv(style="width:50%;float:left;border-width: 0px; border-color: black;text-align:left; margin:0px; padding:0px;")
                bDiv = fold.addDiv(style="width:50%;float:left;border-width: 0px; border-color: black;text-align:left; margin:0px; padding:0px;")
                #problem is have amplitudes too
                mlist = self.xmlnode.xpath("//CTRUNCATE//Moments[@id='acentric']/Moment")
                if len(mlist)>0:
                    aDiv.append("<p>Acentric reflections</p>")
                    table=aDiv.addTable()
                    optab = []
                    vtab = []
                    utab = []
                    ptab = []
                    for x in mlist:
                        y = x.select("@id")
                        y = y.replace("<", "&lt;");
                        y = y.replace(">", "&gt;");
                        #optab.append(x.select("@id"))
                        optab.append(y)
                        vtab.append(x.select("value"))
                        ptab.append(x.select("twinned"))
                        utab.append(x.select("untwinned"))
                    table.addData(title='Operator',data=optab)
                    table.addData(title='Value',data=vtab)
                    table.addData(title='Untwinned',data=utab)
                    table.addData(title='Perfect</br>twin',data=ptab)
                    momlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='acentricMoments']")
                    for thisgraph in momlist:
                        graph = aDiv.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                        graph = graph.addPimpleData(xmlnode=thisgraph)
            mlist = self.xmlnode.xpath("//CTRUNCATE//Moments[@id='centric']/Moment")
            if len(mlist)>0:
                bDiv.append("<p>Centric reflections</p>")
                table=bDiv.addTable()
                optab = []
                vtab = []
                utab = []
                ptab = []
                for x in mlist:
                    y = x.select("@id")
                    y = y.replace("<", "&lt;");
                    y = y.replace(">", "&gt;");
                    #optab.append(x.select("@id"))
                    optab.append(y)
                    vtab.append(x.select("value"))
                    ptab.append(x.select("twinned"))
                    utab.append(x.select("untwinned"))
                table.addData(title='Operator',data=optab)
                table.addData(title='Value',data=vtab)
                table.addData(title='Untwinned',data=utab)
                table.addData(title='Perfect</br>twin',data=ptab)
                momlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='centricMoments']")
                for thisgraph in momlist:
                    graph = bDiv.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                    graph = graph.addPimpleData(xmlnode=thisgraph)
                        
            x = self.xmlnode.select("//Comment[@id='MomentsReso']")
            fold.append("<p><font color='purple'>"+x.text+"</font></p>")
            #fold.append("<p><font color='red'>moments of E</font></p>")

        if self.xmlnode.haspath('//CTRUNCATE//TwinOps'):
            if self.xmlnode.haspath("//CTRUNCATE//Rtwin"):
                oplist = self.xmlnode.xpath("//CTRUNCATE//TwinOps")
                #any twinops
                if len(oplist)>0:
                    fold.append("<p><b>Calculation of possible twinning operators:</b></p>")
                    table = fold.addTable( select = "//CTRUNCATE//TwinOps", transpose=False )
                    for title,select in [ [ "Operator", "Operator/Description" ],
                             [ "Score/Obliquenss", "Operator/Score" ],
                             [ "Type(m/pm)", "Operator/Type" ] ]:
                        table.addData( title=title , select = select )
                    x = self.xmlnode.select("//Comment[@id='TwinOps']")
                    fold.append("<p>"+x.text+"</p>")
                    x = self.xmlnode.select("//Comment[@id='IfTwinOpsPresent']")
                    fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                    fold.append("<p><b>Twinning operator plots:</b></p>")
                    fold.append("<p><i>H plot</i></p>")
                    x = self.xmlnode.select("//Comment[@id='HTest']")
                    fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                    hlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='H-test']")
                    for thisgraph in hlist:
                        graph = fold.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                        graph = graph.addPimpleData(xmlnode=thisgraph)
                    fold.append("<p><i>ML Britton</i></p>")
                    x = self.xmlnode.select("//Comment[@id='MLBritton']")
                    fold.append("<p><font color='purple'>"+x.text+"</font></p>")
                    mllist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='ML-Britton']")
                    for thisgraph in mllist:
                        graph = fold.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                        graph = graph.addPimpleData(xmlnode=thisgraph)


    def addCtruncateGraphs(self, parent):
        reportDiv = parent.addDiv()
        fold = parent.addFold(label="Graphs")
        #summaryNode = self.xmlnode.xpath0('CCP4Summary')
        #summaryDiv = reportDiv.addDiv()
        #summaryDiv.text = '<pre>'+summaryNode.text + '</pre>'
        graphTableList = self.xmlnode.xpath("//CTRUNCATE//CCP4Table")
        graphgroup = fold.addFlotGraphGroup(style="width:500px;  height:400px;")
        for graphTableNode in graphTableList:
            #print "CTruncateGraphs",graphTableNode
            graph = graphgroup.addFlotGraph( xmlnode=graphTableNode, title=graphTableNode.get("title") )
            graph = graph.addPimpleData(xmlnode=graphTableNode)


    def acentricMoments(self, parent):
        if self.xmlnode.haspath('//CTRUNCATE//Twinning/Moments'):
            parent.append("Acentric intensity moments")
            momlist = self.xmlnode.xpath("//CTRUNCATE//CCP4Table[@id='acentricMoments']")
            for thisgraph in momlist:
                graph = parent.addFlotGraph( xmlnode=thisgraph, title=thisgraph.get("title") )
                graph = graph.addPimpleData(xmlnode=thisgraph)

            mlist = self.xmlnode.xpath("//CTRUNCATE//Moments[@id='acentric']/Moment")
            if len(mlist)>0:
                s = "<p>Values for these data, and for ideal data (untwinned or twinned)"
                if (self.addWarningTNCS(parent, check=True)):
                    s += "<br/><span style='color:orange; font-style:italic;'>"
                    s += "Since translation NCS is present, these ideal data values are inappropriate</span>"
                s += "</p>"
                parent.append(s)
                    
                table=parent.addTable()
                optab = []
                vtab = []
                utab = []
                ptab = []
                for x in mlist:
                    y = x.select("@id")
                    y = y.replace("<", "&lt;");
                    y = y.replace(">", "&gt;");
                    #optab.append(x.select("@id"))
                    optab.append(y)
                    vtab.append(x.select("value"))
                    ptab.append(x.select("twinned"))
                    utab.append(x.select("untwinned"))

                table.addData(title='Operator',data=optab)
                table.addData(title='Value',data=vtab)
                table.addData(title='Untwinned',data=utab)
                table.addData(title='Perfect</br>twin',data=ptab)

