Пример #1
0
    def fromXML(self, xmlObj):
        from lxml.etree import _Element

        if xmlObj.__class__ != _Element:
            raise Exception('You must provide a valid XML object.')

        if xmlObj.tag == "CTFCorrectionJob":
            jobDescription = xmlObj
        else:
            jobDescription = xmlObj.xpath('CTFCorrectionJob')
            if len(jobDescription) == 0:
                raise Exception("This XML is not a CTFCorrectionJob.")
            jobDescription = jobDescription[0]

        from pytom.basic.structures import ParticleList, Reference, Mask, SampleInformation

        particleList_element = jobDescription.xpath('ParticleList')[0]
        pl = ParticleList('.')
        pl.fromXML(particleList_element)
        self.particleList = pl

        self.reference = []
        r = jobDescription.xpath('Reference')
        for ref_obj in r:
            ref = Reference('')
            ref.fromXML(ref_obj)
            self.reference.append(ref)

        m = jobDescription.xpath('Mask')[0]
        self.mask = Mask('')
        self.mask.fromXML(m)

        try:
            si = jobDescription.xpath('SampleInformation')[0]
            self.sampleInformation = SampleInformation()
            self.sampleInformation.fromXML(si)
        except:
            self._sampleInformation = SampleInformation()

        self.ctf_conv_pl = jobDescription.get('CTFConvolutedParticleList')
        self.peak_offset = int(jobDescription.get('PeakOffset'))
        self.bw_range = [
            int(i)
            for i in jobDescription.get('BandwidthRange')[1:-1].split(',')
        ]
        self.freq = int(jobDescription.get('Frequency'))
        self.destination = jobDescription.get('Destination')
        self.max_iter = int(jobDescription.get('MaxIterations'))
        self.r_score = jobDescription.get('RScore') == 'True'
        self.weighting = jobDescription.get('WeightedAverage') == 'True'
        self.bfactor = jobDescription.get('BFactor')
        self.sum_ctf_sqr = jobDescription.get('CTFSquared')
Пример #2
0
    def fromXML(self, xmlObj):
        from lxml.etree import _Element

        if xmlObj.__class__ != _Element:
            raise Exception('You must provide a valid XML object.')

        if xmlObj.tag == "FRMResult":
            result = xmlObj
        else:
            result = xmlObj.xpath('FRMResult')
            if len(result) == 0:
                raise Exception("This XML is not a FRMResult.")
            result = result[0]

        from pytom.basic.structures import ParticleList

        particleList_element = result.xpath('ParticleList')[0]
        pl = ParticleList('.')
        pl.fromXML(particleList_element)
        self.pl = pl

        self.name = result.get('Name')
        self.worker_id = int(result.get('WorkerID'))
