JAL-1632 remove unused check for sequences aligned
[jalview.git] / src / jalview / gui / PCAPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import jalview.analysis.scoremodels.ScoreModels;
24 import jalview.analysis.scoremodels.SimilarityParams;
25 import jalview.api.analysis.ScoreModelI;
26 import jalview.api.analysis.SimilarityParamsI;
27 import jalview.api.analysis.ViewBasedAnalysisI;
28 import jalview.bin.Cache;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.AlignmentView;
32 import jalview.datamodel.ColumnSelection;
33 import jalview.datamodel.SequenceI;
34 import jalview.jbgui.GPCAPanel;
35 import jalview.util.MessageManager;
36 import jalview.viewmodel.AlignmentViewport;
37 import jalview.viewmodel.PCAModel;
38
39 import java.awt.BorderLayout;
40 import java.awt.Color;
41 import java.awt.Graphics;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.ActionListener;
44 import java.awt.print.PageFormat;
45 import java.awt.print.Printable;
46 import java.awt.print.PrinterException;
47 import java.awt.print.PrinterJob;
48
49 import javax.swing.ButtonGroup;
50 import javax.swing.JCheckBoxMenuItem;
51 import javax.swing.JColorChooser;
52 import javax.swing.JMenuItem;
53 import javax.swing.JRadioButtonMenuItem;
54 import javax.swing.event.InternalFrameAdapter;
55 import javax.swing.event.InternalFrameEvent;
56
57 /**
58  * DOCUMENT ME!
59  * 
60  * @author $author$
61  * @version $Revision$
62  */
63 public class PCAPanel extends GPCAPanel implements Runnable,
64         IProgressIndicator
65 {
66
67   private IProgressIndicator progressBar;
68
69   RotatableCanvas rc;
70
71   AlignmentPanel ap;
72
73   AlignmentViewport av;
74
75   PCAModel pcaModel;
76
77   int top = 0;
78
79   /**
80    * Creates a new PCAPanel object using default score model and parameters
81    * 
82    * @param alignPanel
83    */
84   public PCAPanel(AlignmentPanel alignPanel)
85   {
86     this(alignPanel, ScoreModels.getInstance().getDefaultModel(
87             !alignPanel.av.getAlignment().isNucleotide()),
88             SimilarityParams.SeqSpace);
89   }
90
91   /**
92    * Constructor given sequence data, a similarity (or distance) score model,
93    * and score calculation parameters
94    * 
95    * @param alignPanel
96    * @param scoreModel
97    * @param params
98    */
99   public PCAPanel(AlignmentPanel alignPanel, ScoreModelI scoreModel,
100           SimilarityParamsI params)
101   {
102     super();
103     this.av = alignPanel.av;
104     this.ap = alignPanel;
105     boolean nucleotide = av.getAlignment().isNucleotide();
106
107     progressBar = new ProgressBar(statusPanel, statusBar);
108
109     addInternalFrameListener(new InternalFrameAdapter()
110     {
111       @Override
112       public void internalFrameClosed(InternalFrameEvent e)
113       {
114         close_actionPerformed();
115       }
116     });
117
118     boolean selected = av.getSelectionGroup() != null
119             && av.getSelectionGroup().getSize() > 0;
120     AlignmentView seqstrings = av.getAlignmentView(selected);
121     SequenceI[] seqs;
122     if (!selected)
123     {
124       seqs = av.getAlignment().getSequencesArray();
125     }
126     else
127     {
128       seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
129     }
130
131     pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel,
132             params);
133     PaintRefresher.Register(this, av.getSequenceSetId());
134
135     rc = new RotatableCanvas(alignPanel);
136     this.getContentPane().add(rc, BorderLayout.CENTER);
137     Thread worker = new Thread(this);
138     worker.start();
139   }
140
141   /**
142    * Ensure references to potentially very large objects (the PCA matrices) are
143    * nulled when the frame is closed
144    */
145   protected void close_actionPerformed()
146   {
147     pcaModel = null;
148   }
149
150   /**
151    * Repopulate the options and actions under the score model menu when it is
152    * selected. Options will depend on whether 'nucleotide' or 'peptide'
153    * modelling is selected (and also possibly on whether any additional score
154    * models have been added).
155    */
156   @Override
157   protected void scoreModel_menuSelected()
158   {
159     scoreModelMenu.removeAll();
160     for (final ScoreModelI sm : ScoreModels.getInstance().getModels())
161     {
162       final String name = sm.getName();
163       JCheckBoxMenuItem jm = new JCheckBoxMenuItem(name);
164
165       /*
166        * if the score model doesn't provide a description, try to look one
167        * up in the text bundle, falling back on its name
168        */
169       String tooltip = sm.getDescription();
170       if (tooltip == null)
171       {
172         tooltip = MessageManager.getStringOrReturn("label.score_model_",
173                 name);
174       }
175       jm.setToolTipText(tooltip);
176       jm.setSelected(pcaModel.getScoreModelName().equals(name));
177       if ((pcaModel.isNucleotide() && sm.isDNA())
178               || (!pcaModel.isNucleotide() && sm.isProtein()))
179       {
180         jm.addActionListener(new ActionListener()
181         {
182           @Override
183           public void actionPerformed(ActionEvent e)
184           {
185             if (!pcaModel.getScoreModelName().equals(name))
186             {
187               ScoreModelI sm2 = configureScoreModel(sm);
188               pcaModel.setScoreModel(sm2);
189               Thread worker = new Thread(PCAPanel.this);
190               worker.start();
191             }
192           }
193         });
194         scoreModelMenu.add(jm);
195       }
196     }
197   }
198
199   @Override
200   public void bgcolour_actionPerformed(ActionEvent e)
201   {
202     Color col = JColorChooser.showDialog(this,
203             MessageManager.getString("label.select_background_colour"),
204             rc.bgColour);
205
206     if (col != null)
207     {
208       rc.bgColour = col;
209     }
210     rc.repaint();
211   }
212
213   /**
214    * DOCUMENT ME!
215    */
216   @Override
217   public void run()
218   {
219     long progId = System.currentTimeMillis();
220     IProgressIndicator progress = this;
221     String message = MessageManager.getString("label.pca_recalculating");
222     if (getParent() == null)
223     {
224       progress = ap.alignFrame;
225       message = MessageManager.getString("label.pca_calculating");
226     }
227     progress.setProgressBar(message, progId);
228     try
229     {
230       calcSettings.setEnabled(false);
231       pcaModel.run();
232       // ////////////////
233       xCombobox.setSelectedIndex(0);
234       yCombobox.setSelectedIndex(1);
235       zCombobox.setSelectedIndex(2);
236
237       pcaModel.updateRc(rc);
238       // rc.invalidate();
239       nuclSetting.setSelected(pcaModel.isNucleotide());
240       protSetting.setSelected(!pcaModel.isNucleotide());
241       top = pcaModel.getTop();
242
243     } catch (OutOfMemoryError er)
244     {
245       new OOMWarning("calculating PCA", er);
246       return;
247     } finally
248     {
249       progress.setProgressBar("", progId);
250     }
251     calcSettings.setEnabled(true);
252     repaint();
253     if (getParent() == null)
254     {
255       addKeyListener(rc);
256       Desktop.addInternalFrame(this, MessageManager
257               .getString("label.principal_component_analysis"), 475, 450);
258     }
259   }
260
261   @Override
262   protected void nuclSetting_actionPerfomed(ActionEvent arg0)
263   {
264     if (!pcaModel.isNucleotide())
265     {
266       pcaModel.setNucleotide(true);
267       pcaModel.setScoreModel(ScoreModels.getInstance().getDefaultModel(
268               false));
269       Thread worker = new Thread(this);
270       worker.start();
271     }
272
273   }
274
275   @Override
276   protected void protSetting_actionPerfomed(ActionEvent arg0)
277   {
278
279     if (pcaModel.isNucleotide())
280     {
281       pcaModel.setNucleotide(false);
282       pcaModel.setScoreModel(ScoreModels.getInstance()
283               .getDefaultModel(true));
284       Thread worker = new Thread(this);
285       worker.start();
286     }
287   }
288
289   /**
290    * DOCUMENT ME!
291    */
292   void doDimensionChange()
293   {
294     if (top == 0)
295     {
296       return;
297     }
298
299     int dim1 = top - xCombobox.getSelectedIndex();
300     int dim2 = top - yCombobox.getSelectedIndex();
301     int dim3 = top - zCombobox.getSelectedIndex();
302     pcaModel.updateRcView(dim1, dim2, dim3);
303     rc.img = null;
304     rc.rotmat.setIdentity();
305     rc.initAxes();
306     rc.paint(rc.getGraphics());
307   }
308
309   /**
310    * DOCUMENT ME!
311    * 
312    * @param e
313    *          DOCUMENT ME!
314    */
315   @Override
316   protected void xCombobox_actionPerformed(ActionEvent e)
317   {
318     doDimensionChange();
319   }
320
321   /**
322    * DOCUMENT ME!
323    * 
324    * @param e
325    *          DOCUMENT ME!
326    */
327   @Override
328   protected void yCombobox_actionPerformed(ActionEvent e)
329   {
330     doDimensionChange();
331   }
332
333   /**
334    * DOCUMENT ME!
335    * 
336    * @param e
337    *          DOCUMENT ME!
338    */
339   @Override
340   protected void zCombobox_actionPerformed(ActionEvent e)
341   {
342     doDimensionChange();
343   }
344
345   @Override
346   public void outputValues_actionPerformed(ActionEvent e)
347   {
348     CutAndPasteTransfer cap = new CutAndPasteTransfer();
349     try
350     {
351       cap.setText(pcaModel.getDetails());
352       Desktop.addInternalFrame(cap,
353               MessageManager.getString("label.pca_details"), 500, 500);
354     } catch (OutOfMemoryError oom)
355     {
356       new OOMWarning("opening PCA details", oom);
357       cap.dispose();
358     }
359   }
360
361   @Override
362   public void showLabels_actionPerformed(ActionEvent e)
363   {
364     rc.showLabels(showLabels.getState());
365   }
366
367   @Override
368   public void print_actionPerformed(ActionEvent e)
369   {
370     PCAPrinter printer = new PCAPrinter();
371     printer.start();
372   }
373
374   @Override
375   public void originalSeqData_actionPerformed(ActionEvent e)
376   {
377     // this was cut'n'pasted from the equivalent TreePanel method - we should
378     // make this an abstract function of all jalview analysis windows
379     if (pcaModel.getSeqtrings() == null)
380     {
381       jalview.bin.Cache.log
382               .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
383       return;
384     }
385     // decide if av alignment is sufficiently different to original data to
386     // warrant a new window to be created
387     // create new alignmnt window with hidden regions (unhiding hidden regions
388     // yields unaligned seqs)
389     // or create a selection box around columns in alignment view
390     // test Alignment(SeqCigar[])
391     char gc = '-';
392     try
393     {
394       // we try to get the associated view's gap character
395       // but this may fail if the view was closed...
396       gc = av.getGapCharacter();
397     } catch (Exception ex)
398     {
399     }
400     ;
401     Object[] alAndColsel = pcaModel.getSeqtrings()
402             .getAlignmentAndColumnSelection(gc);
403
404     if (alAndColsel != null && alAndColsel[0] != null)
405     {
406       // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
407
408       AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]);
409       AlignmentI dataset = (av != null && av.getAlignment() != null) ? av
410               .getAlignment().getDataset() : null;
411       if (dataset != null)
412       {
413         al.setDataset(dataset);
414       }
415
416       if (true)
417       {
418         // make a new frame!
419         AlignFrame af = new AlignFrame(al,
420                 (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
421                 AlignFrame.DEFAULT_HEIGHT);
422
423         // >>>This is a fix for the moment, until a better solution is
424         // found!!<<<
425         // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
426
427         // af.addSortByOrderMenuItem(ServiceName + " Ordering",
428         // msaorder);
429
430         Desktop.addInternalFrame(af, MessageManager.formatMessage(
431                 "label.original_data_for_params",
432                 new String[] { this.title }), AlignFrame.DEFAULT_WIDTH,
433                 AlignFrame.DEFAULT_HEIGHT);
434       }
435     }
436     /*
437      * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
438      * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
439      * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
440      * "\n"); }
441      * 
442      * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
443      */
444   }
445
446   class PCAPrinter extends Thread implements Printable
447   {
448     @Override
449     public void run()
450     {
451       PrinterJob printJob = PrinterJob.getPrinterJob();
452       PageFormat pf = printJob.pageDialog(printJob.defaultPage());
453
454       printJob.setPrintable(this, pf);
455
456       if (printJob.printDialog())
457       {
458         try
459         {
460           printJob.print();
461         } catch (Exception PrintException)
462         {
463           PrintException.printStackTrace();
464         }
465       }
466     }
467
468     @Override
469     public int print(Graphics pg, PageFormat pf, int pi)
470             throws PrinterException
471     {
472       pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
473
474       rc.drawBackground(pg, rc.bgColour);
475       rc.drawScene(pg);
476       if (rc.drawAxes == true)
477       {
478         rc.drawAxes(pg);
479       }
480
481       if (pi == 0)
482       {
483         return Printable.PAGE_EXISTS;
484       }
485       else
486       {
487         return Printable.NO_SUCH_PAGE;
488       }
489     }
490   }
491
492   /**
493    * DOCUMENT ME!
494    * 
495    * @param e
496    *          DOCUMENT ME!
497    */
498   @Override
499   public void eps_actionPerformed(ActionEvent e)
500   {
501     makePCAImage(jalview.util.ImageMaker.TYPE.EPS);
502   }
503
504   /**
505    * DOCUMENT ME!
506    * 
507    * @param e
508    *          DOCUMENT ME!
509    */
510   @Override
511   public void png_actionPerformed(ActionEvent e)
512   {
513     makePCAImage(jalview.util.ImageMaker.TYPE.PNG);
514   }
515
516   void makePCAImage(jalview.util.ImageMaker.TYPE type)
517   {
518     int width = rc.getWidth();
519     int height = rc.getHeight();
520
521     jalview.util.ImageMaker im;
522
523     if (type == jalview.util.ImageMaker.TYPE.PNG)
524     {
525       im = new jalview.util.ImageMaker(this,
526               jalview.util.ImageMaker.TYPE.PNG, "Make PNG image from PCA",
527               width, height, null, null, null, 0, false);
528     }
529     else if (type == jalview.util.ImageMaker.TYPE.EPS)
530     {
531       im = new jalview.util.ImageMaker(this,
532               jalview.util.ImageMaker.TYPE.EPS, "Make EPS file from PCA",
533               width, height, null, this.getTitle(), null, 0, false);
534     }
535     else
536     {
537       im = new jalview.util.ImageMaker(this,
538               jalview.util.ImageMaker.TYPE.SVG, "Make SVG file from PCA",
539               width, height, null, this.getTitle(), null, 0, false);
540
541     }
542
543     if (im.getGraphics() != null)
544     {
545       rc.drawBackground(im.getGraphics(), Color.black);
546       rc.drawScene(im.getGraphics());
547       if (rc.drawAxes == true)
548       {
549         rc.drawAxes(im.getGraphics());
550       }
551       im.writeImage();
552     }
553   }
554
555   @Override
556   public void viewMenu_menuSelected()
557   {
558     buildAssociatedViewMenu();
559   }
560
561   void buildAssociatedViewMenu()
562   {
563     AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
564             .getSequenceSetId());
565     if (aps.length == 1 && rc.av == aps[0].av)
566     {
567       associateViewsMenu.setVisible(false);
568       return;
569     }
570
571     associateViewsMenu.setVisible(true);
572
573     if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
574     {
575       viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
576     }
577
578     associateViewsMenu.removeAll();
579
580     JRadioButtonMenuItem item;
581     ButtonGroup buttonGroup = new ButtonGroup();
582     int i, iSize = aps.length;
583     final PCAPanel thisPCAPanel = this;
584     for (i = 0; i < iSize; i++)
585     {
586       final AlignmentPanel ap = aps[i];
587       item = new JRadioButtonMenuItem(ap.av.viewName, ap.av == rc.av);
588       buttonGroup.add(item);
589       item.addActionListener(new ActionListener()
590       {
591         @Override
592         public void actionPerformed(ActionEvent evt)
593         {
594           rc.applyToAllViews = false;
595           rc.av = ap.av;
596           rc.ap = ap;
597           PaintRefresher.Register(thisPCAPanel, ap.av.getSequenceSetId());
598         }
599       });
600
601       associateViewsMenu.add(item);
602     }
603
604     final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
605
606     buttonGroup.add(itemf);
607
608     itemf.setSelected(rc.applyToAllViews);
609     itemf.addActionListener(new ActionListener()
610     {
611       @Override
612       public void actionPerformed(ActionEvent evt)
613       {
614         rc.applyToAllViews = itemf.isSelected();
615       }
616     });
617     associateViewsMenu.add(itemf);
618
619   }
620
621   /*
622    * (non-Javadoc)
623    * 
624    * @see
625    * jalview.jbgui.GPCAPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
626    * )
627    */
628   @Override
629   protected void outputPoints_actionPerformed(ActionEvent e)
630   {
631     CutAndPasteTransfer cap = new CutAndPasteTransfer();
632     try
633     {
634       cap.setText(pcaModel.getPointsasCsv(false,
635               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
636               zCombobox.getSelectedIndex()));
637       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
638               "label.points_for_params", new String[] { this.getTitle() }),
639               500, 500);
640     } catch (OutOfMemoryError oom)
641     {
642       new OOMWarning("exporting PCA points", oom);
643       cap.dispose();
644     }
645   }
646
647   /*
648    * (non-Javadoc)
649    * 
650    * @see
651    * jalview.jbgui.GPCAPanel#outputProjPoints_actionPerformed(java.awt.event
652    * .ActionEvent)
653    */
654   @Override
655   protected void outputProjPoints_actionPerformed(ActionEvent e)
656   {
657     CutAndPasteTransfer cap = new CutAndPasteTransfer();
658     try
659     {
660       cap.setText(pcaModel.getPointsasCsv(true,
661               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
662               zCombobox.getSelectedIndex()));
663       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
664               "label.transformed_points_for_params",
665               new String[] { this.getTitle() }), 500, 500);
666     } catch (OutOfMemoryError oom)
667     {
668       new OOMWarning("exporting transformed PCA points", oom);
669       cap.dispose();
670     }
671   }
672
673   /*
674    * (non-Javadoc)
675    * 
676    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
677    */
678   @Override
679   public void setProgressBar(String message, long id)
680   {
681     progressBar.setProgressBar(message, id);
682     // if (progressBars == null)
683     // {
684     // progressBars = new Hashtable();
685     // progressBarHandlers = new Hashtable();
686     // }
687     //
688     // JPanel progressPanel;
689     // Long lId = new Long(id);
690     // GridLayout layout = (GridLayout) statusPanel.getLayout();
691     // if (progressBars.get(lId) != null)
692     // {
693     // progressPanel = (JPanel) progressBars.get(new Long(id));
694     // statusPanel.remove(progressPanel);
695     // progressBars.remove(lId);
696     // progressPanel = null;
697     // if (message != null)
698     // {
699     // statusBar.setText(message);
700     // }
701     // if (progressBarHandlers.contains(lId))
702     // {
703     // progressBarHandlers.remove(lId);
704     // }
705     // layout.setRows(layout.getRows() - 1);
706     // }
707     // else
708     // {
709     // progressPanel = new JPanel(new BorderLayout(10, 5));
710     //
711     // JProgressBar progressBar = new JProgressBar();
712     // progressBar.setIndeterminate(true);
713     //
714     // progressPanel.add(new JLabel(message), BorderLayout.WEST);
715     // progressPanel.add(progressBar, BorderLayout.CENTER);
716     //
717     // layout.setRows(layout.getRows() + 1);
718     // statusPanel.add(progressPanel);
719     //
720     // progressBars.put(lId, progressPanel);
721     // }
722     // // update GUI
723     // // setMenusForViewport();
724     // validate();
725   }
726
727   @Override
728   public void registerHandler(final long id,
729           final IProgressIndicatorHandler handler)
730   {
731     progressBar.registerHandler(id, handler);
732     // if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
733     // {
734     // throw new
735     // Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
736     // }
737     // progressBarHandlers.put(new Long(id), handler);
738     // final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
739     // if (handler.canCancel())
740     // {
741     // JButton cancel = new JButton(
742     // MessageManager.getString("action.cancel"));
743     // final IProgressIndicator us = this;
744     // cancel.addActionListener(new ActionListener()
745     // {
746     //
747     // @Override
748     // public void actionPerformed(ActionEvent e)
749     // {
750     // handler.cancelActivity(id);
751     // us.setProgressBar(MessageManager.formatMessage("label.cancelled_params",
752     // new String[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
753     // }
754     // });
755     // progressPanel.add(cancel, BorderLayout.EAST);
756     // }
757   }
758
759   /**
760    * 
761    * @return true if any progress bars are still active
762    */
763   @Override
764   public boolean operationInProgress()
765   {
766     return progressBar.operationInProgress();
767   }
768
769   @Override
770   protected void resetButton_actionPerformed(ActionEvent e)
771   {
772     int t = top;
773     top = 0; // ugly - prevents dimensionChanged events from being processed
774     xCombobox.setSelectedIndex(0);
775     yCombobox.setSelectedIndex(1);
776     top = t;
777     zCombobox.setSelectedIndex(2);
778   }
779
780   /**
781    * If the score model is one that requires to get state data from the current
782    * view, allow it to do so
783    * 
784    * @param sm
785    * @return
786    */
787   protected ScoreModelI configureScoreModel(ScoreModelI sm)
788   {
789     if (sm instanceof ViewBasedAnalysisI)
790     {
791       try
792       {
793         sm = sm.getClass().newInstance();
794         ((ViewBasedAnalysisI) sm).configureFromAlignmentView(ap);
795       } catch (Exception q)
796       {
797         Cache.log.error("Couldn't create a scoremodel instance for "
798                 + sm.getName());
799       }
800     }
801     return sm;
802   }
803 }