From: Jim Procter Date: Tue, 10 May 2016 15:25:23 +0000 (+0100) Subject: JAL-2103 extracted result processing code to allow mocking X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;ds=sidebyside;h=e9898e9e5bc1ef69ffa22b2760803e2c6d333bd7;p=jalview.git JAL-2103 extracted result processing code to allow mocking --- diff --git a/src/jalview/ws/jws1/JPredThread.java b/src/jalview/ws/jws1/JPredThread.java index bb09af3..da53ef5 100644 --- a/src/jalview/ws/jws1/JPredThread.java +++ b/src/jalview/ws/jws1/JPredThread.java @@ -23,7 +23,6 @@ package jalview.ws.jws1; import jalview.analysis.AlignSeq; import jalview.bin.Cache; import jalview.datamodel.Alignment; -import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentView; import jalview.datamodel.ColumnSelection; @@ -31,6 +30,7 @@ import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.Desktop; import jalview.gui.WebserviceInfo; +import jalview.io.FileParse; import jalview.io.FormatAdapter; import jalview.util.Comparison; import jalview.util.MessageManager; @@ -38,8 +38,8 @@ import jalview.ws.AWsJob; import jalview.ws.JobStateSummary; import jalview.ws.WSClientI; +import java.io.IOException; import java.util.Hashtable; -import java.util.List; import vamsas.objects.simple.JpredResult; @@ -61,11 +61,6 @@ class JPredThread extends JWS1Thread implements WSClientI java.util.Hashtable SequenceInfo = null; - int msaIndex = 0; // the position of the original sequence in the array of - - // Sequences in the input object that this job holds a - // prediction for - /** * * @return true if getResultSet will return a valid alignment and prediction @@ -106,261 +101,26 @@ class JPredThread extends JWS1Thread implements WSClientI { return null; } - AlignmentI al = null; - ColumnSelection alcsel = null; - int FirstSeq = -1; // the position of the query sequence in Alignment al JpredResult result = (JpredResult) this.result; jalview.bin.Cache.log.debug("Parsing output from JNet job."); - // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", - // "File"); - jalview.io.JPredFile prediction = new jalview.io.JPredFile( - result.getPredfile(), "Paste"); - SequenceI[] preds = prediction.getSeqsAsArray(); - jalview.bin.Cache.log.debug("Got prediction profile."); - - if ((this.msa != null) && (result.getAligfile() != null)) - { - jalview.bin.Cache.log.debug("Getting associated alignment."); - // we ignore the returned alignment if we only predicted on a single - // sequence - String format = new jalview.io.IdentifyFile().identify( - result.getAligfile(), "Paste"); - - if (jalview.io.FormatAdapter.isValidFormat(format)) - { - SequenceI sqs[]; - if (predMap != null) - { - Object[] alandcolsel = input - .getAlignmentAndColumnSelection(getGapChar()); - sqs = (SequenceI[]) alandcolsel[0]; - al = new Alignment(sqs); - alcsel = (ColumnSelection) alandcolsel[1]; - } - else - { - al = new FormatAdapter().readFile(result.getAligfile(), - "Paste", format); - sqs = new SequenceI[al.getHeight()]; - - for (int i = 0, j = al.getHeight(); i < j; i++) - { - sqs[i] = al.getSequenceAt(i); - } - if (!jalview.analysis.SeqsetUtils.deuniquify(SequenceInfo, sqs)) - { - throw (new Exception( - MessageManager - .getString("exception.couldnt_recover_sequence_properties_for_alignment"))); - } - } - FirstSeq = 0; - if (currentView.getDataset() != null) - { - al.setDataset(currentView.getDataset()); - - } - else - { - al.setDataset(null); - } - jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, - FirstSeq, false, predMap); - - } - else - { - throw (new Exception(MessageManager.formatMessage( - "exception.unknown_format_for_file", new String[] { - format, result.getAligfile() }))); - } - } - else - { - AlignmentI fullAlignment = null; - try - { - // locate full alignment - // http://www.compbio.dundee.ac.uk/jpred/results/jp_GuygEzV/jp_GuygEzV.full_MSA.fasta - String jobid = getJobId().substring( - getJobId().lastIndexOf("/") + 1); - String job_alignment = "http://www.compbio.dundee.ac.uk/jpred/results/" - + jobid + "/" + jobid + ".full_MSA.fasta"; - fullAlignment = new FormatAdapter().readFile(job_alignment, - FormatAdapter.URL, "FASTA"); - } catch (Exception q) - { - - } finally - { - if (fullAlignment != null) - { - al = fullAlignment; - FirstSeq = 0; - } - else - { - al = new Alignment(preds); - FirstSeq = prediction.getQuerySeqPosition(); - } - } - - if (predMap != null) - { - // map the prediction onto the query sequence, excluding positions - // corresponding to hidden regions in the original input. - char gc = getGapChar(); - SequenceI[] sqs = (SequenceI[]) input - .getAlignmentAndColumnSelection(gc)[0]; - if (this.msaIndex >= sqs.length) - { - throw new Error( - MessageManager - .getString("error.implementation_error_invalid_msa_index_for_job")); - } - if (fullAlignment == null) - { - // // - // Uses RemoveGapsCommand - // // - new jalview.commands.RemoveGapsCommand( - MessageManager.getString("label.remove_gaps"), - new SequenceI[] { sqs[msaIndex] }, currentView); - - SequenceI profileseq = al.getSequenceAt(FirstSeq); - profileseq.setSequence(sqs[msaIndex].getSequenceAsString()); - } - } - - if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash( - al.getSequenceAt(FirstSeq), SequenceInfo)) - { - throw (new Exception( - MessageManager - .getString("exception.couldnt_recover_sequence_props_for_jnet_query"))); - } - else - { - if (currentView.getDataset() != null) - { - al.setDataset(currentView.getDataset()); - - } - else - { - al.setDataset(null); - } - jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, - FirstSeq, true, predMap); - SequenceI profileseq = al.getSequenceAt(0); // this includes any gaps. - if (fullAlignment == null) - { - alignToProfileSeq(al, profileseq); - } - if (fullAlignment == null && predMap != null) - { - // Adjust input view for gaps - // propagate insertions into profile - alcsel = ColumnSelection.propagateInsertions(profileseq, al, - input); - } - } - } - // transfer to dataset - for (AlignmentAnnotation alant : al.getAlignmentAnnotation()) - { - if (alant.sequenceRef != null) - { - replaceAnnotationOnAlignmentWith(alant, alant.label, - "jalview.jws1.Jpred" + (this.msa == null ? "" : "MSA"), - alant.sequenceRef); - } - } - return new Object[] { al, alcsel }; // , FirstSeq, noMsa}; - } - - /** - * copied from JabawsCalcWorker - * - * @param newAnnot - * @param typeName - * @param calcId - * @param aSeq - */ - protected void replaceAnnotationOnAlignmentWith( - AlignmentAnnotation newAnnot, String typeName, String calcId, - SequenceI aSeq) - { - SequenceI dsseq = aSeq.getDatasetSequence(); - while (dsseq.getDatasetSequence() != null) - { - dsseq = dsseq.getDatasetSequence(); - } - // look for same annotation on dataset and lift this one over - List dsan = dsseq.getAlignmentAnnotations( - calcId, typeName); - if (dsan != null && dsan.size() > 0) - { - for (AlignmentAnnotation dssan : dsan) - { - dsseq.removeAlignmentAnnotation(dssan); - } - } - AlignmentAnnotation dssan = new AlignmentAnnotation(newAnnot); - dsseq.addAlignmentAnnotation(dssan); - dssan.adjustForAlignment(); + Object[] resview = JPredWSUtils.processJnetResult(currentView, input, + getGapChar(), SequenceInfo, this.msa != null, + this.predMap, + result.getPredfile(), result.getAligfile(), + getFullAlignmentSource()); + return resview; // Alignment, ColumnSelection } - /** - * Given an alignment where all other sequences except profileseq are - * aligned to the ungapped profileseq, insert gaps in the other sequences to - * realign them with the residues in profileseq - * - * @param al - * @param profileseq - */ - private void alignToProfileSeq(AlignmentI al, SequenceI profileseq) + public FileParse getFullAlignmentSource() throws IOException { - char gc = al.getGapCharacter(); - int[] gapMap = profileseq.gapMap(); - // insert gaps into profile - for (int lp = 0, r = 0; r < gapMap.length; r++) - { - if (gapMap[r] - lp > 1) - { - StringBuffer sb = new StringBuffer(); - for (int s = 0, ns = gapMap[r] - lp; s < ns; s++) - { - sb.append(gc); - } - for (int s = 1, ns = al.getHeight(); s < ns; s++) - { - String sq = al.getSequenceAt(s).getSequenceAsString(); - int diff = gapMap[r] - sq.length(); - if (diff > 0) - { - // pad gaps - sq = sq + sb; - while ((diff = gapMap[r] - sq.length()) > 0) - { - sq = sq - + ((diff >= sb.length()) ? sb.toString() : sb - .substring(0, diff)); - } - al.getSequenceAt(s).setSequence(sq); - } - else - { - al.getSequenceAt(s).setSequence( - sq.substring(0, gapMap[r]) + sb.toString() - + sq.substring(gapMap[r])); - } - } - } - lp = gapMap[r]; - } + // locate full alignment + // http://www.compbio.dundee.ac.uk/jpred/results/jp_GuygEzV/jp_GuygEzV.full_MSA.fasta + String jobid = getJobId().substring(getJobId().lastIndexOf("/") + 1); + String job_alignment = "http://www.compbio.dundee.ac.uk/jpred/results/" + + jobid + "/" + jobid + ".full_MSA.fasta"; + return new FileParse(job_alignment, FormatAdapter.URL); } public JPredJob(Hashtable SequenceInfo, SequenceI seq, int[] delMap) diff --git a/src/jalview/ws/jws1/JPredWSUtils.java b/src/jalview/ws/jws1/JPredWSUtils.java new file mode 100644 index 0000000..7b74e2a --- /dev/null +++ b/src/jalview/ws/jws1/JPredWSUtils.java @@ -0,0 +1,317 @@ +package jalview.ws.jws1; + +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.SequenceI; +import jalview.io.FileParse; +import jalview.io.FormatAdapter; +import jalview.util.MessageManager; + +import java.util.Hashtable; +import java.util.List; + + +/** + * extraction of processing routines to allow mocking + * + * @author jprocter + * + */ +public class JPredWSUtils +{ + /** + * Process data extracted from service result set to generate a JPred result + * view. + * + * @param currentView + * + * @param input + * - original input alignment + * @param gapChar + * - character to use for reconstructing alignment used for + * prediction + * @param SequenceInfo + * - from SeqHash + * @param msaPred + * - true if a prediction based on existing MSA + * @param predMap + * - position + * @param result_PredFile + * @param result_Aligfile + * @param full_alignment + * @return { Alignment, ColumnSelection } + * @throws Exception + */ + public static Object[] processJnetResult(AlignmentI currentView, + AlignmentView input, + char gapChar, Hashtable SequenceInfo, + boolean msaPred, int[] predMap, String result_PredFile, + String result_Aligfile, FileParse full_alignment) + throws Exception + { + + AlignmentI al = null; + ColumnSelection alcsel = null; + + // the position of the query sequence in Alignment al + int FirstSeq = -1; + + // the position of the original sequence in the array of + // Sequences in the input object that this job holds a + // prediction for + int msaIndex = 0; + + // JPredFile prediction = new JPredFile("C:/JalviewX/files/jpred.txt", + // "File"); + jalview.io.JPredFile prediction = new jalview.io.JPredFile( + result_PredFile, "Paste"); + SequenceI[] preds = prediction.getSeqsAsArray(); + jalview.bin.Cache.log.debug("Got prediction profile."); + + if (msaPred && (result_Aligfile != null)) + { + jalview.bin.Cache.log.debug("Getting associated alignment."); + // we ignore the returned alignment if we only predicted on a single + // sequence + String format = new jalview.io.IdentifyFile().identify( + result_Aligfile, "Paste"); + + if (jalview.io.FormatAdapter.isValidFormat(format)) + { + SequenceI sqs[]; + if (predMap != null) + { + Object[] alandcolsel = input + .getAlignmentAndColumnSelection(gapChar); + sqs = (SequenceI[]) alandcolsel[0]; + al = new Alignment(sqs); + alcsel = (ColumnSelection) alandcolsel[1]; + } + else + { + al = new FormatAdapter().readFile(result_Aligfile, "Paste", + format); + sqs = new SequenceI[al.getHeight()]; + + for (int i = 0, j = al.getHeight(); i < j; i++) + { + sqs[i] = al.getSequenceAt(i); + } + if (!jalview.analysis.SeqsetUtils.deuniquify(SequenceInfo, sqs)) + { + throw (new Exception( + MessageManager + .getString("exception.couldnt_recover_sequence_properties_for_alignment"))); + } + } + FirstSeq = 0; + if (currentView.getDataset() != null) + { + al.setDataset(currentView.getDataset()); + + } + else + { + al.setDataset(null); + } + jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, + FirstSeq, false, predMap); + + } + else + { + throw (new Exception(MessageManager.formatMessage( + "exception.unknown_format_for_file", new String[] { format, + result_Aligfile }))); + } + } + else + { + AlignmentI fullAlignment = null; + try + { + // read full alignment if present. + if (full_alignment != null) + { + fullAlignment = new FormatAdapter().readFromFile(full_alignment, + "FASTA"); + } + } catch (Exception q) + { + + } finally + { + if (fullAlignment != null) + { + al = fullAlignment; + FirstSeq = 0; + } + else + { + al = new Alignment(preds); + FirstSeq = prediction.getQuerySeqPosition(); + } + } + + if (predMap != null) + { + // map the prediction onto the query sequence, excluding positions + // corresponding to hidden regions in the original input. + char gc = gapChar; + SequenceI[] sqs = (SequenceI[]) input + .getAlignmentAndColumnSelection(gc)[0]; + if (msaIndex >= sqs.length) + { + throw new Error( + MessageManager + .getString("error.implementation_error_invalid_msa_index_for_job")); + } + if (fullAlignment == null) + { + // // + // Uses RemoveGapsCommand + // // + new jalview.commands.RemoveGapsCommand( + MessageManager.getString("label.remove_gaps"), + new SequenceI[] { sqs[msaIndex] }, currentView); + + SequenceI profileseq = al.getSequenceAt(FirstSeq); + profileseq.setSequence(sqs[msaIndex].getSequenceAsString()); + } + } + + if (!jalview.analysis.SeqsetUtils.SeqCharacterUnhash( + al.getSequenceAt(FirstSeq), SequenceInfo)) + { + throw (new Exception( + MessageManager + .getString("exception.couldnt_recover_sequence_props_for_jnet_query"))); + } + else + { + if (currentView.getDataset() != null) + { + al.setDataset(currentView.getDataset()); + + } + else + { + al.setDataset(null); + } + jalview.io.JnetAnnotationMaker.add_annotation(prediction, al, + FirstSeq, true, predMap); + SequenceI profileseq = al.getSequenceAt(0); // this includes any gaps. + if (fullAlignment == null) + { + alignToProfileSeq(al, profileseq); + } + if (fullAlignment == null && predMap != null) + { + // Adjust input view for gaps + // propagate insertions into profile + alcsel = ColumnSelection.propagateInsertions(profileseq, al, + input); + } + } + } + + // transfer to dataset + for (AlignmentAnnotation alant : al.getAlignmentAnnotation()) + { + if (alant.sequenceRef != null) + { + replaceAnnotationOnAlignmentWith(alant, alant.label, + "jalview.jws1.Jpred" + (msaPred ? "MSA" : ""), + alant.sequenceRef); + } + } + + return new Object[] { al, alcsel }; // , FirstSeq, noMsa}; + } + + /** + * copied from JabawsCalcWorker + * + * @param newAnnot + * @param typeName + * @param calcId + * @param aSeq + */ + public static void replaceAnnotationOnAlignmentWith( + AlignmentAnnotation newAnnot, String typeName, String calcId, + SequenceI aSeq) + { + SequenceI dsseq = aSeq.getDatasetSequence(); + while (dsseq.getDatasetSequence() != null) + { + dsseq = dsseq.getDatasetSequence(); + } + // look for same annotation on dataset and lift this one over + List dsan = dsseq.getAlignmentAnnotations(calcId, + typeName); + if (dsan != null && dsan.size() > 0) + { + for (AlignmentAnnotation dssan : dsan) + { + dsseq.removeAlignmentAnnotation(dssan); + } + } + AlignmentAnnotation dssan = new AlignmentAnnotation(newAnnot); + dsseq.addAlignmentAnnotation(dssan); + dssan.adjustForAlignment(); + } + + /** + * Given an alignment where all other sequences except profileseq are aligned + * to the ungapped profileseq, insert gaps in the other sequences to realign + * them with the residues in profileseq + * + * @param al + * @param profileseq + */ + public static void alignToProfileSeq(AlignmentI al, SequenceI profileseq) + { + char gc = al.getGapCharacter(); + int[] gapMap = profileseq.gapMap(); + // insert gaps into profile + for (int lp = 0, r = 0; r < gapMap.length; r++) + { + if (gapMap[r] - lp > 1) + { + StringBuffer sb = new StringBuffer(); + for (int s = 0, ns = gapMap[r] - lp; s < ns; s++) + { + sb.append(gc); + } + for (int s = 1, ns = al.getHeight(); s < ns; s++) + { + String sq = al.getSequenceAt(s).getSequenceAsString(); + int diff = gapMap[r] - sq.length(); + if (diff > 0) + { + // pad gaps + sq = sq + sb; + while ((diff = gapMap[r] - sq.length()) > 0) + { + sq = sq + + ((diff >= sb.length()) ? sb.toString() : sb + .substring(0, diff)); + } + al.getSequenceAt(s).setSequence(sq); + } + else + { + al.getSequenceAt(s).setSequence( + sq.substring(0, gapMap[r]) + sb.toString() + + sq.substring(gapMap[r])); + } + } + } + lp = gapMap[r]; + } + } + +} diff --git a/test/jalview/ws/jws1/JPredWSUtilsTest.java b/test/jalview/ws/jws1/JPredWSUtilsTest.java new file mode 100644 index 0000000..0563647 --- /dev/null +++ b/test/jalview/ws/jws1/JPredWSUtilsTest.java @@ -0,0 +1,31 @@ +package jalview.ws.jws1; + +import org.testng.annotations.Test; + +public class JPredWSUtilsTest +{ + @Test(groups = { "Functional" }) + public void testSingleSeqPrediction() + { + + } + + @Test(groups = { "Functional" }) + public void testSingleSeqPredictionHiddenRegion() + { + + } + + @Test(groups = { "Functional" }) + public void testMsaPrediction() + { + + } + + @Test(groups = { "Functional" }) + public void testMsaPredictionHiddenRegion() + { + + } + +}