Пример #3
0
class GrowingAverageJob(PyTomClass):
    """
    GrowingAverageJob:
    @ivar particleList: List of particles to be aligned
    @ivar angleObject: Angle object L{pytom.angles.AngleObject}
    @ivar startParticleNumber: Number of start particle (default 0)
    @ivar maskFile: Mask used for appedizing 
    """
    
    def __init__(self,particleList=None,angleObject=None,maskFile=None,scoreObject=None,startClassNumber=0,destinationDirectory='.',preprocessing = None):
        
        from pytom.tools.files import checkDirExists
        from pytom.angles.angleList import AngleList
        from pytom.basic.structures import ParticleList
        
        self._particleList = particleList or ParticleList('/')
        self._angleObject = angleObject or AngleList()
        self._startClassNumber = startClassNumber
        self._maskFile = maskFile or None
        
        if preprocessing:
            self._preprocessing = preprocessing
        else:
            from pytom.alignment.preprocessing import Preprocessing
            self._preprocessing = Preprocessing()
        
        
        if self._maskFile.__class__ == str:
            from pytom.basic.structures import Mask 
            self._maskFile = Mask(self.maskFile)
            
        self._score = scoreObject
        
        if not checkDirExists(destinationDirectory):
            raise Exception('Destination directory ' + destinationDirectory + ' does not exist.')
        
        if not destinationDirectory[len(destinationDirectory)-1] == '/':
            destinationDirectory = destinationDirectory + '/'
        
        self._destinationDirectory = destinationDirectory
        
    def toXML(self):
        """
        toXML : Compiles a XML file from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """ 
        from lxml import etree
        
        job_element = etree.Element('GrowingAverageJob',StartClassNumber = str(self._startClassNumber), DestinationDirectory = str(self._destinationDirectory))
        
        job_element.append(self._maskFile.toXML())
        
        job_element.append(self._particleList.toXML())
        
        job_element.append(self._angleObject.toXML())
        
        job_element.append(self._score.toXML())
        
        job_element.append(self._preprocessing.toXML())
        
        return job_element
        
    def fromXML(self,xmlObj):
        """
        fromXML:
        @param xmlObj: A xml object  
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe 
        """
        
        from lxml.etree import _Element
        
        if xmlObj.__class__ != _Element :
            from pytom.basic.exceptions import ParameterError
            raise ParameterError('Is not a lxml.etree._Element! You must provide a valid XMLobject.')
        
        if xmlObj.tag == 'GrowingAverageJob':
            job_element = xmlObj
        else:
            from pytom.basic.exceptions import ParameterError
            raise ParameterError('Is not a GrowingAverageJobXML! You must provide a valid GrowingAverageJobXML object.')
        
        from pytom.angles.angle import AngleObject
        from pytom.score.score import fromXML as scoreFromXML
        from pytom.basic.structures import ParticleList
        from pytom.alignment.preprocessing import Preprocessing
        
        self._startClassNumber = int(job_element.get('StartClassNumber'))
        
        mask = job_element.xpath('Mask')[0]
        from pytom.basic.structures import Mask
        self._maskFile = Mask('')
        self._maskFile.fromXML(mask)
         
        self._destinationDirectory = job_element.get('DestinationDirectory')
        
        particleXML = job_element.xpath('ParticleList')[0]
        
        self._particleList = ParticleList('/',[])
        self._particleList.fromXML(particleXML)
        
        angleXML = job_element.xpath('Angles')[0]
        
        ang = AngleObject()
        self._angleObject = ang.fromXML(angleXML)
        
        scoreXML = job_element.xpath('Score')[0]
        
        self._score = scoreFromXML(scoreXML)
        
        self._preprocessing = Preprocessing()
        preprocessingXML = job_element.xpath('Preprocessing')[0]
        self._preprocessing.fromXML(preprocessingXML)
Пример #4
0
    def fromXML(self, xmlObj):
        """
        read from xml file
        @param xmlObj: xml object
        @type xmlObj: L{lxml.etree.Element}
        """
        from lxml.etree import _Element

        if xmlObj.__class__ != _Element:
            raise Exception('You must provide a valid XML object.')

        if xmlObj.tag == "FRMJob":
            jobDescription = xmlObj
        else:
            jobDescription = xmlObj.xpath('FRMJob')
            if len(jobDescription) == 0:
                raise Exception("This XML is not a FRMJob.")
            jobDescription = jobDescription[0]

        from pytom.basic.structures import ParticleList, Reference, Mask, SampleInformation, MultiSymmetries

        pl = ParticleList('.')
        particleList_element = jobDescription.xpath('ParticleList')
        if len(particleList_element) > 0:
            pl.fromXML(particleList_element[0])
        else:
            list_elements = jobDescription.xpath('ParticleListLocation')
            for e in list_elements:
                sub_pl = ParticleList()
                sub_pl.fromXMLFile(e.get('Path'))
                pl += sub_pl
        self.particleList = pl

        r = jobDescription.xpath('Reference')[0]
        self.reference = Reference('')
        self.reference.fromXML(r)

        m = jobDescription.xpath('Mask')[0]
        self.mask = Mask('')
        self.mask.fromXML(m)

        try:
            si = jobDescription.xpath('SampleInformation')[0]
            self.sampleInformation = SampleInformation()
            self.sampleInformation.fromXML(si)
        except:
            self.sampleInformation = SampleInformation()

        try:
            syms = jobDescription.xpath('MultiSymmetries')[0]
            self.symmetries = MultiSymmetries()
            self.symmetries.fromXML(syms)
        except:
            self.symmetries = MultiSymmetries()

        self.peak_offset = int(jobDescription.get('PeakOffset'))
        self.bw_range = [
            int(i)
            for i in jobDescription.get('BandwidthRange')[1:-1].split(',')
        ]
        self.freq = int(jobDescription.get('Frequency'))
        self.destination = jobDescription.get('Destination')
        self.max_iter = int(jobDescription.get('MaxIterations'))
        self.r_score = jobDescription.get('RScore') == 'True'
        self.weighting = jobDescription.get('WeightedAverage') == 'True'
        self.bfactor = jobDescription.get('BFactor')
        self.binning = int(jobDescription.get('binning'))
        if jobDescription.get('AdaptiveResolution'):
            adaptive_resolution = jobDescription.get('AdaptiveResolution')
            if adaptive_resolution == '+1':
                self.adaptive_res = False  # always increase by 1
            else:
                self.adaptive_res = float(adaptive_resolution)
        else:
            self.adaptive_res = 0.0  # default, if not specified
        if jobDescription.get('FSC'):
            self.fsc_criterion = float(jobDescription.get('FSC'))
        else:
            self.fsc_criterion = 0.5  # default value

        # for the constraint
        try:
            from sh_alignment.constrained_frm import AngularConstraint
            con = jobDescription.xpath('AngularConstraint')
            if len(con) != 0:
                ac = AngularConstraint()
                c = ac.fromXML(con[0])
                self.constraint = c
            else:
                self.constraint = None
        except:
            self.constraint = None
