Model sharing in app
Hi,
Due to the modularization of Geneious It's not clear how one would go about using and sharing a data model.
Let's take this example.
I have a model that is expensive to calculate. It's used for drawing graphs as well as statistics.
It needs to know the content and order all sequences in the viewer for the calculations.
It's dependent on the graph options, plugin preferences and on the content and order of sequences so it needs to be refreshed when this change.
It needs to be loaded before the graphics draw is called.
Given our understanding of the architecture at this point the only possibility is duplication of data, different constructors for the different places and multiple places that refresh needs to be done. None of these is really acceptable for a good quality code.
-
Unfortunately, yes if you want something to show in the statistics and graph sections that is calculated on demand, you can't share that data between the statistics and graphs.
For data that is expensive to calculate, you may want to consider implementing it as a DocumentOperation which adds the data as a custom field (using AnnotatedPluginDocument.setFieldValue or setHiddenFieldValue) or DocumentNote (using AnnotatedPluginDocument.getDocumentNotes) to the document. Then your graph and statistics modules can both use that data and there is no need to recalculate the data each time the document is viewed.
Best regards, Matt.
0 -
And how would I get a hold of that custom field from the the other modules? The draw in graph does not give access to the AnnotatedPluginDocument.
0 -
Hi Adrian,
Sorry for the slow response, I overlooked your reply until now.
You would need to implement your graph as a document based graph. See SequenceGraphFactory.createDocumentBasedGraphForAlignment or SequenceGraphFactory.createDocumentBasedGraphForSequence
Best regards, Matt.
0 -
Hi Matt,
Yes, I already did that. That in turn forces me to use the CrossoverSequenceGraph(AnnotatedPluginDocument constructor:
public CrossoverSequenceGraph(SequenceDocument.Alphabet alphabet) {
System.out.println("Old constructor called");
}
public CrossoverSequenceGraph(AnnotatedPluginDocument annotatedPluginDocument, boolean chimeraIsFirst) {
This new constructor does not seem to force the call toperformBackgroundCalculations(null) so I have to call it explicitly in the constructor which seems to work but it's probably be incorrect because it might be on a wrong thread besides having a large calculation in the constructor.
Cheers,
Adrian0 -
Hi Adrian,
SequenceGraph.performBackgroundCalculations is only called if SequenceGraph.getApproximateCalculationWorkRequiredPerResidue() returns a sufficiently high value.
Sorry, I just noticed that our javadoc for performBackgroundCalculations didn't explain this (it was only explained under getApproximateCalculationWorkRequiredPerResidue) so I've improved the javadoc for the next release.
However, this also applies for non-document based graphs, so I'm a bit confused as to why your change of constructor is causing this. Can you confirm if you were implementing getApproximateCalculationWorkRequiredPerResidue?
Best regards,
Matt.
0 -
Hi Matt,
No, I was not aware of that method and I recall performBackgroundCalculation usually being called with some exceptions that almost seemed random, so it was unreliable.
Cheers,
Adrian
0 -
performBackgroundCalculations shouldn't ever be called by Geneious unless you are implementing getApproximateCalculationWorkRequiredPerResidue. So given you weren't implementing that, the only calls to it should have been when you specifically called it yourself, possibly from your constructor. So I'm not sure why you are seeing almost random calls. Geneious will recreate graphs when undo is used, so maybe that's what you were seeing.
I suggest you implement getApproximateCalculationWorkRequiredPerResidue to return Integer.MAX_VALUE and remove all your own calls to performBackgroundCalculations.
Best regards,
Matt.
0
Please sign in to leave a comment.
Comments
7 comments