1 /*
2  * Copyright (C) 2008  Genome Research Limited
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  *  @author: Tim Carver
19  */
20 
21 package uk.ac.sanger.artemis.circular;
22 
23 
24 import java.awt.BorderLayout;
25 import java.awt.Color;
26 import java.awt.Dimension;
27 import java.io.BufferedReader;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.FileNotFoundException;
31 import java.io.FileReader;
32 import java.io.IOException;
33 import java.io.InputStreamReader;
34 import java.net.MalformedURLException;
35 import java.net.URL;
36 import java.util.Vector;
37 import java.util.Hashtable;
38 
39 import javax.swing.Box;
40 import javax.swing.ButtonGroup;
41 import javax.swing.JLabel;
42 import javax.swing.JOptionPane;
43 import javax.swing.JPanel;
44 import javax.swing.JRadioButton;
45 import javax.swing.JScrollPane;
46 import javax.swing.JSeparator;
47 
48 import uk.ac.sanger.artemis.Entry;
49 import uk.ac.sanger.artemis.EntryGroup;
50 import uk.ac.sanger.artemis.EntryVector;
51 import uk.ac.sanger.artemis.Feature;
52 import uk.ac.sanger.artemis.FeatureVector;
53 import uk.ac.sanger.artemis.Options;
54 import uk.ac.sanger.artemis.SimpleEntryGroup;
55 import uk.ac.sanger.artemis.components.EntryFileDialog;
56 import uk.ac.sanger.artemis.components.MessageDialog;
57 import uk.ac.sanger.artemis.components.StickyFileChooser;
58 import uk.ac.sanger.artemis.components.SwingWorker;
59 import uk.ac.sanger.artemis.io.EntryInformation;
60 import uk.ac.sanger.artemis.io.EntryInformationException;
61 import uk.ac.sanger.artemis.io.Key;
62 import uk.ac.sanger.artemis.io.Location;
63 import uk.ac.sanger.artemis.io.MSPcrunchDocumentEntry;
64 import uk.ac.sanger.artemis.io.Range;
65 import uk.ac.sanger.artemis.io.RangeVector;
66 import uk.ac.sanger.artemis.sequence.Bases;
67 import uk.ac.sanger.artemis.sequence.NoSequenceException;
68 import uk.ac.sanger.artemis.util.Document;
69 import uk.ac.sanger.artemis.util.DocumentFactory;
70 import uk.ac.sanger.artemis.util.OutOfRangeException;
71 import uk.ac.sanger.artemis.util.ReadOnlyException;
72 import uk.ac.sanger.artemis.util.WorkingGZIPInputStream;
73 
74 
75 /**
76 * DNA draw wizard
77 */
78 public class Wizard
79 {
80   private DNADraw dna = null;
81 
82   public static Track TRACK_1 = new Track(0.95d, "CDS", "pseudo", false, true, false, null);
83   public static Track TRACK_2 = new Track(0.9d,  "CDS", "pseudo", false, false, true, null);
84   public static Track TRACK_3 = new Track(0.85d, "CDS", "pseudo", true, true, true, null);
85   public static Track TRACK_4 = new Track(0.8d,  "misc_feature", true, true, null);
86   public static Track TRACK_5 = new Track(0.75d, null, true, true, null);
87 
88   private SwingWorker workerGraph;
89   public static Track[] tracks = { TRACK_1, TRACK_2, TRACK_3, TRACK_4, TRACK_5 };
90 
Wizard(DNADraw dna_current)91   public Wizard(DNADraw dna_current)
92   {
93     int n = getOption(dna_current);  // option 0 - read data file
94                                      // option 1 - edit existing dna
95                                      // option 2 - read template
96     if(n == 0)
97       dna = getDNADrawFromFile(dna_current);
98     else if(n == 2)
99     {
100       StickyFileChooser chooser = new StickyFileChooser();
101       chooser.showOpenDialog(null);
102 
103       File fileTemplate = chooser.getSelectedFile();
104       if(!fileTemplate.exists())
105         JOptionPane.showMessageDialog(null,
106             fileTemplate.getName()+" cannot be found!",
107             "Missing File", JOptionPane.WARNING_MESSAGE);
108       loadTemplate(chooser.getSelectedFile());
109     }
110     else if(n == 1)
111     {
112       Vector block = new Vector();
113       Vector restrictionEnzyme = new Vector();
114       if(dna_current == null)
115         dna = new DNADraw();
116       else
117       {
118         dna = dna_current;
119         block = dna_current.getGeneticMarker();
120         restrictionEnzyme = dna_current.getRestrictionEnzyme();
121       }
122 
123       LineAttribute la = new LineAttribute(dna);
124 
125       GeneticMarker gm;
126       if(dna_current != null)
127         gm = new GeneticMarker(dna_current,block);
128       else
129         gm = new GeneticMarker(dna,block);
130 
131       RestrictionEnzyme re;
132       if(dna_current != null)
133         re = new RestrictionEnzyme(dna_current,restrictionEnzyme);
134       else
135         re = new RestrictionEnzyme(dna,restrictionEnzyme);
136 
137       Ticks tk = new Ticks(dna_current,false);
138 
139       la.setMinimumSize(la.getPreferredSize());
140       la.setMaximumSize(la.getPreferredSize());
141 
142       re.setMinimumSize(re.getPreferredSize());
143       re.setMaximumSize(re.getPreferredSize());
144 
145       ScrollPanel pane = new ScrollPanel(new BorderLayout());
146       Box bdown = Box.createVerticalBox();
147       bdown.add(new JLabel("Properties"));
148       Box bacross = Box.createHorizontalBox();
149       bacross.add(la);
150       bacross.add(tk);
151       bacross.add(Box.createHorizontalGlue());
152       bdown.add(bacross);
153 
154       bdown.add(new JSeparator());
155       bdown.add(Box.createVerticalStrut(10));
156       bdown.add(new JLabel("Features"));
157       bacross = Box.createHorizontalBox();
158       bacross.add(gm);
159       bacross.add(Box.createHorizontalGlue());
160       bdown.add(bacross);
161 
162       bdown.add(new JSeparator());
163       bdown.add(Box.createVerticalStrut(10));
164       bdown.add(new JLabel("Restriction Enzymes"));
165       bacross = Box.createHorizontalBox();
166       bacross.add(re);
167       bacross.add(Box.createHorizontalGlue());
168       bdown.add(bacross);
169       pane.add(bdown,BorderLayout.CENTER);
170 
171       JScrollPane createWizScroll = new JScrollPane(pane);
172 
173       Dimension dscreen = createWizScroll.getToolkit().getScreenSize();
174       int wid = (int)dscreen.getWidth();
175       if(wid > 700)
176         wid = 700;
177 
178       int hgt = (int)dscreen.getHeight();
179       if(hgt > 750)
180         hgt = 700;
181       hgt-=50;
182 
183       Dimension d = new Dimension(wid,hgt);
184       createWizScroll.setPreferredSize(d);
185 
186       JOptionPane.showMessageDialog(null,
187                       createWizScroll, "DNA Wizard",
188                       JOptionPane.PLAIN_MESSAGE);
189 
190       dna.setGeneticMarker(block);
191       dna.setRestrictionEnzyme(restrictionEnzyme);
192       dna.setLineAttributes(la.getLineAttr());
193       dna.setStartTick(tk.getStartTick());
194       dna.setMinorTickInterval(tk.getMinorTickInterval());
195       dna.setTickInterval(tk.getTickInterval());
196 
197       int s = la.getStart();
198       dna.setStart(s);
199 
200       s = la.getEnd();
201       dna.setEnd(s);
202     }
203   }
204 
205   /**
206    * Open a DNA plot based on a template file
207    * @param template
208    */
Wizard(final String templateName)209   public Wizard(final String templateName)
210   {
211     loadTemplate(templateName);
212   }
213 
214   /**
215    * Load from a template file
216    * @param template
217    */
loadTemplate(final String templateName)218   private void loadTemplate(final String templateName)
219   {
220     final ProgressFrame progress = new ProgressFrame();
221     progress.setString("Reading from "+templateName+"   ");
222     progress.setValue(2);
223 
224     if(dna == null)
225       dna = new DNADraw();
226     Options.getOptions();
227     final BufferedReader inputStream = getReader(templateName);
228     loadTemplate(inputStream, templateName, progress);
229   }
230 
231   /**
232    * Load from a template file
233    * @param template
234    */
loadTemplate(final File templateFile)235   private void loadTemplate(final File templateFile)
236   {
237     final ProgressFrame progress = new ProgressFrame();
238     progress.setString("Reading from "+templateFile.getName()+"   ");
239     progress.setValue(2);
240 
241     if(dna == null)
242       dna = new DNADraw();
243     Options.getOptions();
244     FileReader reader;
245     try
246     {
247       reader = new FileReader(templateFile);
248       final BufferedReader inputStream = new BufferedReader(reader);
249       loadTemplate(inputStream, templateFile.getName(), progress);
250     }
251     catch(FileNotFoundException e)
252     {
253       e.printStackTrace();
254     }
255   }
256 
loadTemplate(final BufferedReader inputStream, final String templateName, final ProgressFrame progress)257   private void loadTemplate(final BufferedReader inputStream,
258                             final String templateName,
259                             final ProgressFrame progress)
260   {
261     try
262     {
263       final EntryGroup entryGroup = new SimpleEntryGroup();
264       final Hashtable fileEntrys = new Hashtable();
265       Vector v_tracks = new Vector();
266       String inLine = null;
267       String lineAttrStr[]  = null;
268       String tickMarksStr[] = null;
269       String gcGraphStr[]      = null;
270       String gcSkewGraphStr[]  = null;
271       String userGraphStr[]    = null;
272 
273       String lineAttrStart    = "# line attributes:";
274       String tickMarksStart   = "# tick marks:";
275       String gcGraphStart     = "# GC Graph:";
276       String gcSkewGraphStart = "# GC Skew Graph:";
277       String userGraphStart   = "# User Graph:";
278       String mergeBlastFeatures = "# merge.blast";
279 
280       while((inLine = inputStream.readLine()) != null)
281       {
282         if(inLine.startsWith("#") || inLine.trim().equals(""))
283         {
284           if(inLine.startsWith(lineAttrStart))
285             lineAttrStr = inLine.substring(lineAttrStart.length()).trim().split("[=\\s]");
286           else if(inLine.startsWith(tickMarksStart))
287             tickMarksStr = inLine.substring(tickMarksStart.length()).trim().split("[=\\s]");
288           else if(inLine.startsWith(gcGraphStart))
289             gcGraphStr = inLine.substring(gcGraphStart.length()).trim().split("[=\\s]");
290           else if(inLine.startsWith(gcSkewGraphStart))
291             gcSkewGraphStr = inLine.substring(gcSkewGraphStart.length()).trim().split("[=\\s]");
292           else if(inLine.startsWith(userGraphStart))
293             userGraphStr = inLine.substring(userGraphStart.length()).trim().split("[=\\s]");
294           else if(inLine.startsWith(mergeBlastFeatures))
295             System.setProperty("merge.blast", "true");
296           continue;
297         }
298 
299         String properties[] = inLine.split("\t");
300 
301         final String separator;
302         if (properties[11].indexOf ("://") != -1)
303           separator = "/";
304         else
305           separator = File.separator;
306         String fileName = properties[11] + separator  + properties[10];
307         Entry entry;
308         if(!fileEntrys.containsKey(fileName))
309         {
310           progress.setString("Reading "+properties[10]);
311           progress.setValue(4);
312           entry = getEntry(fileName, entryGroup);
313           if(entry == null)
314             continue;
315           fileEntrys.put(fileName, entry);
316         }
317         else
318         {
319           entry = (Entry)fileEntrys.get(fileName);
320         }
321 
322         Track track = new Track(.9,entry);
323         track.setPropertiesFromTemplate(inLine);
324         v_tracks.add(track);
325       }
326       inputStream.close();
327 
328       progress.setString("Read template "+templateName);
329       progress.setValue(7);
330       Track[] newTracks = new Track[v_tracks.size()];
331       for(int i=0; i<v_tracks.size(); i++)
332         newTracks[i] = (Track) v_tracks.get(i);
333 
334       Wizard.tracks = newTracks;
335 
336       dna.setArtemisEntryGroup(entryGroup);
337 
338       int sequenceLength = entryGroup.getSequenceEntry().getBases().getLength();
339 
340       Hashtable lineAttr = new Hashtable();
341       lineAttr.put("lsize", new Integer(1));
342       lineAttr.put("circular", new Boolean(true));
343       lineAttr.put("start", new Integer(0));
344       lineAttr.put("end", new Integer(sequenceLength));
345       if(lineAttrStr != null)
346       {
347         for(int i=0; i<lineAttrStr.length; i++)
348         {
349           if(lineAttrStr[i].startsWith("line_size"))
350             lineAttr.put("lsize", new Integer(lineAttrStr[i+1]));
351           else if(lineAttrStr[i].startsWith("circular"))
352             lineAttr.put("circular", new Boolean(lineAttrStr[i+1]));
353           else if(lineAttrStr[i].startsWith("line_height"))
354             dna.setLineHeight(Float.parseFloat(lineAttrStr[i+1]));
355           else if(lineAttrStr[i].startsWith("bases_per_line"))
356             dna.setBasesPerLine(Integer.parseInt(lineAttrStr[i+1]));
357         }
358       }
359       dna.setLineAttributes(lineAttr);
360 
361       final int div;
362       if(sequenceLength < 1000)
363         div = 100;
364       else if(sequenceLength < 10000)
365         div = 1000;
366       else if(sequenceLength < 100000)
367         div = 10000;
368       else
369         div = 100000;
370       int tick = sequenceLength / div;
371       tick = tick * (div / 10);
372       int tick2 = tick / 2;
373       tick = tick2 * 2;
374 
375       if(tickMarksStr != null)
376       {
377         for(int i=0; i<tickMarksStr.length; i++)
378         {
379           if(tickMarksStr[i].startsWith("major"))
380             tick = Integer.parseInt(tickMarksStr[i+1]);
381           else if(tickMarksStr[i].startsWith("minor"))
382             tick2 = Integer.parseInt(tickMarksStr[i+1]);
383         }
384       }
385 
386       dna.setGeneticMarker(new Vector());
387       dna.setRestrictionEnzyme(new Vector());
388       dna.setMinorTickInterval(tick2);
389       dna.setTickInterval(tick);
390 
391       TrackManager trackManager = dna.getTrackManager();
392       if(trackManager == null)
393       {
394         trackManager = new TrackManager(dna);
395         dna.setTrackManager(trackManager);
396       }
397       trackManager.update(tracks);
398 
399       final String[] this_gcGraphStr = gcGraphStr;
400       final String[] this_gcSkewGraphStr = gcSkewGraphStr;
401       final String[] this_userGraphStr = userGraphStr;
402       workerGraph = new SwingWorker()
403       {
404         public Object construct()
405         {
406           loadGraphs(this_gcGraphStr, this_gcSkewGraphStr, this_userGraphStr, dna, progress);
407           return null;
408         }
409       };
410     }
411     catch(FileNotFoundException e)
412     {
413       e.printStackTrace();
414     }
415     catch(IOException e)
416     {
417       e.printStackTrace();
418     }
419     catch(NoSequenceException e)
420     {
421       e.printStackTrace();
422     }
423   }
424 
425   /**
426    * Load graphs using template file details
427    * @param gcGraphStr
428    * @param gcSkewGraphStr
429    * @param userGraphStr
430    * @param dna
431    */
loadGraphs(final String gcGraphStr[], final String gcSkewGraphStr[], final String userGraphStr[], final DNADraw dna, final ProgressFrame progress)432   private void loadGraphs(final String gcGraphStr[],
433                           final String gcSkewGraphStr[],
434                           final String userGraphStr[],
435                           final DNADraw dna,
436                           final ProgressFrame progress)
437   {
438 
439     if(gcGraphStr != null)
440     {
441       if(progress != null)
442       {
443         progress.setString("Calculating GC graph points");
444       }
445       GCGraph gcGraph = new GCGraph(dna);
446       gcGraph.setOptionsStr(gcGraphStr);
447       dna.setGcGraph(gcGraph);
448       gcGraph.calcGraphValues();
449       dna.add(gcGraph);
450       dna.repaint();
451       dna.revalidate();
452     }
453     if(gcSkewGraphStr != null)
454     {
455       if(progress != null)
456       {
457         progress.setString("Calculating GC Skew graph points");
458         progress.setValue(8);
459       }
460       GCSkewGraph gcSkewGraph = new GCSkewGraph(dna);
461       gcSkewGraph.setOptionsStr(gcSkewGraphStr);
462       dna.setGcSkewGraph(gcSkewGraph);
463       gcSkewGraph.calcGraphValues();
464       dna.add(gcSkewGraph);
465       dna.repaint();
466       dna.revalidate();
467     }
468     if(userGraphStr != null)
469     {
470       String fileName = null;
471       for(int i=0;i<userGraphStr.length; i++)
472       {
473         if(userGraphStr[i].startsWith("file_name"))
474           fileName = userGraphStr[i+1];
475       }
476       //final uk.ac.sanger.artemis.util.Document document =
477       //  new uk.ac.sanger.artemis.util.FileDocument(new File(fileName));
478       try
479       {
480         if(progress != null)
481         {
482           progress.setString("Calculating user graph points");
483           progress.setValue(9);
484         }
485         UserGraph userGraph = new UserGraph(dna, fileName);
486         userGraph.setOptionsStr(userGraphStr);
487         dna.setUserGraph(userGraph);
488         userGraph.calcGraphValues();
489         dna.add(userGraph);
490         dna.repaint();
491         dna.revalidate();
492       }
493       catch(IOException e)
494       {
495         e.printStackTrace();
496         return;
497       }
498     }
499     progress.dispose();
500   }
501 
502   /**
503    * Return an Artemis entry from a file
504    * @param entryFileName
505    * @param entryGroup
506    * @return
507    * @throws NoSequenceException
508    */
getEntry(final String entryFileName, final EntryGroup entryGroup)509   private Entry getEntry(final String entryFileName, final EntryGroup entryGroup)
510                    throws NoSequenceException
511   {
512     final Document entry_document = DocumentFactory.makeDocument(entryFileName);
513     final EntryInformation artemis_entry_information =
514       Options.getArtemisEntryInformation();
515 
516     uk.ac.sanger.artemis.io.Entry new_embl_entry =
517       EntryFileDialog.getEntryFromFile(null, entry_document,
518                                        artemis_entry_information,
519                                        false);
520 
521     if(new_embl_entry == null)  // the read failed
522       return null;
523 
524     new_embl_entry = mergeOption(new_embl_entry);
525 
526     Entry entry = null;
527     try
528     {
529       Bases bases = null;
530       if(entryGroup.getSequenceEntry() != null)
531         bases = entryGroup.getSequenceEntry().getBases();
532       if(bases == null)
533         entry = new Entry(new_embl_entry);
534       else
535         entry = new Entry(bases,new_embl_entry);
536 
537       entryGroup.add(entry);
538     }
539     catch(OutOfRangeException e)
540     {
541       new MessageDialog(null, "read failed: one of the features in " +
542           entryFileName + " has an out of range " +
543                         "location: " + e.getMessage());
544     }
545     return entry;
546   }
547 
548 
mergeOption(uk.ac.sanger.artemis.io.Entry embl_entry)549   private static uk.ac.sanger.artemis.io.Entry mergeOption(uk.ac.sanger.artemis.io.Entry embl_entry)
550   {
551     if(embl_entry instanceof uk.ac.sanger.artemis.io.MSPcrunchDocumentEntry &&
552         System.getProperty("merge.blast") == null)
553     {
554       int status = JOptionPane.showConfirmDialog(null,
555           "This looks like a BLAST file. Do you want to merge\n"+
556           "overlapping BLAST hits to improve performance?", "Read BLAST",
557           JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
558       if(status == JOptionPane.OK_OPTION)
559         System.setProperty("merge.blast", "");
560       else
561         System.setProperty("merge.blast", "false");
562     }
563 
564     if( embl_entry instanceof uk.ac.sanger.artemis.io.MSPcrunchDocumentEntry &&
565         System.getProperty("merge.blast") != null &&
566        !System.getProperty("merge.blast").equals("false") )
567       embl_entry = mergeOverlappingFeatures(embl_entry);
568     return embl_entry;
569   }
570 
571   /**
572    * Merge overlapping BLAST hit features to improve the performance of
573    * DNAPlotter.
574    * @param embl_entry
575    * @return
576    */
mergeOverlappingFeatures(uk.ac.sanger.artemis.io.Entry embl_entry)577   private static uk.ac.sanger.artemis.io.Entry mergeOverlappingFeatures(uk.ac.sanger.artemis.io.Entry embl_entry)
578   {
579     final String name = embl_entry.getName();
580     final RangeVector ranges = new RangeVector();
581     uk.ac.sanger.artemis.io.FeatureVector features = embl_entry.getAllFeatures();
582     System.out.print("Number of features: before merge = "+features.size());
583 
584     for(int i=0; i<features.size(); i++)
585     {
586       Range ri = ((uk.ac.sanger.artemis.io.Feature) features.elementAt(i)).
587           getLocation().getTotalRange();
588       boolean overlaps = false;
589       Range rjOld = null;
590       Range rj = null;
591       int j;
592       for(j=0; j<ranges.size(); j++)
593       {
594         rjOld = (Range) ranges.get(j);
595         if(ri.overlaps(rjOld))
596         {
597           int start = rjOld.getStart();
598           int end = rjOld.getEnd();
599           if(start > ri.getStart())
600             start = ri.getStart();
601           if(end < ri.getEnd())
602             end = ri.getEnd();
603 
604           try
605           {
606             rj = new Range(start, end);
607             overlaps = true;
608             break;
609           }
610           catch (OutOfRangeException e){}
611         }
612       }
613       if(!overlaps)
614         ranges.add(ri);
615       else
616       {
617         ranges.remove(rjOld);
618         ranges.add(rj);
619       }
620     }
621 
622     embl_entry.dispose();
623     embl_entry = new MSPcrunchDocumentEntry(
624         Options.getOptions().getArtemisEntryInformation())
625     {
626       public boolean isReadOnly () {
627         return false;
628       }
629     };
630     embl_entry.setName(name);
631 
632     final Key key = new Key("CRUNCH_D");
633     for(int i=0; i<ranges.size(); i++)
634     {
635       Range r = (Range)ranges.get(i);
636       try
637       {
638         Feature f = new uk.ac.sanger.artemis.Feature(
639             new uk.ac.sanger.artemis.io.EmblStreamFeature(key, new Location(r), null));
640         embl_entry.add(f.getEmblFeature());
641       }
642       catch (ReadOnlyException e){}
643       catch (EntryInformationException e){}
644       catch (OutOfRangeException e)
645       {
646         e.printStackTrace();
647       }
648     }
649 
650     System.out.println(" after merge = "+ranges.size());
651     return embl_entry;
652   }
653 
654   /**
655    * Create a DNADraw panel from a file
656    * @param dna_current
657    * @return
658    */
getDNADrawFromFile(DNADraw dna_current)659   protected static DNADraw getDNADrawFromFile(DNADraw dna_current)
660   {
661     Options.getOptions();
662     uk.ac.sanger.artemis.components.FileDialogEntrySource entrySource =
663       new uk.ac.sanger.artemis.components.FileDialogEntrySource(null, null);
664 
665     final EntryGroup entryGroup = new SimpleEntryGroup();
666     Entry entry;
667     try
668     {
669       entry = entrySource.getEntry(true);
670       entryGroup.add(entry);
671       return getDNADrawFromArtemisEntry(dna_current, entryGroup, entry);
672     }
673     catch(OutOfRangeException e)
674     {
675       e.printStackTrace();
676     }
677     catch(NoSequenceException e)
678     {
679       JOptionPane.showMessageDialog(null, "No sequence found!",
680           "Sequence Missing", JOptionPane.WARNING_MESSAGE);
681     }
682     return null;
683   }
684 
685   /**
686    * Create a DNADraw panel from an entry
687    * @param dna_current
688    * @param entryGroup
689    * @param entry
690    * @return
691    */
getDNADrawFromArtemisEntry(DNADraw dna_current, final EntryGroup entryGroup, final Entry entry)692   public static DNADraw getDNADrawFromArtemisEntry(DNADraw dna_current,
693                                              final EntryGroup entryGroup,
694                                              final Entry entry)
695   {
696     for(int i=0; i<tracks.length; i++)
697       tracks[i].setEntry(entry);
698 
699     FeatureVector features = entry.getAllFeatures();
700     Vector block = new Vector();
701 
702     if(dna_current == null)
703       dna_current = new DNADraw();
704 
705     dna_current.setArtemisEntryGroup(entryGroup);
706 
707     Hashtable lineAttr = new Hashtable();
708     lineAttr.put("lsize", new Integer(1));
709     lineAttr.put("circular", new Boolean(true));
710     lineAttr.put("start", new Integer(0));
711     lineAttr.put("end", new Integer(entry.getBases().getLength()));
712 
713     dna_current.setLineAttributes(lineAttr);
714 
715     for(int i = 0; i < features.size(); i++)
716     {
717       Feature f = features.elementAt(i);
718 
719       RangeVector ranges = f.getLocation().getRanges();
720 
721       for(int j = 0; j < ranges.size(); j++)
722       {
723         Range range = (Range) ranges.get(j);
724 
725         Color col = f.getColour();
726         if(col == null || col.equals(Color.white))
727           col = Color.lightGray;
728 
729         Track track;
730 
731         if(TRACK_1.isOnTrack(f))
732           track = TRACK_1;
733         else if(TRACK_2.isOnTrack(f))
734           track = TRACK_2;
735         else if(TRACK_3.isOnTrack(f))
736           track = TRACK_3;
737         else if(TRACK_4.isOnTrack(f))
738           track = TRACK_4;
739         else
740           track = TRACK_5;
741 
742         Block drawBlock = new Block(f.getIDString(), range.getStart(), range
743             .getEnd(), col, 10.f, track, dna_current);
744 
745         drawBlock.setFeature(f);
746         block.add(drawBlock);
747       }
748     }
749 
750     int div;
751     if(entry.getBases().getLength() < 1000)
752       div = 100;
753     else if(entry.getBases().getLength() < 10000)
754       div = 1000;
755     else if(entry.getBases().getLength() < 100000)
756       div = 10000;
757     else
758       div = 100000;
759     int tick = entry.getBases().getLength() / div;
760     tick = tick * (div / 10);
761     int tick2 = tick / 2;
762     tick = tick2 * 2;
763 
764     dna_current.setGeneticMarker(block);
765     dna_current.setRestrictionEnzyme(new Vector());
766     dna_current.setMinorTickInterval(tick2);
767     dna_current.setTickInterval(tick);
768 
769     EntryVector entries = entryGroup.getActiveEntries();
770     for(int i=0; i<entries.size(); i++)
771     {
772       Entry this_entry = entries.elementAt(i);
773       if(!this_entry.getName().equals(entry.getName()))
774         addFeaturesFromEntry(this_entry, dna_current);
775     }
776     return dna_current;
777   }
778 
779   /**
780    * Read a new entry from a file
781    * @param dna_current
782    * @param bases
783    * @return
784    */
readEntry(final DNADraw dna_current, final Bases bases)785   public static DNADraw readEntry(final DNADraw dna_current,
786                                   final Bases bases)
787   {
788     Options.getOptions();
789     uk.ac.sanger.artemis.components.FileDialogEntrySource entrySource =
790       new uk.ac.sanger.artemis.components.FileDialogEntrySource(null, null);
791 
792     try
793     {
794       Entry entry = entrySource.getEntry(bases,true);
795 
796       if(entry.getEMBLEntry() instanceof uk.ac.sanger.artemis.io.MSPcrunchDocumentEntry)
797       {
798         uk.ac.sanger.artemis.io.Entry new_embl_entry =
799           mergeOption(entry.getEMBLEntry());
800         entry = new Entry(bases, new_embl_entry);
801       }
802 
803       dna_current.getArtemisEntryGroup().add(entry);
804 
805       addFeaturesFromEntry(entry, dna_current);
806     }
807     catch(OutOfRangeException e)
808     {
809       JOptionPane.showMessageDialog(null,
810           "Feature found out of range:\n"+
811           e.getMessage(),"Out of Range",
812           JOptionPane.WARNING_MESSAGE);
813     }
814 
815     return dna_current;
816   }
817 
818   /**
819    * Add features from an entry to a new track
820    * @param entry
821    * @param dna_current
822    */
addFeaturesFromEntry(final Entry entry, final DNADraw dna_current)823   private static void addFeaturesFromEntry(final Entry entry,
824                                    final DNADraw dna_current)
825   {
826     FeatureVector features = entry.getAllFeatures();
827 
828     Track track = addTrack(entry);
829     track.setAny(true);
830     for(int i=0; i<features.size(); i++)
831     {
832       Feature f = features.elementAt(i);
833       RangeVector ranges = f.getLocation().getRanges();
834 
835       for(int j=0; j<ranges.size(); j++)
836       {
837         Range range = (Range) ranges.get(j);
838 
839         Color col = f.getColour();
840         if(col == null || col.equals(Color.white))
841           col = Color.lightGray;
842 
843         Block drawBlock = new Block(f.getIDString(),
844             range.getStart(),
845             range.getEnd(),
846             col,
847             10.f,
848             track, dna_current);
849 
850         drawBlock.setFeature(f);
851         dna_current.getGeneticMarker().add(drawBlock);
852       }
853     }
854   }
855 
856 
857 
getDNADraw()858   public DNADraw getDNADraw()
859   {
860     return dna;
861   }
862 
863 
getOption(DNADraw dna_current)864   private int getOption(DNADraw dna_current)
865   {
866     Box bdown = Box.createVerticalBox();
867 
868     JRadioButton[] radioButtons;
869 
870     radioButtons = new JRadioButton[2];
871 
872     final ButtonGroup group = new ButtonGroup();
873     radioButtons[0] = new JRadioButton("Read in sequence file");
874     group.add(radioButtons[0]);
875 
876     radioButtons[0].setSelected(true);
877     bdown.add(radioButtons[0]);
878 
879 
880     radioButtons[0].setSelected(true);
881     if(dna_current !=  null)
882     {
883       radioButtons[1] = new JRadioButton("Edit current dna display");
884       group.add(radioButtons[1]);
885       radioButtons[1].setSelected(true);
886     }
887     else
888     {
889       radioButtons[1] = new JRadioButton("Read template file");
890       group.add(radioButtons[1]);
891     }
892     bdown.add(radioButtons[1]);
893 
894     JPanel pane = new JPanel(new BorderLayout());
895     pane.add(bdown);
896     JOptionPane.showMessageDialog(null,
897                       pane, "DNA Viewer Wizard",
898                       JOptionPane.QUESTION_MESSAGE);
899 
900     if(radioButtons[0].isSelected())
901       return 0;
902     else if(radioButtons[1].isSelected() && dna_current !=  null)
903       return 1;
904     else if(radioButtons[1].isSelected())
905       return 2;
906 
907     return 1;
908   }
909 
getTracks()910   protected static Track[] getTracks()
911   {
912     return tracks;
913   }
914 
915 
addTrack(Entry entry)916   protected static Track addTrack(Entry entry)
917   {
918     Track[] tracks = getTracks();
919     Track[] newTracks = new Track[tracks.length+1];
920     for(int i=0; i<tracks.length; i++)
921       newTracks[i] = tracks[i];
922 
923     final double position;
924     if(tracks.length > 1)
925       position = tracks[tracks.length-1].getPosition()-0.05;
926     else
927       position = 0.95;
928     Track newTrack = new Track(position, entry);
929     newTracks[tracks.length] = newTrack;
930     Wizard.tracks = newTracks;
931     return newTrack;
932   }
933 
deleteTrack(int trackIndex)934   protected static void deleteTrack(int trackIndex)
935   {
936     Track[] tracks = getTracks();
937     Track[] newTracks = new Track[tracks.length-1];
938     int count = 0;
939     for(int i=0; i<tracks.length; i++)
940     {
941       if(i == trackIndex)
942         continue;
943 
944       newTracks[count] = tracks[i];
945       count++;
946     }
947 
948     Wizard.tracks = newTracks;
949   }
950 
951   /**
952    * Return reader for a file or a URL
953    * @param templateName
954    * @return
955    */
getReader(final String templateName)956   protected static BufferedReader getReader(final String templateName)
957   {
958     final File fileTemplate = new File(templateName);
959     BufferedReader inputStream = null;
960     if(!fileTemplate.exists())
961     {
962       if (templateName.indexOf ("://") != -1)
963       {
964         URL template;
965         try
966         {
967           template = new URL(templateName);
968           inputStream = new BufferedReader(
969               new InputStreamReader(template.openStream()));
970         }
971         catch(MalformedURLException e)
972         {
973           e.printStackTrace();
974         }
975         catch(IOException e)
976         {
977           e.printStackTrace();
978         }
979       }
980     }
981     else
982     {
983       try
984       {
985         if(templateName.endsWith(".gz"))
986           inputStream = new BufferedReader(
987               new InputStreamReader(new WorkingGZIPInputStream(
988                   new FileInputStream(fileTemplate) )));
989         else
990           inputStream = new BufferedReader(new FileReader(fileTemplate));
991       }
992       catch(FileNotFoundException e)
993       {
994         e.printStackTrace();
995       }
996       catch (IOException e)
997       {
998         e.printStackTrace();
999       }
1000     }
1001     return inputStream;
1002   }
1003 
getWorkerGraph()1004   public SwingWorker getWorkerGraph()
1005   {
1006     return workerGraph;
1007   }
1008 }
1009 
1010