Пример #5
0
class ReconstructionMessage(Message):
    """
    ReconstructionMessage:
    """

    def __init__(self,sender='',receiver='',particleList='',projectionList='',cubeSize='', binning=1, applyWeighting = False):
        
        super(ReconstructionMessage,self).__init__(sender,receiver)
        
        self._particleList   = particleList
        self._projectionList = projectionList
        self._cubeSize       = cubeSize
        self._binning        = binning
        self._applyWeighting = applyWeighting
                
    def toXML(self):
        from lxml import etree
        
        message_element = etree.Element('ReconstructionMessage',Sender = str(self._sender), Recipient = str(self._recipient), Timestamp = str(self._timestamp))
                                
        message_element.append(self._particleList.toXML())
        message_element.append(self._projectionList.toXML())
        message_element.set('CubeSize',str(self._cubeSize))
        message_element.set('Binning',str(self._binning))
        message_element.set('ApplyWeighting',str(self._applyWeighting))
        
        return message_element
                

    def fromXML(self,xmlObj):
        from lxml.etree import _Element
        from pytom.basic.structures import ParticleList
        from pytom.reconstruction.reconstructionStructures import ProjectionList
        
        if xmlObj.__class__ != _Element :
            raise Exception('Is not a lxml.etree._Element! You must provide a valid XMLobject.')
                
        if xmlObj.tag == 'ReconstructionMessage':
            message_element = xmlObj
        else:
            Exception('Is not a ReconstructionMessage! You must provide a valid ReconstructionMessage object.')
                    
        
        self._sender = message_element.get('Sender')
        self._recipient = message_element.get('Recipient')
        self._timestamp = message_element.get('Timestamp')
        self._cubeSize = int(message_element.get('CubeSize'))
        self._binning = float(message_element.get('Binning'))
        self._applyWeighting = bool(message_element.get('ApplyWeighting'))        
        
        self._particleList = ParticleList('.')
        particleListXML = message_element.xpath('ParticleList')[0]
        self._particleList.fromXML(particleListXML)
               
        self._projectionList = ProjectionList()
        projectionListXML = message_element.xpath('ProjectionList')[0]
        self._projectionList.fromXML(projectionListXML)
        
    
    def getProjectionList(self):
        
        return self._projectionList
    
    def getParticleList(self):
        
        return self._particleList
        
    def getCubeSize(self):
        
        return self._cubeSize
    
    def getBinning(self):
        
        return self._binning
    
    def getApplyWeighting(self):
        
        return self._applyWeighting  
