package org.nextprot.api.blast.service.impl; import org.nextprot.api.blast.domain.GlobalHit; import org.nextprot.api.blast.domain.gen.*; import org.nextprot.api.blast.service.BlastResultUpdaterService; import org.nextprot.api.commons.exception.NextProtException; import org.nextprot.api.core.domain.MainNames; import org.nextprot.api.core.service.MainNamesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.text.DecimalFormat; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Modify and customize blast output. * * <ul> * <li>Remove useless fields (ex: blast paper reference)</li> * <li>Add some new fields (ex: sequence query, matching isoform accession,...)</li> * </ul> */ @Service public class BlastResultUpdaterServiceImpl implements BlastResultUpdaterService { private final static Pattern ISOFORM_ACCESSION_PATTERN = Pattern.compile("^.*(NX_[^-]+)(-\\d+).*$"); private final static DecimalFormat PERCENT_FORMAT = new DecimalFormat("#.##"); @Autowired private MainNamesService mainNamesService; @Override public void update(Report blastReport, String querySequence) { if (blastReport == null) { throw new NextProtException("nothing to update: blast result report was not defined"); } updateReport(blastReport); updateParams(blastReport.getParams(), querySequence); Search search = blastReport.getResults().getSearch(); updateSearch(search); for (Hit hit : search.getHits()) { updateHit(hit, querySequence.length()); hit.getDescription().forEach(this::updateHitDescription); hit.getHsps().forEach(this::updateHsp); } updateStat(search.getStat()); } @Override public void updateDescription(Description description, String isoAccession, String entryAccession) { MainNames entryNames = mainNamesService.findIsoformOrEntryMainName(entryAccession); MainNames isoNames = mainNamesService.findIsoformOrEntryMainName(isoAccession); if (entryNames == null) throw new NextProtException("could not find informations for entry "+entryAccession); if (isoNames == null) throw new NextProtException("could not find informations for isoform "+isoAccession); String geneName = (!entryNames.getGeneNameList().isEmpty()) ? entryNames.getGeneNameList().get(0) : null; String proteinName = entryNames.getName(); String title = proteinName + ((geneName != null) ? " ("+geneName+")":"")+" ["+isoNames.getAccession()+"]"; description.setTitle(title); description.setEntryAccession(entryNames.getAccession()); description.setIsoAccession(isoNames.getAccession()); description.setIsoName(isoNames.getName()); description.setProteinName(proteinName); description.setGeneName(geneName); } private void updateReport(Report report) { report.setProgram(null); report.setReference(null); report.setSearchTarget(null); } private void updateParams(Params params, String proteinSequence) { //params.setMatrix(null); //params.setExpect(null); //params.setGapOpen(null); //params.setGapExtend(null); params.setSequence(proteinSequence); } private void updateSearch(Search search) { search.setQueryId(null); search.setQueryTitle(null); search.setQueryLen(null); } private void updateHit(Hit hit, int queryLen) { hit.setNum(null); hit.setGlobalHit(buildGlobalHit(hit.getHsps(), queryLen)); } private GlobalHit buildGlobalHit(List<Hsp> hsps, int queryLen) { int totalIdentityCount = 0; int totalScore = 0; int maxScore = Integer.MIN_VALUE; double minEvalue = Double.MAX_VALUE; for (Hsp hsp : hsps) { int currentScore = hsp.getScore(); double currentEvalue = hsp.getEvalue(); totalIdentityCount += hsp.getIdentity(); totalScore += currentScore; maxScore = (currentScore > maxScore) ? currentScore : maxScore; minEvalue = (currentEvalue < minEvalue) ? currentEvalue : minEvalue; } float identityPercent = (float) totalIdentityCount / queryLen * 100; GlobalHit globalHit = new GlobalHit(); globalHit.setIdentityPercent(Float.parseFloat(PERCENT_FORMAT.format(identityPercent))); globalHit.setMaxScore(maxScore); globalHit.setMinEvalue(minEvalue); globalHit.setTotalScore(totalScore); return globalHit; } private void updateHitDescription(Description description) { description.setId(null); description.setAccession(null); Matcher matcher = ISOFORM_ACCESSION_PATTERN.matcher(description.getTitle()); if (matcher.find()) { String entryAccession = matcher.group(1); String isoformAccession = entryAccession + matcher.group(2); updateDescription(description, isoformAccession, entryAccession); } else { throw new NextProtException("blast db error: could not extract isoform information from header "+description.getTitle()); } } private void updateHsp(Hsp hsp) { float identityPercent = (float) hsp.getIdentity() / hsp.getAlignLen() * 100; hsp.setIdentityPercent(Float.parseFloat(PERCENT_FORMAT.format(identityPercent))); hsp.setNum(null); } private void updateStat(Stat stat) { stat.setHspLen(null); stat.setEffSpace(null); stat.setKappa(null); stat.setLambda(null); stat.setEntropy(null); } }