Skip to main content

How to call codon optimization in a workflow

Comments

18 comments

  • Official comment
    Jonas Kuhn

    The reason why you're seeing always the same results is because the `options` that you're passing in are always using the same 'Seed' value for randomly changing codons.

    If you update that value in every iteration this should work...

    options.setStringValue("seedValue", "" + new Random().nextInt());
  • Ashfaq Indragadia

    Have a look at this FAQ in our API docs: https://assets.geneious.com/developer/geneious/javadoc/latest/index.html#faqInvokeOperations

    Try following this example with the unique id for the annotation generator as: com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator

    Let us know if you face further issues. 

    0
  • K J

    Thanks so much, that seems to be working!  I had a follow up question about codon optimization options.  I would like to allow the user to access a similar options dialogue as the built-in Optimize Codons function in Geneious as shown below:

     

    Most of the examples I've seen allow the user to choose from a list of options, is there a way they can free-form select enzymes?

    0
  • Richard Moir

    Unfortunately choosing enzymes is tied to that specific "Select Enzymes" window so the only way to allow users of your plugin to choose enzyme would be for you to pop up the options that are provided by the annotation generator. Hopefully that answers the question! E.g:

    SequenceAnnotationGenerator generator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");
    Options o = generator.getGeneralOptions();
    //if you want to hide some options, use o.getOption("name").setVisible(false)
    if (!Dialogs.showOptionsDialog(o, "Optimization Options", false)) {
    return; //canceled
    }
    //then pass o into generateAnnotations
    0
  • K J

    Thank you both so much, that was really helpful!

    0
  • K J

    I have a follow up question for this project.  I have written the following code but am encountering an error when I attempt to run it.

    Custom Java Code:

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument and modifies the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify. If the input document is a sequence list, or a non-editable sequence,
    *then Geneious will create a copy of the sequence before calling this method.
    */
    public static void modifySequence(DefaultSequenceDocument sequence){
        
        //Instantiates a new list representing optimized codon annotations
        List<SequenceAnnotation> optimizedCodons = new ArrayList<SequenceAnnotation>(); 
            
        //codon optimize at least once to remove restriction sites
        try {
            optimizedCodons = codonOptimize(sequence);
        } catch (DocumentOperationException doe) {
            doe.printStackTrace();
        }

    //Applies the optimized codon annotations to the sequence
        for(SequenceAnnotation annotation : optimizedCodons){
            sequence.addSequenceAnnotation(annotation); // applies each annotation to the sequence
        }

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = sequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

        while(DNA_NucleotideInfo.getPercentGC() > 0.551){
                
            try {
                optimizedCodons = codonOptimize(sequence);
            } catch (DocumentOperationException doe) {
                doe.printStackTrace();
            }

    //Applies the optimized codon annotations to the sequence
            for(SequenceAnnotation annotation : optimizedCodons){
                sequence.addSequenceAnnotation(annotation);
            }
            
            //updates nucleotide info for the modified sequence now that optimized codon annotations have been applied
            charSequence = sequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence); 
    }
    }


    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a list of optimized codon annotations
    *Uses CodonOptimizationSequenceAnnotationGenerator and displays the general options for this annotation generator so user can select forbidden restriction sites.
    *@param sequence the sequence to generate codon optimized annotations for.
    *@throws DocumentOperationException
    */
    public static List<SequenceAnnotation> codonOptimize(DefaultSequenceDocument sequence) throws DocumentOperationException{
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");
        
        AnnotatedPluginDocument sequenceDocument = DocumentUtilities.createAnnotatedPluginDocument(sequence);
        
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();
        if (!Dialogs.showOptionsDialog(options, "Optimization Options", false)) {
            return null; //canceled
    }

        List<SequenceAnnotation> annotationsList = codonOptimizeGenerator.generateAnnotations(selectionRange, ProgressListener.EMPTY, options, sequenceDocument).get(0);
        
        return annotationsList;
    }

    When I try to run the workflow on a nucleotide sequence document, I receive the following error.

     

    Does anyone know how I might be able to resolve this issue?  Thanks so much in advance!

    ---------------


    P.S. The full error message

    com.biomatters.geneious.publicapi.plugin.DocumentOperationException at com.biomatters.plugins.workflows.WorkflowDocumentOperation.a(WorkflowDocumentOperation.java:413) at com.biomatters.plugins.workflows.WorkflowDocumentOperation.performOperation(WorkflowDocumentOperation.java:179) at com.biomatters.iseek.plugin.operations.o.b(OperationManager.java:513) at com.biomatters.geneious.common.operations.c.c(OperationsUtilities.java:165) at com.biomatters.geneious.common.operations.c.b(OperationsUtilities.java:162) at com.biomatters.geneious.common.operations.b$c.a(OperationsUtilities.java:141) at com.biomatters.geneious.common.operations.b$d.a(OperationsUtilities.java:168) at com.biomatters.iseek.plugin.operations.e.a(OperationManager.java:518) at com.biomatters.iseek.plugin.operations.s.a(OperationPerformer.java:136) at com.biomatters.iseek.plugin.operations.OperationAction.performAction(OperationAction.java:116) at com.biomatters.iseek.plugin.operations.a.run(OperationAction.java:92) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: com.biomatters.geneious.publicapi.plugin.DocumentOperationException: RuntimeDocumentOperationException: Failed to call custom code modifySequence method: showOptionsDialog must be called from the dispatch (swing) thread. at com.biomatters.plugins.workflows.CustomCodeMethods.a(CustomCodeMethods.java:234) at com.biomatters.plugins.workflows.WorkflowElementCustomCode.a(WorkflowElementCustomCode.java:74) at com.biomatters.plugins.workflows.WorkflowDocumentOperation.a(WorkflowDocumentOperation.java:395) ... 11 more Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at com.biomatters.plugins.workflows.CustomCodeMethods.a(CustomCodeMethods.java:211) ... 13 more Caused by: com.biomatters.geneious.publicapi.plugin.RuntimeDocumentOperationException: Failed to call custom code modifySequence method: showOptionsDialog must be called from the dispatch (swing) thread. at com.biomatters.plugins.workflows.CustomCodeMethods$PerformOperationImplementation.performOperation(CustomCodeMethods.java:309) ... 18 more Caused by: com.biomatters.geneious.publicapi.plugin.DocumentOperationException: Failed to call custom code modifySequence method: showOptionsDialog must be called from the dispatch (swing) thread. ... 19 more Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at com.biomatters.plugins.workflows.CustomCodeMethods$PerformOperationImplementation.performOperation(CustomCodeMethods.java:307) ... 18 more Caused by: java.lang.RuntimeException: showOptionsDialog must be called from the dispatch (swing) thread. at com.biomatters.geneious.publicapi.components.Dialogs.a(Dialogs.java:352) at com.biomatters.geneious.publicapi.components.Dialogs.a(Dialogs.java:244) at com.biomatters.geneious.publicapi.components.Dialogs.showOptionsDialog(Dialogs.java:199) at com.biomatters.geneious.publicapi.components.Dialogs.showOptionsDialog(Dialogs.java:177) at com.biomatters.plugins.workflows.CustomCode.CustomCode.codonOptimize(CustomCode.java:102) at com.biomatters.plugins.workflows.CustomCode.CustomCode.modifySequence(CustomCode.java:52) ... 23 more

    0
  • Jonas Kuhn

    You can wrap your call that shows the option dialog in a 

    ThreadUtilities.invokeNowOrWait(() -> {
    // your code handling the options
    })
    0
  • K J

    Thanks so much Jonas, that helped!

    I now have two issues:

    1) I tried running my workflow and saw that it ran indefinitely.  I added some showMessageDialog statements into the code to show the %GC after the annotations should have been applied (lines 28-31 and 47-50) and saw that the %GC was not changing.  How can I apply the annotations to the sequence such that the sequence is modified?

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument and modifies the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify. If the input document is a sequence list, or a non-editable sequence,
    *then Geneious will create a copy of the sequence before calling this method.
    */
    public static void modifySequence(DefaultSequenceDocument sequence){

        //Instantiates a new list representing optimized codon annotations
        List<SequenceAnnotation> optimizedCodons = new ArrayList<SequenceAnnotation>(); 

        //codon optimize at least once to remove restriction sites
        try {
            optimizedCodons = codonOptimize(sequence);
        } catch (DocumentOperationException doe) {
            doe.printStackTrace();
        }

        //Applies the optimized codon annotations to the sequence
        for(SequenceAnnotation annotation : optimizedCodons){
            sequence.addSequenceAnnotation(annotation); // applies each annotation to the sequence
        }

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = sequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

    Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());

        while(DNA_NucleotideInfo.getPercentGC() > 55.1){
                
            try {
                optimizedCodons = codonOptimize(sequence);
            } catch (DocumentOperationException doe) {
                doe.printStackTrace();
            }

            //Applies the optimized codon annotations to the sequence
            for(SequenceAnnotation annotation : optimizedCodons){
                sequence.addSequenceAnnotation(annotation);
            }

            //updates nucleotide info for the modified sequence now that optimized codon annotations have been applied
            charSequence = sequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence);

    Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());
      }
    }

    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a list of optimized codon annotations
    *Uses CodonOptimizationSequenceAnnotationGenerator and displays the general options for this annotation generator so user can select forbidden restriction sites.
    *@param sequence the sequence to generate codon optimized annotations for.
    *@throws DocumentOperationException
    */
    public static List<SequenceAnnotation> codonOptimize(DefaultSequenceDocument sequence) throws DocumentOperationException{

    SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

    AnnotatedPluginDocument sequenceDocument = DocumentUtilities.createAnnotatedPluginDocument(sequence);

    SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();

        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
        });

    List<SequenceAnnotation> annotationsList = codonOptimizeGenerator.generateAnnotations(selectionRange, ProgressListener.EMPTY, options, sequenceDocument).get(0);

        return annotationsList;
    }

     

    2) I realized that the way I set up the code has the options window pop up each time the while loop iterates.  I would like to change this so the user only has to set the options once.  I attempted this by moving the line that creates codonOptimizeGenerator and the lines handling the options into the modifySequence method (see below).  However, I am having issues configuring the code to catch the DocumentOperactionException error.  Any assistance would be greatly appreciated!

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument and modifies the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify. If the input document is a sequence list, or a non-editable sequence,
    *then Geneious will create a copy of the sequence before calling this method.
    */
    public static void modifySequence(DefaultSequenceDocument sequence){

        //Instantiates a new list representing optimized codon annotations
        List<SequenceAnnotation> optimizedCodons = new ArrayList<SequenceAnnotation>(); 

        //codon optimize at least once to remove restriction sites
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

        //Options: allow user to select enzymes and codon usage table
        Options options = new Options(getThisClass());

        try {
            options = codonOptimizeGenerator.getGeneralOptions();
        } catch (DocumentOperationException doe) {
            doe.printStackTrace();
        }

        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
        });

        try {
            optimizedCodons = codonOptimize(codonOptimizeGenerator, sequence, options);
        } catch (DocumentOperationException doe) {
            doe.printStackTrace();
        }

        //Applies the optimized codon annotations to the sequence
        for(SequenceAnnotation annotation : optimizedCodons){
            sequence.addSequenceAnnotation(annotation); // applies each annotation to the sequence
        }

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = sequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

    while(DNA_NucleotideInfo.getPercentGC() > 55.1){

            try {
                optimizedCodons = codonOptimize(codonOptimizeGenerator, sequence, options);
            } catch (DocumentOperationException doe) {
                doe.printStackTrace();
            }

            //Applies the optimized codon annotations to the sequence
            for(SequenceAnnotation annotation : optimizedCodons){
                sequence.addSequenceAnnotation(annotation);
            }

            //updates nucleotide info for the modified sequence now that optimized codon annotations have been applied
            charSequence = sequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence); 
    }
    }

    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a list of optimized codon annotations
    *@param CodonOptimizationSequenceAnnotationGenerator, the annotation generator.
    *@param options, displays the general options for this annotation generator so user can select forbidden restriction sites.
    *@param sequence the sequence to generate codon optimized annotations for.
    *@throws DocumentOperationException
    */
    public static List<SequenceAnnotation> codonOptimize(SequenceAnnotationGenerator codonOptimizeGenerator, DefaultSequenceDocument sequence, Options options) throws DocumentOperationException{
      AnnotatedPluginDocument sequenceDocument = DocumentUtilities.createAnnotatedPluginDocument(sequence);

        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        List<SequenceAnnotation> annotationsList = codonOptimizeGenerator.generateAnnotations(selectionRange, ProgressListener.EMPTY, options, sequenceDocument).get(0);
        
        List<SequenceAnnotation> annotationsList = codonOptimizeGenerator.generateAnnotations(selectionRange, ProgressListener.EMPTY, options, sequenceDocument).get(0);
        
        return annotationsList;
    }
    0
  • Jonas Kuhn

    Hi, glad that it helped.

    To your follow-up questions:

    1) You're calling the annotation generator with `generateAnnotations()`. That returns only annotations and leaves the actual charSequence untouched; so iterating over it will always have the same results.
    Calling `generate()` instead would return a set of modified sequences that you can access with `results.get(indexOfInputSequence).getGeneratedDocuments()` , and you can iterate over those.

    2) You could change `modifySequence()` to throw a DOE and handle it from wherever you're calling that method, or let it propagate all the way up. Other than that, I'm not sure where you're encountering difficulties.
    One thing is that you're only 'printing' the error, instead of cancelling the operation or showing some dialogs (which you could do instead); but I assume this is somewhat intentional?

    0
  • K J

    Thank you so much for the help!

    I implemented the suggestions and they appear to have worked!  My 'print' statements now show that the %GC has changed.  However, I am now facing two new issues:

    1) The generated document is not being saved into my folder branch.  When my code finishes running, no changes are made to the original sequence and there are no newly generated sequence.  I tried using 'modifyCopyOfSequence()' to see if that would change anything, but it did not.  I also tried using 'addGeneratedDocument​(AnnotatedPluginDocument document)' to see if that would change anything, but my problem still persists.

    2) My code is going through the loop (as confirmed by my 'print' statements) but the %GC does not change after the first round of codon optimization.  I have a sense that I am missing something in my while loop, but I am not sure what.

    Thanks again, any help is really appreciated!

     

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument, makes a copy, and modifies the copy of the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify.
    *@throws DocumentOperationException.
    */
    public static void modifyCopyOfSequence(DefaultSequenceDocument sequence)throws DocumentOperationException{
        //Creates the annotation generator
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();

        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
        });

        //codon optimize at least once to remove restriction sites
        sequence = (DefaultSequenceDocument)codonOptimize(sequence, options, codonOptimizeGenerator).getDocument();

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = sequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

        //Sanity Check
        Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());

        while(DNA_NucleotideInfo.getPercentGC() > 55.1){
                
            //codon optimizes
            sequence = (DefaultSequenceDocument)codonOptimize(sequence, options, codonOptimizeGenerator).getDocument();

            //updates nucleotide info for the modified sequence now that the codon optimized sequence has been generated
            charSequence = sequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence);

            //sanity check
            Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());
    }
    }

    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a codon optimized AnnotatedPluginDocument
    *Uses CodonOptimizationSequenceAnnotationGenerator and displays the general options for this annotation generator so user can select forbidden restriction sites.
    *@param sequence the sequence to generate codon optimized annotations for.
    *@throws DocumentOperationException.
    */
    public static AnnotatedPluginDocument codonOptimize(DefaultSequenceDocument sequence, Options options, SequenceAnnotationGenerator codonOptimizeGenerator) throws DocumentOperationException{

        //Creates an array to store the sequence as an AnnotatedPluginDocument
        AnnotatedPluginDocument[] sequenceDocument = new AnnotatedPluginDocument[1];
        sequenceDocument[0] = DocumentUtilities.createAnnotatedPluginDocument(sequence);

        //Creates the SelectionRange for the annotation generator to be applied
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Annotation generator is applied to the set of sequenceDocuments within the selection range and generates a set of codon optimized sequence documents
        List<SequenceAnnotationGenerator.AnnotationGeneratorResult> results = codonOptimizeGenerator.generate(sequenceDocument, selectionRange, ProgressListener.EMPTY, options);
        List<AnnotatedPluginDocument> optimizedDocument = results.get(0).getGeneratedDocuments();

        //Attempt at saving the generated document
        results.get(0).addGeneratedDocument​(optimizedDocument.get(0));

        return optimizedDocument.get(0);
    }








    0
  • Jonas Kuhn

    1) Both `modifySequence` and `modifyCopyOfSequence` make and save modifications only on the sequence that was passed in. While your intention is to modify that passed in sequence, it does not actually work by assigning a new object to the same variable, but by modifying the sequence object that was originally passed in.

    So you have two options that you can do:

    Option 1: Instead of re-assigning a new object to the `sequence` variable, you can modify the original sequence object by setting the sequence and annotations (preferably once at the very end), similar like so:

    ((EditableSequenceDocument) sequence).setSequenceAndAnnotations(charSequenceOfFinalOptimizedSequence, newAnnotations);

    Option 2: Instead of modifying the input sequence, create and return new sequences by using the `performOperation()` method instead of `modifySequence()`. This will add the codon-optimized sequences to your database and leave the original sequence untouched.

     

    2) Quite frankly I also can't spot why your loop doesn't update the sequence in the while loop, it does look like you're doing the correct thing there. (Although possibly it would be a good idea to build in a break that stops the loop if the underlying charSequence hasn't changed between two iterations, in order to avoid an endless loop if codonOptimize fails to discover and change anything.)

    That is also the main thing that I would try to investigate, whether it's not changing anything because it's failing to, or possibly the changes are A <-> T substitutions only?

    0
  • K J

    Thanks so much for all the help!

    I implemented your suggestions and the code now save the codon optimized document, but continues to be unmodified by the while loop.  I confirmed this by adding in a 'break' in the while loop, which my code always encounters immediately:  

    //Stops the program if there are no longer any changes being made to the sequence
    if(CharSequenceUtilities.equals(storedSeq,charSequence)){
    Dialogs.showMessageDialog​("Sequence was not further optimized");
    break;
    }

    I also checked to see if the program only performs A <-> T substitutions and saw that it does not.  In this test, I ran my workflow on the original sequence, and then ran my workflow on the optimized sequence.

    Here we can see that we have all sorts of different mutations.

    To summarize, I am seeing that the first run of codon optimization on the input sequence generates a new sequence with mutations, but all subsequent optimizations (performed within the while loop) do not change the sequence.  I am unsure as to why that is.  Below is my workflow code, I would greatly appreciate any help!

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument, makes a copy, and modifies the copy of the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify.
    *@throws DocumentOperationException.
    */
    public static void modifyCopyOfSequence(DefaultSequenceDocument sequence)throws DocumentOperationException{
        //Creates the annotation generator
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();

        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
        });

        //codon optimize at least once to remove restriction sites
        DefaultSequenceDocument codonOptimizedSequence = (DefaultSequenceDocument)codonOptimize(sequence, options, codonOptimizeGenerator).getDocument();

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = codonOptimizedSequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

        //Sanity Check
        Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());


        //Debugging - trying to see if codon optimizing the input sequence again results in a different sequence
        codonOptimizedSequence = (DefaultSequenceDocument)codonOptimize(sequence, options, codonOptimizeGenerator).getDocument();
        charSequence = codonOptimizedSequence.getCharSequence();
        DNA_NucleotideInfo = new NucleotideCounter(charSequence);
        Dialogs.showMessageDialog​("1GC%:" + DNA_NucleotideInfo.getPercentGC());

    while(DNA_NucleotideInfo.getPercentGC() > 55.1){

            //stores the char sequence before the new round of optimization
            SequenceCharSequence storedSeq = charSequence;

            //codon optimizes
            codonOptimizedSequence = (DefaultSequenceDocument)codonOptimize(codonOptimizedSequence, options, codonOptimizeGenerator).getDocument();

            //updates nucleotide info for the modified sequence now that the codon optimized sequence has been generated
            charSequence = codonOptimizedSequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence);

            //sanity check
            Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());

            //Stops the program if there are no longer any changes being made to the sequence
            if(CharSequenceUtilities.equals(storedSeq,charSequence)){
                Dialogs.showMessageDialog​("Sequence was not further optimized");
                break;
            }
    }

        //Saves the codon optimized sequence
        ((EditableSequenceDocument) sequence).setSequenceAndAnnotations(codonOptimizedSequence.getCharSequence(), SequenceUtilities.getAnnotationsOfType((SequenceDocument)codonOptimizedSequence, "TYPE_OPTIMIZED_CODON"));
        sequence.setName(sequence.getName().replace("(original)", "(optimized)"));
    }


    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a codon optimized AnnotatedPluginDocument
    *Uses CodonOptimizationSequenceAnnotationGenerator and displays the general options for this annotation generator so user can select forbidden restriction sites.
    *@param sequence the sequence to generate codon optimized annotations for.
    *@throws DocumentOperationException.
    */
    public static AnnotatedPluginDocument codonOptimize(DefaultSequenceDocument sequence, Options options, SequenceAnnotationGenerator codonOptimizeGenerator) throws DocumentOperationException{
    //Creates an array to store the sequence as an AnnotatedPluginDocument
        AnnotatedPluginDocument[] sequenceDocument = new AnnotatedPluginDocument[1];
        sequenceDocument[0] = DocumentUtilities.createAnnotatedPluginDocument(sequence);
        
        //Creates the SelectionRange for the annotation generator to be applied
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Annotation generator is applied to the set of sequenceDocuments within the selection range and generates a set of codon optimized sequence documents
        List<SequenceAnnotationGenerator.AnnotationGeneratorResult> results = codonOptimizeGenerator.generate(sequenceDocument, selectionRange, ProgressListener.EMPTY, options);
        List<AnnotatedPluginDocument> optimizedDocuments = results.get(0).getGeneratedDocuments();

        return optimizedDocuments.get(0);
    }
    0
  • K J

    Hi Jonas!  Thanks for your response.  I tried adding the line of code you suggested into my 'codonOptimize' function and kept everything else the same.  This did not seem to fix the problem as the loop still appears to produce the same document.  Any further help would be greatly appreciated!

    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a codon optimized AnnotatedPluginDocument
    *@param sequence the sequence to generate codon optimized annotations for.
    *@param options the general options for the annotation generator so user can select forbidden restriction sites.
    *@param CodonOptimizationSequenceAnnotationGenerator the sequence generator 
    *@throws DocumentOperationException.
    */
    public static AnnotatedPluginDocument codonOptimize(DefaultSequenceDocument sequence, Options options, SequenceAnnotationGenerator codonOptimizeGenerator) throws DocumentOperationException{
        
        //Update seed value for randomly changing codons
        options.setStringValue("seedValue", "" + new Random().nextInt());
        
        //Creates an array to store the sequence as an AnnotatedPluginDocument
        AnnotatedPluginDocument[] sequenceDocument = new AnnotatedPluginDocument[1];
        sequenceDocument[0] = DocumentUtilities.createAnnotatedPluginDocument(sequence);
        
        //Creates the SelectionRange for the annotation generator to be applied
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);
        
        //Annotation generator is applied to the set of sequenceDocuments within the selection range and generates a set of codon optimized sequence documents
        List<SequenceAnnotationGenerator.AnnotationGeneratorResult> results = codonOptimizeGenerator.generate(sequenceDocument, selectionRange, ProgressListener.EMPTY, options);
        List<AnnotatedPluginDocument> optimizedDocuments = results.get(0).getGeneratedDocuments();
        
        return optimizedDocuments.get(0);
    }
    0
  • K J

    Hi there! 

    Just wanted to follow up on my previous comment.  Any help would be appreciated!  I tried to see if I could "print" the "seedValue" after we set it, but the compiler said it did not recognize the symbol "seedValue".  Maybe the optionName is wrong and that is causing "setStringValue" to return "FALSE"?

    Thanks in advance!

    0
  • Jonas Kuhn

    Hi KJ, 

    apologies for the delay, and Happy New Year. 

    You're indeed correct, there were two issues with my previous suggestion:

    a) the option is nested inside the 'advancedOptions' panel, so the name needs to be adjusted to that
    b) the option is by default disabled, and the disabled value needs to be set in addition to the 'active' value.

    This code should work:

    Options.IntegerOption seedValue = (Options.IntegerOption) options.getOption("advancedOptions.seedValue");
    seedValue.setDisabledValue(randomSeed);
    seedValue.setValue(randomSeed);

     

    On another note:

    It might be that the sequence finds two local minimas that it would just always swap between when optimizing, so it is possible that your loop will never end.
    Best to have some sort of detection of that state as well; e.g. by keeping all the sequences in a list and checking whether it has already encountered one of them (as long as those aren't too large to be kept in memory). 
    Alternatively comparing the GC counts might also work.

    0
  • K J

    Hi Jonas,

    Happy New Year!  Thanks so much for your response.

    I copied the code your provided, but unfortunately I am running into a similar compilation error as before.  I have attached my full code below for your reference.  Please let me know if you have any suggestions to fix this error!

     

    Also, thanks for the suggestions of storing the sequences in a list.  I will try and implement that in the future, but for now I added a second condition that will break the while loop after 100 repetitions.

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *modifySequence takes in a DefaultSequenceDocument, makes a copy, and modifies the copy of the sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1%, the sequence will be repeatedly codon optimized.
    *@param sequence the sequence to modify.
    *@throws DocumentOperationException.
    */
    public static void modifyCopyOfSequence(DefaultSequenceDocument sequence)throws DocumentOperationException{
        //Creates the annotation generator
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();

        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
      });

        //codon optimize at least once to remove restriction sites
        DefaultSequenceDocument codonOptimizedSequence = (DefaultSequenceDocument)codonOptimize(sequence, options, codonOptimizeGenerator).getDocument();

        //set up to use getPercentGC()
        SequenceCharSequence charSequence = codonOptimizedSequence.getCharSequence();
        NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

        //Sanity Check
        Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());

        //Counter for the number of loops performed
        int numberOfLoopsCompleted = 0;
        while(DNA_NucleotideInfo.getPercentGC() > 55.1){
            //stores the char sequence before the new round of optimization
            SequenceCharSequence storedSeq = charSequence;

            //codon optimizes
            codonOptimizedSequence = (DefaultSequenceDocument)codonOptimize(codonOptimizedSequence, options, codonOptimizeGenerator).getDocument();

            //updates nucleotide info for the modified sequence now that the codon optimized sequence has been generated
            charSequence = codonOptimizedSequence.getCharSequence();
            DNA_NucleotideInfo = new NucleotideCounter(charSequence);

            //sanity check
            Dialogs.showMessageDialog​("GC%:" + DNA_NucleotideInfo.getPercentGC());

            //Updates counter
            numberOfLoopsCompleted++;

            //Stops the program if there are no longer any changes being made to the sequence or if number of loops is > 100
            if(CharSequenceUtilities.equals(storedSeq,charSequence) || numberOfLoopsCompleted > 100){
                Dialogs.showMessageDialog​("Sequence was not further optimized");
                break;
            }

        }

        //Saves the codon optimized sequence
        ((EditableSequenceDocument) sequence).setSequenceAndAnnotations(codonOptimizedSequence.getCharSequence(), SequenceUtilities.getAnnotationsOfType((SequenceDocument)codonOptimizedSequence, "TYPE_OPTIMIZED_CODON"));
        sequence.setName(sequence.getName().replace("(original)", "(optimized)"));
    }

    /**
    *codonOptimize takes in a DefaultSequenceDocument and returns a codon optimized AnnotatedPluginDocument
    *@param sequence the sequence to generate codon optimized annotations for.
    *@param options the general options for the annotation generator so user can select forbidden restriction sites.
    *@param CodonOptimizationSequenceAnnotationGenerator the sequence generator 
    *@throws DocumentOperationException.
    */
    public static AnnotatedPluginDocument codonOptimize(DefaultSequenceDocument sequence, Options options, SequenceAnnotationGenerator codonOptimizeGenerator) throws DocumentOperationException{
        //Update seed value for randomly changing codons
        Options.IntegerOption seedValue = (Options.IntegerOption) options.getOption("advancedOptions.seedValue");
        seedValue.setDisabledValue(randomSeed);
        seedValue.setValue(randomSeed);

        //Creates an array to store the sequence as an AnnotatedPluginDocument
        AnnotatedPluginDocument[] sequenceDocument = new AnnotatedPluginDocument[1];
        sequenceDocument[0] = DocumentUtilities.createAnnotatedPluginDocument(sequence);

        //Creates the SelectionRange for the annotation generator to be applied
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Annotation generator is applied to the set of sequenceDocuments within the selection range and generates a set of codon optimized sequence documents
        List<SequenceAnnotationGenerator.AnnotationGeneratorResult> results = codonOptimizeGenerator.generate(sequenceDocument, selectionRange, ProgressListener.EMPTY, options);
        List<AnnotatedPluginDocument> optimizedDocuments = results.get(0).getGeneratedDocuments();

        return optimizedDocuments.get(0);
    }

     

    0
  • Ashfaq Indragadia

    Hi KJ,

    Looks like 'randomSeed' field is not created. You can add the below line on top of the code block:
    int randomSeed = new Random().nextInt();

    0
  • K J

    Thank you so much everyone for all of your help!  My code now works as desired and should be very helpful for my workflows going forward.  I have attached the final code below for reference in case anyone in the future would like to do something similar.  Thanks again for all the help!

    //Import packages
    import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.DefaultSequenceListDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.NucleotideSequenceDocument;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceCharSequence;
    import com.biomatters.geneious.publicapi.documents.sequence.SequenceDocument;
    import com.biomatters.geneious.publicapi.implementations.SequenceExtractionUtilities;
    import com.biomatters.geneious.publicapi.implementations.sequence.DefaultSequenceDocument;

    /**
    *performOperation takes in a list of AnnotatedPluginDocument and modifies each sequence by codon optimizing it at least once.  
    *While the GC% of the codon optimized sequence is greater than 55.1% or the number of rounds is < 100, the sequence will be repeatedly codon optimized.
    *@param documents the list of AnnotatedPluginDocument to modify.
    *@throws DocumentOperationException.
    */
    public static List<AnnotatedPluginDocument> performOperation(List<AnnotatedPluginDocument> documents, Options choices,
                                                          ProgressListener progressListener) throws DocumentOperationException {
        //Creates the output list
        List<AnnotatedPluginDocument> codonOptimizedDocuments = new ArrayList<AnnotatedPluginDocument>();

        //Creates the annotation generator
        SequenceAnnotationGenerator codonOptimizeGenerator = PluginUtilities.getSequenceAnnotationGenerator("com.biomatters.plugins.codonOptimization.CodonOptimizationSequenceAnnotationGenerator");

        //Options: allow user to select enzymes and codon usage table
        Options options = codonOptimizeGenerator.getGeneralOptions();

        //Displays options to the user
        ThreadUtilities.invokeNowOrWait(() -> {
            Dialogs.showOptionsDialog(options,"Choose Annotation",true);
        });

        for (SequenceDocument sequence : SequenceUtilities.getSequences(documents, Alphabet.NUCLEOTIDE, progressListener)) {
            //codon optimize at least once to remove restriction sites
            AnnotatedPluginDocument codonOptimizedAnnotated = codonOptimize(sequence, options, codonOptimizeGenerator);
            SequenceDocument codonOptimizedSequence = (SequenceDocument)codonOptimizedAnnotated.getDocument();

            //set up to use getPercentGC()
            SequenceCharSequence charSequence = codonOptimizedSequence.getCharSequence();
            NucleotideCounter DNA_NucleotideInfo = new NucleotideCounter(charSequence);

            //Counter for the number of loops performed
            int numberOfLoopsCompleted = 0;
            while(DNA_NucleotideInfo.getPercentGC() > 55.1){
                //stores the char sequence before the new round of optimization
                SequenceCharSequence storedSeq = charSequence;

                //codon optimizes
                codonOptimizedAnnotated = codonOptimize(codonOptimizedSequence, options, codonOptimizeGenerator);
                codonOptimizedSequence = (SequenceDocument)codonOptimizedAnnotated.getDocument();

                //updates nucleotide info for the modified sequence now that the codon optimized sequence has been generated
                charSequence = codonOptimizedSequence.getCharSequence();
                DNA_NucleotideInfo = new NucleotideCounter(charSequence);

                //Updates counter
                numberOfLoopsCompleted++;

                //Stops the program if there are no longer any changes being made to the sequence or if number of loops is > 100
              if(CharSequenceUtilities.equals(storedSeq,charSequence) || numberOfLoopsCompleted > 100){
                   Dialogs.showMessageDialog​("Sequence was not further optimized");
    break;
              }
          }

            //Saves the codon optimized sequence
            codonOptimizedAnnotated.setName(sequence.getName().replace("(original)", "(optimized)"));

            codonOptimizedDocuments.add(codonOptimizedAnnotated);
        }

        return codonOptimizedDocuments;
    }


    /**
    *codonOptimize takes in a SequenceDocument and returns a codon optimized AnnotatedPluginDocument
    *@param sequence the sequence to generate codon optimized annotations for.
    *@param options the general options for the annotation generator so user can select forbidden restriction sites.
    *@param codonOptimizationSequenceAnnotationGenerator the sequence generator 
    *@throws DocumentOperationException.
    */
    public static AnnotatedPluginDocument codonOptimize(SequenceDocument sequence, Options options, SequenceAnnotationGenerator codonOptimizeGenerator) throws DocumentOperationException{

        //Update seed value for randomly changing codons
        Options.IntegerOption seedValue = (Options.IntegerOption) options.getOption("advancedOptions.seedValue");
        int randomSeed = new Random().nextInt();
        seedValue.setDisabledValue(randomSeed);
        seedValue.setValue(randomSeed);

        //Creates an array to store the sequence as an AnnotatedPluginDocument
        AnnotatedPluginDocument[] sequenceDocument = new AnnotatedPluginDocument[1];
        sequenceDocument[0] = DocumentUtilities.createAnnotatedPluginDocument(sequence);

        //Creates the SelectionRange for the annotation generator to be applied
        SequenceAnnotationGenerator.SelectionRange selectionRange = new SequenceAnnotationGenerator.SelectionRange(0, 0, 0, sequence.getSequenceLength() - 1);

        //Annotation generator is applied to the set of sequenceDocuments within the selection range and generates a set of codon optimized sequence documents
        List<SequenceAnnotationGenerator.AnnotationGeneratorResult> results = codonOptimizeGenerator.generate(sequenceDocument, selectionRange, ProgressListener.EMPTY, options);
        List<AnnotatedPluginDocument> optimizedDocuments = results.get(0).getGeneratedDocuments();

        return optimizedDocuments.get(0);
    }
    0

Please sign in to leave a comment.