Пример #6
0
class CorrelationVectorJob(PyTomClass):
    """
    CorrelationVectorJob: All settings needed for a correlation vector job. Explore class for more info.
    """
    
    def __init__(self,particle=None,particleList=None,mask=None,particleIndex = None,applyWedge = True,binningFactor=0,lowestFrequency=-1,highestFrequency=-1):
        """
        __init__:
        @param particle: Particle
        @type particle: pytom.alignment.structures.Particle
        @param particleList: ParticleList of all particles will be correlated with self._particle
        @type particleList: pytom.alignment.structures.ParticleList
        @param mask: Mask used for correlation
        @type mask: str
        @param applyWedge: Apply wedge during correlation. True by default, disable for rotation classification.
        @type applyWedge: Bool  
        @param binningFactor: Binning factor accroding to libtomc definition. 0 by default.
        @type binningFactor: unsigned int
        @param lowestFrequency: Lowest frequency for bandpass in nyquist
        @type lowestFrequency: float
        @param highestFrequency: Highest frequency for bandpass in nyquist
        @type highestFrequency: float  
        """
        from pytom.basic.structures import Particle,ParticleList,Mask
        
        if particle and particle.__class__ != Particle:
            raise ParameterError('You must provide a Particle object.')
        
        if particleList and particleList.__class__ != ParticleList:
            raise ParameterError('You must provide a ParticleList object.')
        
        self._particle = particle
        self._particleList = particleList
        
        if not mask:
            mask = Mask()
        elif mask.__class__ == str:
            mask = Mask(mask)
        elif mask.__class__ != Mask:
            from pytom.basic.exceptions import ParameterError
            raise ParameterError('Mask must be a string or Mask object!')
        
        self._mask = mask
        self._particleIndex = particleIndex
        self._applyWedge = applyWedge
        self._binningFactor = binningFactor
        self._lowestFrequency = lowestFrequency
        self._highestFrequency = highestFrequency
        
    def getMask(self):
        return self._mask
    
    def getParticle(self):
        return self._particle
    
    def getParticleList(self):
        return self._particleList
    
    def getParticleIndex(self):
        return self._particleIndex
    
    def getApplyWedge(self):
        return self._applyWedge
    
    def getBinning(self):
        return self._binningFactor
    
    def getLowestFrequency(self):
        return self._lowestFrequency
    
    def getHighestFrequency(self):
        return self._highestFrequency
    
    def toXML(self):
        """
        toXML : Compiles a XML object from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        
        from lxml import etree
        
        jobElement = etree.Element('CorrelationVectorJob',ParticleIndex = self._particleIndex.__str__(),ApplyWedge=self._applyWedge.__str__(),Binning = self._binningFactor.__str__(),LowestFrequency = str(self._lowestFrequency),HighestFrequency = str(self._highestFrequency))
        
        jobElement.append(self._particle.toXML())
        jobElement.append(self._particleList.toXML())
        jobElement.append(self._mask.toXML())
        
        return jobElement
        
    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object  
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe 
        """
        from lxml.etree import _Element
        
        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationVectorJob object.')
        
        
        from pytom.basic.structures import Particle,ParticleList,Mask
        
        particleObject = xmlObj.xpath('Particle')
        self._particle = Particle('.')
        self._particle.fromXML(particleObject[0])
        
        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0])
    
        maskObject = xmlObj.xpath('Mask')[0]
        self._mask = Mask()
        self._mask.fromXML(maskObject)
        
        self._particleIndex = xmlObj.get('ParticleIndex')
        self._applyWedge = xmlObj.get('ApplyWedge') == 'True'
        self._binningFactor = float(xmlObj.get('Binning'))
        
        self._lowestFrequency = float(xmlObj.get('LowestFrequency'))
        self._highestFrequency = float(xmlObj.get('HighestFrequency'))
