Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 91
CRAP
0.00% covered (danger)
0.00%
0 / 739
MzIdentMlReader1r1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 91
46872
0.00% covered (danger)
0.00%
0 / 739
 __construct
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getAdditionalSearchParams
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 12
 getAffiliation
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getAmigiousResidue
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getAnalysisCollection
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getAnalysisData
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getAnalysisParams
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getAnalysisProtocolCollection
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 12
 getAnalysisSampleCollection
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getAnalysisSoftwareList
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 7
 getAnalysisSoftware
0.00% covered (danger)
0.00%
0 / 1
30
0.00% covered (danger)
0.00%
0 / 17
 getAuditCollection
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getBibliographicReference
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getContactRole
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getCustomisations
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getDbSequence
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 24
 parseDbSequenceParam
0.00% covered (danger)
0.00%
0 / 1
90
0.00% covered (danger)
0.00%
0 / 32
 getDataCollection
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 6
 getDatabaseFilters
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getDatabaseName
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getDatabaseTranslation
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getEnzyme
0.00% covered (danger)
0.00%
0 / 1
110
0.00% covered (danger)
0.00%
0 / 34
 getEnzymeName
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 6
 getEnzymes
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 12
 getExclude
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getExternalFormatDocumentation
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getFileFormat
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getFilter
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getFilterType
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getFragmentArray
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getFragmentTolerance
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getFragmentation
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getFragmentationTable
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getInclude
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getInputSpectra
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getInputSpectrumIdentifications
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getInputs
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 14
 getIonType
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getMassTable
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getMeasure
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getModification
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 28
 getModificationParams
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 7
 getOrganization
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getParent
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getParentTolerance
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getPeptide
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getPeptideEvidence
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 14
 getPeptideEvidenceRef
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getPeptideHypothesis
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 10
 getPeptideSequence
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getPerson
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getProteinAmbiguityGroup
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getProteinDetection
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getProteinDetectionHypothesis
0.00% covered (danger)
0.00%
0 / 1
30
0.00% covered (danger)
0.00%
0 / 23
 getProteinDetectionList
0.00% covered (danger)
0.00%
0 / 1
30
0.00% covered (danger)
0.00%
0 / 19
 getProteinDetectionProtocol
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 9
 getProvider
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getResidue
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getRole
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSample
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSearchDatabase
0.00% covered (danger)
0.00%
0 / 1
156
0.00% covered (danger)
0.00%
0 / 47
 getSearchDatabaseRef
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSearchModification
0.00% covered (danger)
0.00%
0 / 1
56
0.00% covered (danger)
0.00%
0 / 29
 getSearchType
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSeq
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getSequenceCollection
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 15
 getSequenceCollectionPeptides
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 8
 getSequenceCollectionProteins
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 8
 getSiteRegexp
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSoftwareName
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 9
 getSourceFile
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSpecifityRules
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 18
 getSpectraData
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 10
 getSpectrumIdFormat
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 4
 getSpectrumIdentification
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSpectrumIdentificationItem
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 35
 parsePeptideEvidenceCv
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 30
 getSpectrumIdentificationItemRef
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 getSpectrumIdentificationList
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getSpectrumIdentificationProtocol
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 23
 getSpectrumIdentificationResult
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 28
 getSubSample
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSubstitutionModification
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getThreshold
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 7
 getTolerance
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 17
 getTranslationTable
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getCv
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getCvList
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getProteinEntryType
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 14
 isFilterMatch
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 6
 setRankFilter
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
<?php
/**
 * Copyright 2019 University of Liverpool
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
namespace pgb_liv\php_ms\Reader;
use pgb_liv\php_ms\Core\Modification;
use pgb_liv\php_ms\Core\Tolerance;
use pgb_liv\php_ms\Core\Peptide;
use pgb_liv\php_ms\Core\Protein;
use pgb_liv\php_ms\Core\Identification;
use pgb_liv\php_ms\Core\Spectra\PrecursorIon;
use pgb_liv\php_ms\Core\Chromosome;
use pgb_liv\php_ms\Core\Entry\ProteinEntry;
use pgb_liv\php_ms\Core\Entry\ChromosomeProteinEntry;
use pgb_liv\php_ms\Reader\HupoPsi\PsiXmlTrait;
use pgb_liv\php_ms\Reader\HupoPsi\PsiVerb;
/**
 *
 * @author Andrew Collins
 */