Пример #7
0
class CorrelationVector(PyTomClass):
    """
    CorrelationVector: Stores a vector of correlation values of one particle with many others from particle list
    @todo: Add unittest
    """
    
    def __init__(self,particle=None,particleList=None,particleIndex=None):
        self._correlations = []
        self._particle = particle
        self._particleList = particleList
        self._particleIndex = particleIndex
        
    def append(self,value):
        self._correlations.append(value)
    
    def getParticleIndex(self):
        return self._particleIndex
    
    def __len__(self):
        return len(self._correlations)
    
    def __getitem__(self,key):
        """
        """
        if isinstance(key, int):
            if key < len(self):
                return self._correlations[key]
            else:
                raise IndexError('Index out of range.')
        else:
            assert False
            
    def toXML(self): 
        """
        toXML : Compiles a XML file from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """        
        from lxml import etree

        vectorElement = etree.Element("CorrelationVector",ParticleIndex = self._particleIndex.__str__())
        
        vectorElement.append(self._particle.toXML())
        vectorElement.append(self._particleList.toXML())
        
        for i in range(len(self._correlations)):
            
            valueElement = etree.Element("Correlation",Index=i.__str__(),Value=self._correlations[i].__str__())
            
            vectorElement.append(valueElement)

        return vectorElement

    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object  
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe 
        """
        from lxml.etree import _Element,tostring
        
        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationVector object.')
        
        from pytom.basic.structures import Particle,ParticleList
        
        self._particleIndex = int(xmlObj.get('ParticleIndex'))
        
        particleObject = xmlObj.xpath('Particle')
        self._particle = Particle('.')
        self._particle.fromXML(particleObject[0])
        
        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0])
        
        values = xmlObj.xpath('Correlation')
        
        self._correlations = [0  for _ in range(len(values))]
        
        for v in values:
            
            index = int(v.get('Index'))
            self._correlations[index] = float(v.get('Value'))
Пример #8
0
class CorrelationMatrixJob(PyTomClass):
    """
    CorrelationVectorJob: Represents all settings for a correlation matrix job. Explore the class for further information
    """
    
    def __init__(self,particleList=None,mask='',resultMatrixName='',applyWedge = True,binningFactor=0,lowestFrequency=-1,highestFrequency=-1):
        """
        __init__:
        @param particleList: ParticleList of all particles that will be correlated 
        @type particleList: L{pytom.basic.structures.ParticleList}
        @param mask: Mask used for correlation
        @type mask: str or L{pytom.basic.structures.Mask}
        @param resultMatrixName: Result filename
        @type resultMatrixName: str  
        @param applyWedge: Apply wedge weighting if available?
        @type applyWedge: boolean, False by default  
        @param binningFactor: Binning factor accroding to libtomc definition. 0 by default.
        @type binningFactor: unsigned int
        @param lowestFrequency: Lowest frequency for bandpass in nyquist
        @type lowestFrequency: float
        @param highestFrequency: Highest frequency for bandpass in nyquist
        @type highestFrequency: float
        """
        from pytom.basic.structures import ParticleList,Mask
        from pytom.tools.files import checkFileExists
        
        if not particleList:
            particleList = ParticleList('/')
        elif particleList.__class__ != ParticleList:
            raise ParameterError('You must provide a ParticleList object!')
        
        self._particleList = particleList
        
        if mask.__class__ == str:
            mask = Mask(mask)
        elif mask.__class__ != Mask:
            raise ParameterError('Mask must be a string or Mask object!')
        
        self._mask = mask
        self._resultMatrixName = resultMatrixName
        self._applyWedge = applyWedge
        self._binningFactor = binningFactor
        self._lowestFrequency = lowestFrequency
        self._highestFrequency = highestFrequency
        
    def getParticleList(self):    
        return self._particleList
    
    def getMask(self):
        return self._mask
    
    def getResultMatrixName(self):
        return self._resultMatrixName
    
    def getApplyWedge(self):
        return self._applyWedge
    
    def getBinning(self):
        return self._binningFactor
    
    def getLowestFrequency(self):
        return self._lowestFrequency
    
    def getHighestFrequency(self):
        return self._highestFrequency
    
    def toXML(self):
        """
        toXML : Compiles a XML object from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml import etree
        
        jobElement = etree.Element('CorrelationMatrixJob',ResultMatrixName = self._resultMatrixName, ApplyWedge=self._applyWedge.__str__(),Binning=self._binningFactor.__str__(),LowestFrequency = str(self._lowestFrequency),HighestFrequency = str(self._highestFrequency))
        
        jobElement.append(self._particleList.toXML())
        
        jobElement.append(self._mask.toXML())
        
        return jobElement
        
    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object  
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe 
        """
        from lxml.etree import _Element
        
        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationMatrixJob object.')
        
        
        from pytom.basic.structures import ParticleList,Mask
        
        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0]) 
        
        maskObject = xmlObj.xpath('Mask')[0]
        self._mask = Mask()
        self._mask.fromXML(maskObject)
        
        self._resultMatrixName = xmlObj.get('ResultMatrixName')
        self._applyWedge = xmlObj.get('ApplyWedge') == 'True'
        self._binningFactor = float(xmlObj.get('Binning'))
        
        self._lowestFrequency = float(xmlObj.get('LowestFrequency'))
        self._highestFrequency = float(xmlObj.get('HighestFrequency'))
        
    def toHTMLFile(self,filename):
        """
        toHTMLFile: Overrides parent method and stores CorrelationMatrixJob to HMTL
        @param filename: HTML filename
        """
        from lxml import etree
        import io
        from pytom.tools.files import getPytomPath,readStringFile
        
        pytomPath = getPytomPath()
        
        xsltString = readStringFile(pytomPath + '/xslt/CorrelationMatrix.xsl')
        
        xsltStringIO = io.StringIO(xsltString)
        
        selfHTML = self.xsltTransform(xsltStringIO)
        
        htmlString = etree.tostring(selfHTML,pretty_print=True)

        file = open(filename, "w")

        file.write(htmlString)
    
        file.close()
        
Пример #9
0
class ExpectationJob(PyTomClass):
    def __init__(self, particleList=None, newAverageName=''):
        """
        @param particleList: particle list
        @type particleList: L{pytom.basic.structures.ParticleList}
        @param newAverageName: name of output average
        @type newAverageName: L{str}
        """
        from pytom.basic.structures import ParticleList

        self._particleList = particleList or ParticleList('/', [])
        self._newAverageName = newAverageName

    def appendMaximisationResult(self, result):
        """
        @param result: maximization result
        @type result: L{pytom.alignment.structures.MaximisationResult}
        """
        from pytom.alignment.structures import MaximisationResult

        if not result.__class__ == MaximisationResult:
            raise RuntimeError(
                'The object you are appending must be a MaximisationResult!')

        self._particleList.append(result.toParticle())

    def appendParticle(self, particle):
        """
        @param particle: particle
        @type particle: L{pytom.basic.structures.Particle}
        """
        self._particleList.append(particle)

    def setParticleList(self, particleList):
        """
        @param particleList: particle list
        @type particleList: L{pytom.basic.structures.ParticleList}
        """
        self._particleList = particleList

    def getParticleList(self):
        return self._particleList

    def getNewAverageName(self):
        return self._newAverageName

    def fromXML(self, xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object
        @type xmlObj: L{lxml.etree._Element}

        @author: Thomas Hrabe 
        """
        from lxml import etree
        from lxml.etree import _Element
        from pytom.basic.structures import ParticleList

        if xmlObj.__class__ != _Element:
            from pytom.basic.exceptions import ParameterError
            raise ParameterError(
                'Is not a lxml.etree._Element! You must provide a valid XML object.'
            )

        if not xmlObj.tag == 'ExpectationJob':
            jobElement = xmlObj.xpath('ExpectationJob')

            if len(jobElement) == 0:
                from pytom.basic.exceptions import ParameterError
                raise ParameterError(
                    'You must provide a valid XML-ExpectationJob object.')
            else:
                jobElement = jobElement[0]
        else:
            jobElement = xmlObj

        self._newAverageName = jobElement.get('AverageName').__str__()

        particleListXML = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        if len(particleListXML) > 0:
            self._particleList.fromXML(particleListXML[0])

    def toXML(self):
        """
        toXML : Compiles a XML file from job object
        @author: Thomas Hrabe
        """
        from lxml import etree

        expJob = etree.Element("ExpectationJob",
                               AverageName=self._newAverageName)
        expJob.append(self._particleList.toXML())
        return expJob