class MzIdentMlReader1r1 implements MzIdentMlReader1Interface
{
    use PsiXmlTrait;
    /**
     * Map of Peptide ID => Peptide object from Peptide list
     *
     * @var Peptide[]
     */
    private $peptides = array();
    /**
     * Map of Protin ID => Protein object from DbSequence list
     *
     * @var Protein[]
     */
    private $proteins = array();
    private $evidence = array();
    private $inputs;
    /**
     * Filters to apply
     *
     * @var array
     */
    private $filter = array();
    const PROTOCOL_SPECTRUM = 'spectrum';
    const PROTOCOL_PROTEIN = 'protein';
    protected $xmlReader;
    public function __construct($filePath)
    {
        $this->xmlReader = new \SimpleXMLElement($filePath, null, true);
    }
    protected function getAdditionalSearchParams($xml)
    {
        $additional = array();
        $additional['cv'] = array();
        $additional['user'] = array();
        foreach ($xml->cvParam as $cvParam) {
            $additional['cv'][] = $this->getCvParam($cvParam);
        }
        foreach ($xml->userParam as $userParam) {
            $additional['user'][(string) $userParam->attributes()->name] = (string) $userParam->attributes()->value;
        }
        return $additional;
    }
    private function getAffiliation()
    {
        // TODO: Implement
    }
    private function getAmigiousResidue()
    {
        // TODO: Implement
    }
    public function getAnalysisCollection()
    {
        // TODO: Implement
    }
    
    /**
     *
     * @return PrecursorIon[]
     */
    public function getAnalysisData()
    {
        // TODO: This should link to getProteinDetectionList
        return $this->getSpectrumIdentificationList();
    }
    private function getAnalysisParams()
    {
        // TODO: Implement
    }
    public function getAnalysisProtocolCollection()
    {
        $protocols = array();
        $protocols[self::PROTOCOL_SPECTRUM] = array();
        foreach ($this->xmlReader->AnalysisProtocolCollection->SpectrumIdentificationProtocol as $xml) {
            $protocols[self::PROTOCOL_SPECTRUM][$this->getAttributeId($xml)] = $this->getSpectrumIdentificationProtocol(
                $xml);
        }
        if (isset($this->xmlReader->AnalysisProtocolCollection->ProteinDetectionProtocol)) {
            $protocols[self::PROTOCOL_PROTEIN] = $this->getProteinDetectionProtocol();
        }
        return $protocols;
    }
    private function getAnalysisSampleCollection()
    {
        // TODO: Implement
    }
    public function getAnalysisSoftwareList()
    {
        $softwareList = array();
        foreach ($this->xmlReader->AnalysisSoftwareList->AnalysisSoftware as $analysisSoftware) {
            $softwareList[$this->getAttributeId($analysisSoftware)] = $this->getAnalysisSoftware($analysisSoftware);
        }
        return $softwareList;
    }
    protected function getAnalysisSoftware(\SimpleXMLElement $xml)
    {
        $software = array();
        if (isset($xml->attributes()->version)) {
            $software['version'] = (string) $xml->attributes()->version;
        }
        if (isset($xml->attributes()->name)) {
            $software['name'] = (string) $xml->attributes()->name;
        } elseif (isset($xml->SoftwareName->cvParam)) {
            $cvParam = $this->getCvParam($xml->SoftwareName->cvParam);
            $software['name'] = $cvParam[PsiVerb::CV_NAME];
        }
        if (isset($xml->attributes()->uri)) {
            $software['uri'] = (string) $xml->attributes()->uri;
        }
        $software['product_name'] = $software['name'];
        return $software;
    }
    private function getAuditCollection()
    {
        // TODO: Implement
    }
    private function getBibliographicReference()
    {
        // TODO: Implement
    }
    private function getContactRole()
    {
        // TODO: Implement
    }
    private function getCustomisations()
    {
        // TODO: Implement
    }
    protected function getDbSequence(\SimpleXMLElement $xml)
    {
        $protein = new Protein();
        $protein->setIdentifier((string) $xml->attributes()->accession);
        foreach ($xml->cvParam as $xmlCvParam) {
            $cvParam = $this->getCvParam($xmlCvParam);
            $this->parseDbSequenceParam($cvParam, $protein);
        }
        if (isset($xml->Seq)) {
            $sequence = $this->getSeq($xml->Seq);
            if (strlen($sequence) > 0) {
                $protein->setSequence($sequence);
            }
        }
        $databaseRef = (string) $xml->attributes()->searchDatabase_ref;
        $databases = $this->getInputs()['SearchDatabase'];
        if ($databases[$databaseRef]['isDecoy'] == 1) {
            $protein->setIsDecoy(true);
        } elseif ($databases[$databaseRef]['isDecoy'] == 2) {
            $isDecoy = preg_match('/' . $databases[$databaseRef]['decoyRules']['regExp'] . '/',
                $protein->getIdentifier());
            $protein->setIsDecoy($isDecoy > 0);
        }
        return $protein;
    }
    protected function parseDbSequenceParam(array $cvParam, Protein $protein)
    {
        switch ($cvParam[PsiVerb::CV_ACCESSION]) {
            case 'MS:1001088':
                if (isset($cvParam[PsiVerb::CV_VALUE])) {
                    $protein->setDescription($cvParam[PsiVerb::CV_VALUE]);
                }
                break;
            case 'MS:1002637':
                // Chromosome Name
                $chromosome = $protein->getChromosome();
                if (is_null($chromosome)) {
                    $protein->setChromosome(new Chromosome());
                }
                $protein->getChromosome()->setName($cvParam[PsiVerb::CV_VALUE]);
                break;
            case 'MS:1002638':
                // chromosome strand
                $chromosome = $protein->getChromosome();
                if (is_null($chromosome)) {
                    $protein->setChromosome(new Chromosome());
                }
                $protein->getChromosome()->setStrand($cvParam[PsiVerb::CV_VALUE]);
                break;
            case 'MS:1002644':
                // genome reference version
                $chromosome = $protein->getChromosome();
                if (is_null($chromosome)) {
                    $protein->setChromosome(new Chromosome());
                }
                $protein->getChromosome()->setGenomeReferenceVersion($cvParam[PsiVerb::CV_VALUE]);
                break;
            default:
                // Unknown field
                break;
        }
    }
    public function getDataCollection()
    {
        $dataCollection = array();
        $dataCollection['inputs'] = $this->getInputs();
        $dataCollection['analysisData'] = $this->getAnalysisData();
        return $dataCollection;
    }
    private function getDatabaseFilters()
    {
        // TODO: Implement
    }
    private function getDatabaseName()
    {
        // TODO: Implement
    }
    private function getDatabaseTranslation()
    {
        // TODO: Implement
    }
    /**
     * The details of an individual cleavage enzyme should be provided by giving a regular expression or a CV term if a "standard" enzyme cleavage has been
     * performed.
     *
     * @param \SimpleXMLElement $xmlEnzyme
     *            The XML element
     * @return string[]|number[]|boolean[]|NULL[]|string[][]
     */
    private function getEnzyme(\SimpleXMLElement $xmlEnzyme)
    {
        $enzyme = array();
        foreach ($xmlEnzyme->attributes() as $attribute => $value) {
            switch ($attribute) {
                case 'cTermGain':
                    $enzyme['cTermGain'] = (string) $value;
                    break;
                case 'id':
                    $enzyme['id'] = (string) $value;
                    break;
                case 'minDistance':
                    $enzyme['minDistance'] = (int) $value;
                    break;
                case 'missedCleavages':
                    $enzyme['missedCleavages'] = (int) $value;
                    break;
                case 'nTermGain':
                    $enzyme['nTermGain'] = (string) $value;
                    break;
                case 'name':
                    $enzyme['name'] = (string) $value;
                    break;
                case 'semiSpecific':
                    $enzyme['semiSpecific'] = (string) $value == 'true';
                    break;
                default:
                    // Unknown element
                    break;
            }
        }
        if (isset($xmlEnzyme->EnzymeName)) {
            $enzyme['EnzymeName'] = $this->getEnzymeName($xmlEnzyme->EnzymeName);
        }
        return $enzyme;
    }
    private function getEnzymeName(\SimpleXMLElement $enzymeName)
    {
        if (isset($enzymeName->cvParam)) {
            return $this->getCvParam($enzymeName->cvParam);
        }
        return null;
    }
    /**
     * The list of enzymes used in experiment
     *
     * @param \SimpleXMLElement $xml
     * @return array
     */
    protected function getEnzymes(\SimpleXMLElement $xml)
    {
        $enzymes = array();
        foreach ($xml->Enzyme as $xmlEnzyme) {
            $enzyme = $this->getEnzyme($xmlEnzyme);
            if (isset($enzyme['id'])) {
                $enzymes[$enzyme['id']] = $enzyme;
                continue;
            }
            $enzymes[] = $enzyme;
        }
        return $enzymes;
    }
    private function getExclude()
    {
        // TODO: Implement
    }
    private function getExternalFormatDocumentation()
    {
        // TODO: Implement
    }
    /**
     * The format of the ExternalData file, for example "tiff" for image files.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     */
    private function getFileFormat(\SimpleXMLElement $xml)
    {
        $formats = array();
        foreach ($xml->cvParam as $xmlCvParam) {
            $cvParam = $this->getCvParam($xmlCvParam);
            $formats[] = $cvParam[PsiVerb::CV_ACCESSION];
        }
        return $formats;
    }
    private function getFilter()
    {
        // TODO: Implement
    }
    private function getFilterType()
    {
        // TODO: Implement
    }
    private function getFragmentArray()
    {
        // TODO: Implement
    }
    private function getFragmentTolerance(\SimpleXMLElement $xml)
    {
        return $this->getTolerance($xml);
    }
    private function getFragmentation()
    {
        // TODO: Implement
    }
    private function getFragmentationTable()
    {
        // TODO: Implement
    }
    private function getInclude()
    {
        // TODO: Implement
    }
    private function getInputSpectra()
    {
        // TODO: Implement
    }
    private function getInputSpectrumIdentifications()
    {
        // TODO: Implement
    }
    public function getInputs()
    {
        if (is_null($this->inputs)) {
            $this->inputs = array();
            $this->inputs['SearchDatabase'] = array();
            foreach ($this->xmlReader->DataCollection->Inputs->SearchDatabase as $xml) {
                $this->inputs['SearchDatabase'][$this->getAttributeId($xml)] = $this->getSearchDatabase($xml);
            }
            $this->inputs['SpectraData'] = array();
            foreach ($this->xmlReader->DataCollection->Inputs->SpectraData as $xml) {
                $this->inputs['SpectraData'][$this->getAttributeId($xml)] = $this->getSpectraData($xml);
            }
        }
        return $this->inputs;
    }
    private function getIonType()
    {
        // TODO: Implement
    }
    private function getMassTable()
    {
        // TODO: Implement
    }
    private function getMeasure()
    {
        // TODO: Implement
    }
    protected function getModification(\SimpleXMLElement $xml)
    {
        $attributes = $xml->attributes();
        $modification = new Modification();
        if (isset($attributes->avgMassDelta)) {
            $modification->setAverageMass((float) $attributes->avgMassDelta);
        }
        if (isset($attributes->location)) {
            $modification->setLocation((int) $attributes->location);
        }
        if (isset($attributes->monoisotopicMassDelta)) {
            $modification->setMonoisotopicMass((float) $attributes->monoisotopicMassDelta);
        }
        if (isset($attributes->residues)) {
            $residues = (string) $attributes->residues;
            if (strlen($residues) > 0) {
                $modification->setResidues(str_split($residues));
            }
        }
        $cvParam = $this->getCvParam($xml->cvParam);
        if ($cvParam[PsiVerb::CV_ACCESSION] == 'MS:1001460') {
            // Unknown modification
            $name = isset($cvParam[PsiVerb::CV_VALUE]) ? $cvParam[PsiVerb::CV_VALUE] : 'Unknown Modification';
            $modification->setName($name);
        } else {
            // Known modification
            $modification->setAccession($cvParam[PsiVerb::CV_ACCESSION]);
            $modification->setName($cvParam[PsiVerb::CV_NAME]);
        }
        return $modification;
    }
    protected function getModificationParams(\SimpleXMLElement $xml)
    {
        $modifications = array();
        foreach ($xml->SearchModification as $xmlModification) {
            $modifications[] = $this->getSearchModification($xmlModification);
        }
        return $modifications;
    }
    private function getOrganization()
    {
        // TODO: Implement
    }
    private function getParent()
    {
        // TODO: Implement
    }
    protected function getParentTolerance(\SimpleXMLElement $xml)
    {
        return $this->getTolerance($xml);
    }
    /**
     *
     * @param \SimpleXMLElement $xml
     * @return Peptide
     */
    protected function getPeptide(\SimpleXMLElement $xml)
    {
        $peptide = new Peptide();
        $peptide->setSequence($this->getPeptideSequence($xml->PeptideSequence));
        foreach ($xml->Modification as $xmlModification) {
            $peptide->addModification($this->getModification($xmlModification));
        }
        return $peptide;
    }
    /**
     *
     * @param \SimpleXMLElement $xml
     * @param Peptide[] $peptides
     * @param Protein[] $proteins
     * @return ProteinEntry
     */
    private function getPeptideEvidence(\SimpleXMLElement $xml)
    {
        $peptideEvidence = array();
        $peptideEvidence['peptide'] = (string) $xml->attributes()->peptide_ref;
        $peptideEvidence['protein'] = (string) $xml->attributes()->dBSequence_ref;
        $peptideEvidence['start'] = (int) $xml->attributes()->start;
        $peptideEvidence['end'] = (int) $xml->attributes()->end;
        $peptideEvidence['is_decoy'] = (string) $xml->attributes()->isDecoy == 'true';
        $peptideEvidence['cv'] = array();
        foreach ($xml->cvParam as $xmlCvParam) {
            $cvParam = $this->getCvParam($xmlCvParam);
            $peptideEvidence['cv'][] = $cvParam;
        }
        return $peptideEvidence;
    }
    /**
     * Reference to the PeptideEvidence element identified.
     * If a specific sequence can be assigned to multiple proteins and or positions in a protein all possible PeptideEvidence elements should be referenced
     * here.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     * @return ProteinEntry
     */
    private function getPeptideEvidenceRef(\SimpleXMLElement $xml)
    {
        return (string) $xml->attributes()->peptideEvidence_ref;
    }
    /**
     * Peptide evidence on which this ProteinHypothesis is based by reference to a PeptideEvidence element.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     */
    private function getPeptideHypothesis(\SimpleXMLElement $xml)
    {
        $hypothesis = array();
        $ref = (string) $xml->attributes()->peptideEvidence_ref;
        $hypothesis['peptide'] = $ref;
        $hypothesis['spectra'] = array();
        // TODO: Nothing we can currently do with this data - yet
        foreach ($xml->SpectrumIdentificationItemRef as $spectrumIdentificationItemRef) {
            $hypothesis['spectra'][] = $this->getSpectrumIdentificationItemRef($spectrumIdentificationItemRef);
        }
        return $hypothesis;
    }
    protected function getPeptideSequence(\SimpleXMLElement $xml)
    {
        return (string) $xml;
    }
    private function getPerson()
    {
        // TODO: Implement
    }
    /**
     * A set of logically related results from a protein detection, for example to represent conflicting assignments of peptides to proteins.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     */
    private function getProteinAmbiguityGroup(\SimpleXMLElement $xml)
    {
        $hypos = array();
        foreach ($xml->ProteinDetectionHypothesis as $proteinDetectionHypothesis) {
            $hypo = $this->getProteinDetectionHypothesis($proteinDetectionHypothesis);
            $hypos[$hypo['id']] = $hypo;
        }
        return $hypos;
    }
    private function getProteinDetection()
    {
        // TODO: Implement
    }
    /**
     * A single result of the ProteinDetection analysis (i.e.
     * a protein).
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     */
    private function getProteinDetectionHypothesis(\SimpleXMLElement $xml)
    {
        $hypothesis = array();
        $hypothesis['id'] = $this->getAttributeId($xml);
        $hypothesis['passThreshold'] = ((string) $xml->attributes()->passThreshold) == 'true';
        if (isset($xml->attributes()->name)) {
            $hypothesis['name'] = (string) $xml->attributes()->name;
        }
        if (isset($xml->attributes()->dBSequence_ref)) {
            $ref = (string) $xml->attributes()->dBSequence_ref;
            $hypothesis['protein'] = $ref;
        }
        $hypoPeptides = array();
        foreach ($xml->PeptideHypothesis as $peptideHypothesis) {
            $hypoPeptides[] = $this->getPeptideHypothesis($peptideHypothesis);
        }
        $cvParams = array();
        foreach ($xml->cvParam as $cvParam) {
            $cvParams[] = $this->getCvParam($cvParam);
        }
        $hypothesis['peptides'] = $hypoPeptides;
        $hypothesis['cvParam'] = $cvParams;
        return $hypothesis;
    }
    /**
     * The protein list resulting from a protein detection process.
     */
    public function getProteinDetectionList()
    {
        $this->getSequenceCollection();
        $groups = array();
        if (! isset($this->xmlReader->DataCollection->AnalysisData->ProteinDetectionList->ProteinAmbiguityGroup)) {
            return null;
        }
        foreach ($this->xmlReader->DataCollection->AnalysisData->ProteinDetectionList->ProteinAmbiguityGroup as $proteinAmbiguityGroup) {
            $group = $this->getProteinAmbiguityGroup($proteinAmbiguityGroup);
            $groupId = $this->getAttributeId($proteinAmbiguityGroup);
            // Reprocess each group to change refs to element
            foreach ($group as $id => $value) {
                $group[$id]['protein'] = $this->proteins[$value['protein']];
                foreach ($value['peptides'] as $pepId => $peptide) {
                    $group[$id]['peptides'][$pepId] = $this->peptides[$this->evidence[$peptide['peptide']]['peptide']];
                }
            }
            $groups[$groupId] = $group;
        }
        return $groups;
    }
    public function getProteinDetectionProtocol()
    {
        $xml = $this->xmlReader->AnalysisProtocolCollection->ProteinDetectionProtocol;
        $software = $this->getAnalysisSoftwareList();
        $protocol = array();
        $softwareId = (string) $xml->attributes()->analysisSoftware_ref;
        $protocol['software'] = $software[$softwareId];
        $protocol['threshold'] = $this->getThreshold($xml->Threshold);
        return $protocol;
    }
    private function getProvider()
    {
        // TODO: Implement
    }
    private function getResidue()
    {
        // TODO: Implement
    }
    private function getRole()
    {
        // TODO: Implement
    }
    private function getSample()
    {
        // TODO: Implement
    }
    protected function getSearchDatabase(\SimpleXMLElement $xml)
    {
        $database = array();
        // Required
        $database['location'] = (string) $xml->attributes()->location;
        // Optional
        if (isset($xml->attributes()->name)) {
            $database['name'] = (string) $xml->attributes()->name;
        }
        if (isset($xml->attributes()->numDatabaseSequences)) {
            $database['numDatabaseSequences'] = (int) $xml->attributes()->numDatabaseSequences;
        }
        if (isset($xml->attributes()->numResidues)) {
            $database['numResidues'] = (int) $xml->attributes()->numResidues;
        }
        if (isset($xml->attributes()->releaseDate)) {
            $database['releaseDate'] = (string) $xml->attributes()->releaseDate;
        }
        if (isset($xml->attributes()->version)) {
            $database['version'] = (string) $xml->attributes()->version;
        }
        $database['isDecoy'] = 0;
        $database['decoyRules'] = array(
            'isReversed' => false,
            'isMixed' => false,
            'regExp' => null
        );
        foreach ($xml->cvParam as $xmlCvParam) {
            $cvParam = $this->getCvParam($xmlCvParam);
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1001195':
                    $database['decoyRules']['isReversed'] = true;
                    break;
                case 'MS:1001197':
                    $database['decoyRules']['isMixed'] = true;
                    break;
                case 'MS:1001283':
                    $database['decoyRules']['regExp'] = $cvParam[PsiVerb::CV_VALUE];
                    break;
                default:
                    break;
            }
        }
        if ($database['decoyRules']['isMixed']) {
            $database['isDecoy'] = 2;
        } elseif ($database['decoyRules']['isReversed']) {
            $database['isDecoy'] = 1;
        }
        return $database;
    }
    private function getSearchDatabaseRef()
    {
        // TODO: Implement
    }
    protected function getSearchModification(\SimpleXMLElement $xml)
    {
        $modification = new Modification();
        $modification->setLocation((int) $xml->attributes()->location);
        $modification->setMonoisotopicMass((float) $xml->attributes()->massDelta);
        if (isset($xml->SpecificityRules)) {
            $modification->setPosition($this->getSpecifityRules($xml->SpecificityRules));
        }
        $residues = (string) $xml->attributes()->residues;
        // Peaks fix
        if (strlen($residues) === 0) {
            $residues = '.';
        }
        if ($residues != '.') {
            $residues = explode(' ', $residues);
            $modification->setResidues($residues);
        }
        $modType = Modification::TYPE_VARIABLE;
        if ((string) $xml->attributes()->fixedMod == 'true') {
            $modType = Modification::TYPE_FIXED;
        }
        $modification->setType($modType);
        $cvParam = $this->getCvParam($xml->cvParam);
        if ($cvParam[PsiVerb::CV_ACCESSION] == 'MS:1001460') {
            // Unknown modification
            $name = isset($cvParam[PsiVerb::CV_VALUE]) ? $cvParam[PsiVerb::CV_VALUE] : 'Unknown Modification';
            $modification->setName($name);
        } else {
            $modification->setName($cvParam[PsiVerb::CV_NAME]);
        }
        return $modification;
    }
    private function getSearchType()
    {
        // TODO: Implement
    }
    protected function getSeq(\SimpleXMLElement $xml)
    {
        return (string) $xml;
    }
    public function getSequenceCollection()
    {
        $this->getSequenceCollectionProteins();
        $this->getSequenceCollectionPeptides();
        if (count($this->evidence) == 0) {
            foreach ($this->xmlReader->SequenceCollection->PeptideEvidence as $peptideEvidence) {
                $this->evidence[$this->getAttributeId($peptideEvidence)] = $this->getPeptideEvidence($peptideEvidence,
                    $this->peptides, $this->proteins);
            }
        }
        return array(
            'peptides' => $this->peptides,
            'proteins' => $this->proteins,
            'evidence' => $this->evidence
        );
    }
    private function getSequenceCollectionPeptides()
    {
        if (count($this->peptides) == 0) {
            foreach ($this->xmlReader->SequenceCollection->Peptide as $xml) {
                $this->peptides[$this->getAttributeId($xml)] = $this->getPeptide($xml);
            }
        }
        return $this->peptides;
    }
    private function getSequenceCollectionProteins()
    {
        if (count($this->proteins) == 0) {
            foreach ($this->xmlReader->SequenceCollection->DBSequence as $xml) {
                $this->proteins[$this->getAttributeId($xml)] = $this->getDbSequence($xml);
            }
        }
        return $this->proteins;
    }
    private function getSiteRegexp()
    {
        // TODO: Implement
    }
    private function getSoftwareName(\SimpleXMLElement $xml)
    {
        $param = array();
        if (isset($xml->cvParam)) {
            $param = $this->parseCvParam($xml);
        } elseif (isset($xml->userParam)) {
            $param = $this->parseUserParam($xml);
        }
        return $param;
    }
    private function getSourceFile()
    {
        // TODO: Implement
    }
    protected function getSpecifityRules(\SimpleXMLElement $xml)
    {
        foreach ($xml->cvParam as $xmlParam) {
            $cvParam = $this->getCvParam($xmlParam);
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1001189':
                    return Modification::POSITION_NTERM;
                case 'MS:1001190':
                    return Modification::POSITION_CTERM;
                case 'MS:1002057':
                    return Modification::POSITION_PROTEIN_NTERM;
                case 'MS:1002058':
                    return Modification::POSITION_PROTEIN_CTERM;
                default:
                    // TODO: Correctly handle MS:1001875 / MS:1001876
                    break;
            }
        }
        return Modification::POSITION_ANY;
    }
    protected function getSpectraData(\SimpleXMLElement $xml)
    {
        $spectra = array();
        // Required
        $spectra['location'] = (string) $xml->attributes()->location;
        // Optional
        if (isset($xml->attributes()->name)) {
            $spectra['name'] = (string) $xml->attributes()->name;
        }
        $spectra['format']['id'] = $this->getSpectrumIdFormat($xml->SpectrumIDFormat);
        $spectra['format']['file'] = $this->getFileFormat($xml->FileFormat);
        return $spectra;
    }
    /**
     * The format of the spectrum identifier within the source file.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     * @return string
     */
    private function getSpectrumIdFormat(\SimpleXMLElement $xml)
    {
        $cvParam = $this->getCvParam($xml->cvParam);
        return $cvParam[PsiVerb::CV_ACCESSION];
    }
    private function getSpectrumIdentification()
    {
        // TODO: Implement
    }
    /**
     * An identification of a single (poly)peptide, resulting from querying an input spectra, along with the set of confidence values for that identification.
     * PeptideEvidence elements should be given for all mappings of the corresponding Peptide sequence within protein sequences.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     * @return \pgb_liv\php_ms\Core\Spectra\PrecursorIon
     */
    private function getSpectrumIdentificationItem(\SimpleXMLElement $xml)
    {
        $identification = new Identification();
        $identification->setRank((int) $xml->attributes()->rank);
        // peptide_ref will tell use the peptide?
        if (isset($xml->attributes()->peptide_ref)) {
            $peptide = clone $this->peptides[(string) $xml->attributes()->peptide_ref];
        } else {
            $peptide = clone $this->peptides[$this->evidence[(string) $xml->PeptideEvidenceRef->attributes->peptideEvidence_ref]['peptide']];
        }
        $identification->setSequence($peptide);
        foreach ($xml->PeptideEvidenceRef as $peptideEvidenceRef) {
            $ref = $this->getPeptideEvidenceRef($peptideEvidenceRef);
            $peptideEvidence = $this->evidence[$ref];
            $protein = $this->proteins[$peptideEvidence['protein']];
            $peptide->setIsDecoy($peptideEvidence['is_decoy']);
            $entry = $this->getProteinEntryType($peptideEvidence, $protein);
            $entry->setStart($peptideEvidence['start']);
            $entry->setEnd($peptideEvidence['end']);
            $this->parsePeptideEvidenceCv($peptideEvidence['cv'], $entry);
            $peptide->addProteinEntry($entry);
        }
        foreach ($xml->cvParam as $cvParam) {
            $cvParam = $this->getCvParam($cvParam);
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1001363':
                // peptide unique to one protein - not supported
                case 'MS:1001175':
                // Peptide shared in multipe proteins - not supported
                case 'MS:1000016':
                // Scan start time - not supported
                case 'MS:1002315':
                    // Concensus result - not supported
                    break;
                default:
                    $identification->setScore($cvParam[PsiVerb::CV_ACCESSION], $cvParam[PsiVerb::CV_VALUE]);
                    break;
            }
        }
        return $identification;
    }
    private function parsePeptideEvidenceCv(array $cvParams, ProteinEntry $entry)
    {
        foreach ($cvParams as $cvParam) {
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1002640':
                    // peptide end on chromosome
                    $entry->setChromosomePositionEnd((int) $cvParam[PsiVerb::CV_VALUE]);
                    break;
                case 'MS:1002641':
                    // peptide exon count
                    $entry->setChromosomeBlockCount((int) $cvParam[PsiVerb::CV_VALUE]);
                    break;
                case 'MS:1002642':
                    // peptide exon nucleotide sizes
                    $blockSizesStr = explode(',', $cvParam[PsiVerb::CV_VALUE]);
                    $blockSizes = array();
                    foreach ($blockSizesStr as $blockSize) {
                        $blockSizes[] = (int) $blockSize;
                    }
                    $entry->setChromosomeBlockSizes($blockSizes);
                    break;
                case 'MS:1002643':
                    // peptide start positions on chromosome
                    $positions = array();
                    $chunks = explode(',', $cvParam[PsiVerb::CV_VALUE]);
                    foreach ($chunks as $chunk) {
                        $positions[] = (int) $chunk;
                    }
                    $entry->setChromosomePositionsStart($positions);
                    break;
                default:
                    // Unknown field
                    break;
            }
        }
    }
    /**
     * PeptideEvidence element.
     * Using these references it is possible to indicate which spectra were actually accepted as evidence for this peptide identification in the given protein.
     *
     * @param \SimpleXMLElement $xml
     *            XML to parse
     * @return string
     */
    private function getSpectrumIdentificationItemRef(\SimpleXMLElement $xml)
    {
        return (string) $xml->attributes()->spectrumIdentificationItem_ref;
    }
    /**
     *
     * @return PrecursorIon[]
     */
    private function getSpectrumIdentificationList()
    {
        $sequences = $this->getSequenceCollection();
        $results = array();
        foreach ($this->xmlReader->DataCollection->AnalysisData->SpectrumIdentificationList->SpectrumIdentificationResult as $xml) {
            $results[$this->getAttributeId($xml)] = $this->getSpectrumIdentificationResult($xml, $sequences);
        }
        return $results;
    }
    protected function getSpectrumIdentificationProtocol(\SimpleXMLElement $xml)
    {
        $software = $this->getAnalysisSoftwareList();
        $protocol = array();
        $softwareId = (string) $xml->attributes()->analysisSoftware_ref;
        $protocol['software'] = $software[$softwareId];
        $protocol['modifications'] = array();
        if (isset($xml->ModificationParams)) {
            $protocol['modifications'] = $this->getModificationParams($xml->ModificationParams);
        }
        if (isset($xml->AdditionalSearchParams)) {
            $protocol['additions'] = $this->getAdditionalSearchParams($xml->AdditionalSearchParams);
        }
        if (isset($xml->Enzymes)) {
            $protocol['enzymes'] = $this->getEnzymes($xml->Enzymes);
        }
        if (isset($xml->FragmentTolerance)) {
            $protocol['fragmentTolerance'] = $this->getFragmentTolerance($xml->FragmentTolerance);
        }
        if (isset($xml->ParentTolerance)) {
            $protocol['parentTolerance'] = $this->getParentTolerance($xml->ParentTolerance);
        }
        return $protocol;
    }
    /**
     *
     * @param \SimpleXMLElement $xml
     *            XML object to parse
     * @param Peptide[] $sequences
     *            Array of peptide sequences to use for identifications
     * @return PrecursorIon
     */
    private function getSpectrumIdentificationResult(\SimpleXMLElement $xml, array $sequences)
    {
        $spectra = new PrecursorIon();
        $spectra->setIdentifier((string) $xml->attributes()->spectrumID);
        // We can not currently pull data from the .raw data so take the m/z vlaues from the first identification
        $charge = (int) $xml->SpectrumIdentificationItem->attributes()->chargeState;
        $massCharge = (float) $xml->SpectrumIdentificationItem->attributes()->experimentalMassToCharge;
        $spectra->setMonoisotopicMassCharge($massCharge, $charge);
        foreach ($xml->SpectrumIdentificationItem as $spectrumItem) {
            $identification = $this->getSpectrumIdentificationItem($spectrumItem, $sequences);
            if (! $this->isFilterMatch($identification)) {
                continue;
            }
            $spectra->addIdentification($identification);
        }
        foreach ($xml->cvParam as $cvParam) {
            $cvParam = $this->getCvParam($cvParam);
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1000796':
                    $spectra->setTitle($cvParam[PsiVerb::CV_VALUE]);
                    break;
                case 'MS:1001115':
                    $spectra->setScan((float) $cvParam[PsiVerb::CV_VALUE]);
                    break;
                default:
                    // Unknown element
                    break;
            }
        }
        return $spectra;
    }
    private function getSubSample()
    {
        // TODO: Implement
    }
    private function getSubstitutionModification()
    {
        // TODO: Implement
    }
    private function getThreshold(\SimpleXMLElement $xmlThreshold)
    {
        $params = array();
        foreach ($xmlThreshold->cvParam as $xmlParam) {
            $params[] = $this->getCvParam($xmlParam);
        }
        return $params;
    }
    private function getTolerance(\SimpleXMLElement $xml)
    {
        $tolerances = array();
        foreach ($xml->cvParam as $xmlCvParam) {
            $cvParam = $this->getCvParam($xmlCvParam);
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1001412':
                case 'MS:1001413':
                    $tolerance = new Tolerance((float) $cvParam[PsiVerb::CV_VALUE], $cvParam[PsiVerb::CV_UNITACCESSION]);
                    break;
                default:
                    $tolerance = $cvParam;
                    break;
            }
            $tolerances[] = $tolerance;
        }
        return $tolerances;
    }
    private function getTranslationTable()
    {
        // TODO: Implement
    }
    private function getCv()
    {
        // TODO: Implement
    }
    private function getCvList()
    {
        // TODO: Implement
    }
    private function getProteinEntryType(array $peptideEvidence, Protein $protein)
    {
        foreach ($peptideEvidence['cv'] as $cvParam) {
            switch ($cvParam[PsiVerb::CV_ACCESSION]) {
                case 'MS:1002640':
                case 'MS:1002641':
                case 'MS:1002642':
                case 'MS:1002643':
                    return new ChromosomeProteinEntry($protein);
                default:
                    break;
            }
        }
        return new ProteinEntry($protein);
    }
    private function isFilterMatch(Identification $identification)
    {
        // Remove idents > rank filter
        if (isset($this->filter['rank']) && $identification->getRank() > $this->filter['rank']) {
            return false;
        }
        return true;
    }
    /**
     * Sets the rank limit for retrieved identifications.
     * All returned indentifications will be <= $rank
     *
     * @param int $rank
     */
    public function setRankFilter($rank)
    {
        $this->filter['rank'] = $rank;
    }
}