update spikes/mungo from JAL-3076 patch branch
[jalview.git] / src / jalview / util / HMMProbabilityDistributionAnalyser.java
1 package jalview.util;
2
3 import jalview.datamodel.AlignmentAnnotation;
4 import jalview.datamodel.HiddenMarkovModel;
5 import jalview.datamodel.SequenceI;
6 import jalview.io.DataSourceType;
7 import jalview.io.FileParse;
8 import jalview.io.HMMFile;
9 import jalview.io.StockholmFile;
10 import jalview.schemes.ResidueProperties;
11
12 import java.io.BufferedReader;
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.io.FileOutputStream;
16 import java.io.FileReader;
17 import java.io.IOException;
18 import java.io.InputStreamReader;
19 import java.io.PrintWriter;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Random;
25 import java.util.Scanner;
26 import java.util.Vector;
27
28 /**
29  * Processes probability data. The file indexes used in this program represent
30  * the index of the location of a family or hmm in their respective files,
31  * starting from 0.
32  * 
33  * @author TZVanaalten
34  *
35  */
36 public class HMMProbabilityDistributionAnalyser
37 {
38   AlignmentAnnotation reference = null;
39
40   Vector<SequenceI> sequences;
41
42   HiddenMarkovModel hmm;
43
44   // contains the raw data produced
45   List<ArrayList<Double>> raw = new ArrayList<>();
46
47   // contains binned data
48   Map<String, Double> binned = new HashMap<>();
49
50   // location of the family file
51   String families = "/media/sf_Shared_Folder/PFAM/Family/SeedFamilies.seed";
52
53   // location of the file containing the family-clan links
54   final static String FAMILIESTOCLAN = "/media/sf_Shared_Folder/PFAM/Family/Clanlinks.dat";
55
56   // location of the HMM file
57   String hmms = "/media/sf_Shared_Folder/PFAM/HMMs/Pfam-A.hmm";
58
59   // suffix for raw file
60   final static String RAW = "/Raw.csv";
61
62   // suffix for binned file
63   final static String BINNED = "/Binned.csv";
64
65   // normalisation scale
66   final static double SCALE = 1;
67
68   // current position in file
69   int currentFilePosition = 0;
70
71   final static String NL = "\n";
72
73   Random generator = new Random();
74
75   // current directory
76   String currentFolder;
77
78   boolean keepRaw = false;
79
80   /**
81    * Sets the working directory.
82    * 
83    * @param path
84    */
85   public void setFolder(String path)
86   {
87     currentFolder = path;
88   }
89
90   /**
91    * Moves a buffered reader forward in the file by a certain amount of entries.
92    * Each entry in the file is delimited by '//'.
93    * 
94    * @param index
95    *          The index of the location in the file.
96    * @param br
97    * @throws IOException
98    */
99   public void moveLocationBy(int index, BufferedReader br)
100           throws IOException
101   {
102     for (int i = 0; i < index; i++)
103     {
104       String line = br.readLine();
105       while (!"//".equals(line))
106       {
107         line = br.readLine();
108
109       }
110     }
111
112   }
113   
114   /**
115    * Analyses a specified number of families and then saves the data. Before
116    * analysing the data, the previous saved data will be imported and after
117    * analysing this, the data is exported back into the file. The file must be
118    * in flat file format.
119    * 
120    * @param increments
121    *          The number of families to read before saving.
122    * @throws IOException
123    */
124   public void run(int increments, boolean keepRawData) throws IOException
125   {
126     keepRaw = keepRawData;
127     try
128     {
129       readPreviousData(currentFolder);
130       BufferedReader posReader = new BufferedReader(
131               new FileReader(currentFolder + "/CurrentPosition.txt"));
132
133       String line = posReader.readLine();
134       posReader.close();
135       currentFilePosition = Integer.parseInt(line);
136     } catch (Exception e)
137     {
138       System.out.println("No previous data found");
139     }
140
141
142
143     BufferedReader inputSTO = new BufferedReader(new FileReader(families));
144     BufferedReader inputHMM = new BufferedReader(new FileReader(hmms));
145
146
147
148     moveLocationBy(currentFilePosition, inputHMM);
149     moveLocationBy(currentFilePosition, inputSTO);
150
151     int filesRead = 0;
152     int i = 0;
153     while (filesRead < increments)
154     {
155
156       readStockholm(inputSTO);
157
158       readHMM(inputHMM);
159
160         int count = countValidResidues();
161         processData(count);
162         filesRead++;
163
164       currentFilePosition++;
165       System.out.println(i);
166       i++;
167     }
168
169     PrintWriter p = new PrintWriter(
170             new File(currentFolder + "/CurrentPosition.txt"));
171     p.print(currentFilePosition);
172     p.close();
173     exportData(currentFolder);
174     raw.clear();
175     binned.clear();
176
177   }
178
179   /**
180    * Analyses all families and then saves the data. Before analysing the data,
181    * the previous saved data will be imported and after analysing this, the data
182    * is exported back into the file. The file must be in flat file format.
183    * 
184    * @param increments
185    *          The number of families to read before saving.
186    * @throws IOException
187    */
188   public void runToEnd(int minCount, int maxCount, boolean keepRawData,
189           boolean forClans)
190           throws IOException
191   {
192     keepRaw = keepRawData;
193     BufferedReader inputSTO = null;
194     BufferedReader inputHMM = null;
195     int size = 0;
196     int files = 1;
197     try
198     {
199     if (forClans)
200     {
201         files = 603;
202     }
203     int filesRead = 0;
204     for (int clan = 0; clan < files; clan++)
205     {
206       System.out.println(clan);
207       String clanPath = "";
208       int numberOfFamilies = 0;
209       if (forClans)
210       {
211         clanPath = currentFolder + "/Clan" + clan;
212           if (!new File(clanPath).exists())
213           {
214             continue;
215           }
216         BufferedReader famCountReader = new BufferedReader(
217                 new FileReader(clanPath + "/NumberOfFamilies.txt"));
218         numberOfFamilies = Integer.parseInt(famCountReader.readLine());
219       }
220       else
221       {
222         numberOfFamilies = 1;
223       }
224       
225       for (int fam = 0; fam < numberOfFamilies; fam++)
226       {
227         if (forClans)
228         {
229           families = clanPath + "/Families/Fam" + fam + ".sto";
230           hmms = clanPath + "/HMMs/HMM" + fam + ".hmm";
231         }
232
233         inputSTO = new BufferedReader(new FileReader(families));
234         inputHMM = new BufferedReader(new FileReader(hmms));
235
236
237         int i = 0;
238         boolean endReached = atEnd(inputSTO);
239         while (!endReached)
240         {
241           readStockholm(inputSTO);
242           readHMM(inputHMM);
243
244         int count = countValidResidues();
245             if (count >= minCount && count < maxCount)
246             {
247               processData(count);
248             }
249         filesRead++;
250           System.out.println(filesRead);
251       endReached = atEnd(inputSTO);
252       }
253       }
254     }
255     } catch (Exception e)
256     {
257       e.printStackTrace();
258     } finally
259     {
260       exportData(currentFolder);
261       raw.clear();
262       binned.clear();
263     }
264   }
265
266   /**
267    * Reads the previous data from both files
268    * 
269    * @param source
270    * @throws IOException
271    */
272   public void readPreviousData(String source) throws IOException
273   {
274     readBinned(source);
275     if (keepRaw)
276     {
277       readRaw(source);
278     }
279   }
280
281   /**
282    * Reads the previous data from the binned file.
283    * 
284    * @param source
285    * @throws IOException
286    */
287   public void readBinned(String source) throws IOException
288   {
289     BufferedReader input = new BufferedReader(
290             new FileReader(source + BINNED));
291     String line = input.readLine();
292     binned = new HashMap<>();
293     while (!("".equals(line) || line == null))
294     {
295       Scanner scanner = new Scanner(line);
296       scanner.useDelimiter(",");
297       String key = scanner.next();
298       String value = scanner.next();
299       binned.put(key, Double.valueOf(value));
300       scanner.close();
301       line = input.readLine();
302     }
303
304     input.close();
305   }
306
307   /**
308    * Reads the previous data from the raw file.
309    * 
310    * @param source
311    * @throws IOException
312    */
313   public void readRaw(String source) throws IOException
314   {
315     BufferedReader input = new BufferedReader(new FileReader(source + RAW));
316     String line = input.readLine();
317     if (line == null)
318     {
319       input.close();
320       return;
321     }
322     Scanner numberScanner = new Scanner(line);
323     numberScanner.useDelimiter(",");
324     raw = new ArrayList<>();
325     while (numberScanner.hasNext())
326     {
327       numberScanner.next();
328       raw.add(new ArrayList<Double>());
329     }
330     numberScanner.close();
331
332     line = input.readLine();
333     while (!("".equals(line) || line == null))
334     {
335       Scanner scanner = new Scanner(line);
336       scanner.useDelimiter(",");
337
338       int i = 0;
339       while (scanner.hasNext())
340       {
341         String value;
342         value = scanner.next();
343         if (!value.equals("EMPTY"))
344         {
345           raw.get(i).add(Double.parseDouble(value));
346         }
347         else
348         {
349           raw.get(i).add(null);
350         }
351
352         i++;
353       }
354       scanner.close();
355       line = input.readLine();
356     }
357
358     input.close();
359   }
360
361   /**
362    * Counts the number of valid residues in the sequence.
363    * 
364    * @return
365    */
366   public int countValidResidues()
367   {
368     int count = 0;
369
370     for (int width = 0; width < sequences.size(); width++)
371     {
372       for (int length = 1; length < hmm.getLength() + 1; length++)
373       {
374         char symbol;
375         int alignPos;
376         alignPos = hmm.getNodeMapPosition(length);
377
378         symbol = sequences.get(width).getCharAt(alignPos);
379         if (ResidueProperties.backgroundFrequencies.get("amino")
380                 .containsKey(symbol))
381         {
382           count++;
383         }
384       }
385     }
386
387     return count;
388   }
389
390   /**
391    * Processes data, and stores it in both a raw and binned format.
392    * 
393    * @param count
394    */
395   public void processData(int count)
396   {
397     int rawPos = 0;
398     if (keepRaw)
399     {
400       raw.add(new ArrayList<Double>());
401       rawPos = raw.size() - 1;
402     }
403     Double total = 0d;
404     for (int width = 0; width < sequences.size(); width++)
405     {
406       for (int length = 1; length < hmm.getLength() + 1; length++)
407       {
408         char symbol;
409         int alignPos;
410         alignPos = hmm.getNodeMapPosition(length);
411         
412         symbol = sequences.get(width).getCharAt(alignPos);
413         if (ResidueProperties.backgroundFrequencies.get("amino")
414                 .containsKey(symbol))
415         {
416           Double prob;
417           Float bfreq;
418           Double llr;
419           prob = hmm.getMatchEmissionProbability(alignPos, symbol);
420           bfreq = ResidueProperties.backgroundFrequencies.get("amino")
421                   .get(symbol);
422           if (prob == 0 || bfreq == 0)
423           {
424             System.out.println("error");
425           }
426           llr = Math.log(prob / bfreq);
427           if (keepRaw)
428           {
429             raw.get(rawPos).add(llr);
430           }
431
432           String output;
433           output = String.format("%.1f", llr);
434           total += Double.parseDouble(output);
435           if ("-0.0".equals(output))
436           {
437             output = "0.0";
438           }
439           if (binned.containsKey(output))
440           {
441             double prev = binned.get(output);
442             prev += (SCALE / count);
443             binned.put(output, prev);
444
445           }
446           else
447           {
448             binned.put(output, SCALE / count);
449           }
450         }
451       }
452     }
453     System.out.println(total / count);
454   }
455
456
457   /**
458    * Reads in the sequence data from a Stockholm file.
459    * 
460    * @param source
461    * @throws IOException
462    */
463   public void readStockholm(BufferedReader inputSTO) throws IOException
464   {
465     FileParse parserSTO = new FileParse(inputSTO, "", DataSourceType.FILE);
466     StockholmFile file = new StockholmFile(parserSTO);
467     Vector<AlignmentAnnotation> annots = file.getAnnotations();
468
469     for (AlignmentAnnotation annot : annots)
470     {
471       if (annot.label.contains("Reference"))
472       {
473         reference = annot;
474       }
475     }
476     sequences = file.getSeqs();
477   }
478
479   /**
480    * Reads in the HMM data from a HMMer file.
481    * 
482    * @param source
483    * @throws IOException
484    */
485   public void readHMM(BufferedReader inputHMM) throws IOException
486   {
487     FileParse parserHMM = new FileParse(inputHMM, "", DataSourceType.FILE);
488     HMMFile file = new HMMFile(parserHMM);
489     hmm = file.getHMM();
490
491
492   }
493
494   /**
495    * Exports both the binned and raw data into separate files.
496    * 
497    * @param location
498    * @throws FileNotFoundException
499    */
500   public void exportData(String location) throws FileNotFoundException
501   {
502     PrintWriter writerBin = new PrintWriter(new File(location + BINNED));
503     for (Map.Entry<String, Double> entry : binned.entrySet())
504     {
505       writerBin.println(entry.getKey() + "," + entry.getValue());
506     }
507     writerBin.close();
508     if (keepRaw)
509     {
510
511     PrintWriter writerRaw = new PrintWriter(new File(location + RAW));
512     
513     StringBuilder identifier = new StringBuilder();
514     
515     for (int i = 1; i < raw.size() + 1; i++)
516     {
517       identifier.append("Fam " + i + ",");
518     }
519     
520     writerRaw.println(identifier);
521     
522     boolean rowIsEmpty = false;
523     int row = 0;
524     while (!rowIsEmpty)
525     {
526       rowIsEmpty = true;
527       StringBuilder string = new StringBuilder();
528       for (int column = 0; column < raw.size(); column++)
529       {
530         if (raw.get(column).size() <= row)
531         {
532           string.append("EMPTY,");
533         }
534         else
535         {
536           string.append(raw.get(column).get(row) + ",");
537           rowIsEmpty = false;
538         }
539       }
540       row++;
541       writerRaw.println(string);
542     }
543     writerRaw.close();
544
545     }
546
547   }
548
549   /**
550    * Prints the specified family on the console.
551    * 
552    * @param index
553    * @throws IOException
554    */
555   public void printFam(int index) throws IOException
556   {
557     BufferedReader br = new BufferedReader(new FileReader(families));
558
559     moveLocationBy(index, br);
560
561     String line = br.readLine();
562
563     while (!"//".equals(line))
564     {
565       System.out.println(line);
566       line = br.readLine();
567     }
568     System.out.println(line);
569     br.close();
570
571   }
572
573   /**
574    * Prints the specified HMM on the console.
575    * 
576    * @param index
577    * @throws IOException
578    */
579   public void printHMM(int index) throws IOException
580   {
581     BufferedReader br = new BufferedReader(new FileReader(hmms));
582
583     moveLocationBy(index, br);
584
585     String line = br.readLine();
586
587     while (!"//".equals(line))
588     {
589       System.out.println(line);
590       line = br.readLine();
591     }
592     System.out.println(line);
593     br.close();
594
595   }
596
597   /**
598    * Prints the specified family to a .sto file.
599    * 
600    * @param index
601    * @throws IOException
602    */
603   public void exportFam(int index, String location) throws IOException
604   {
605     BufferedReader br = new BufferedReader(new FileReader(families));
606
607     moveLocationBy(index, br);
608
609     String line = br.readLine();
610     PrintWriter writer = new PrintWriter(
611             new FileOutputStream(new File(location), true));
612     while (!"//".equals(line))
613     {
614       writer.println(line);
615       line = br.readLine();
616     }
617     writer.println(line);
618     writer.close();
619     br.close();
620
621   }
622
623   public void exportFile(BufferedReader br, String location, boolean append)
624           throws IOException
625   {
626     String line = br.readLine();
627     PrintWriter writer = new PrintWriter(
628             new FileOutputStream(location, append));
629     while (!"//".equals(line))
630     {
631       writer.println(line);
632       line = br.readLine();
633     }
634     writer.println(line);
635     writer.close();
636
637
638   }
639
640   public String getHMMName(int index) throws IOException
641   {
642     String name;
643
644     BufferedReader nameFinder = new BufferedReader(new FileReader(hmms));
645
646     moveLocationBy(index, nameFinder);
647
648     nameFinder.readLine();
649
650     Scanner scanner = new Scanner(nameFinder.readLine());
651     name = scanner.next();
652     name = scanner.next();
653     scanner.close();
654     return name;
655   }
656
657   public String getFamilyName(int index) throws IOException
658   {
659     String name;
660
661     BufferedReader nameFinder = new BufferedReader(
662             new FileReader(families));
663
664     moveLocationBy(index, nameFinder);
665
666     nameFinder.readLine();
667
668     Scanner scanner = new Scanner(nameFinder.readLine());
669     name = scanner.next();
670     name = scanner.next();
671     name = scanner.next();
672     scanner.close();
673     return name;
674   }
675
676   /**
677    * Prints the specified family to a .hmm file.
678    * 
679    * @param index
680    * @throws IOException
681    */
682   public void exportHMM(int index, String location) throws IOException
683   {
684
685
686     BufferedReader br = new BufferedReader(new FileReader(hmms));
687
688     moveLocationBy(index, br);
689
690     String line = br.readLine();
691
692     PrintWriter writer = new PrintWriter(
693             new FileOutputStream(new File(location), true));
694     while (!"//".equals(line))
695     {
696       writer.println(line);
697       line = br.readLine();
698     }
699     writer.println(line);
700     writer.close();
701     br.close();
702
703   }
704   
705   /**
706    * Clears all raw, binned and current position data in the current directory.
707    * 
708    * @throws FileNotFoundException
709    */
710   public void clear() throws FileNotFoundException
711   {
712     PrintWriter pos = new PrintWriter(
713             currentFolder + "/CurrentPosition.txt");
714     pos.println("0");
715     
716     PrintWriter raw = new PrintWriter(currentFolder + RAW);
717     
718     PrintWriter bin = new PrintWriter(currentFolder + BINNED);
719     
720     pos.close();
721     bin.close();
722     raw.close();
723   }
724
725   public void sortIntoClans(String directory) throws IOException
726   {
727     BufferedReader clanFinder = new BufferedReader(new FileReader(FAMILIESTOCLAN));
728     BufferedReader familyReader = new BufferedReader(
729             new FileReader(families));
730     BufferedReader hmmReader = new BufferedReader(new FileReader(hmms));
731     int families = 0;
732     // moveLocationBy(7000, familyReader);
733     // moveLocationBy(7000, clanFinder);
734     // moveLocationBy(7000, hmmReader);
735     HashMap<String, Integer> clanIndexes = new HashMap<>();
736     ArrayList<Integer> familyCounts = new ArrayList<>();
737     int filePos = 0; 
738     int clanCount = 0;
739     String line;
740     line = clanFinder.readLine();
741     
742     while (!"".equals(line) && !" ".equals(line) && line != null)
743     {
744      String clanName;
745       boolean inClan = false;
746      while (!(line.indexOf("//") > -1))
747      {
748        
749       if (line.indexOf("#=GF CL") > -1)
750       {
751           families++;
752           System.out.println(families);
753           inClan = true;
754         Scanner scanner = new Scanner(line);
755         scanner.next();
756         scanner.next();
757         clanName = scanner.next();
758           scanner.close();
759         
760         if (!clanIndexes.containsKey(clanName))
761         {
762           clanIndexes.put(clanName, clanCount);
763             clanCount++;
764             familyCounts.add(0);
765         }
766
767
768           Integer clanI = clanIndexes.get(clanName);
769           String clanPath = directory + "/Clan" + clanI.toString();
770           createFolders(clanPath);
771
772           int index = clanIndexes.get(clanName);
773           exportFile(familyReader,
774                   clanPath + "/Families/Fam" + familyCounts.get(index)
775                           + ".sto",
776                   false);
777           exportFile(hmmReader,
778                   clanPath + "/HMMs/HMM" + familyCounts.get(index) + ".hmm",
779                   false);
780
781           int count = familyCounts.get(index);
782           count++;
783           familyCounts.set(index, count);
784       }
785         line = clanFinder.readLine();
786
787       }
788       if (!inClan)
789       {
790         moveLocationBy(1, familyReader);
791         moveLocationBy(1, hmmReader);
792       }
793       filePos++;
794       // System.out.println(filePos + " files read.");
795       line = clanFinder.readLine();
796
797      }
798     clanFinder.close();
799
800     for (int clan = 0; clan < clanCount; clan++)
801     {
802       PrintWriter writer = new PrintWriter(
803               directory + "/Clan" + clan + "/NumberOfFamilies.txt");
804       int count = familyCounts.get(clan);
805       writer.print(count);
806       writer.close();
807     }
808       
809     }
810
811   public String getFamilies()
812   {
813     return families;
814   }
815
816   public void setFamilies(String families)
817   {
818     this.families = currentFolder + families;
819   }
820
821   public String getHmms()
822   {
823     return hmms;
824   }
825
826   public void setHmms(String hmms)
827   {
828     this.hmms = currentFolder + hmms;
829   }
830     
831   public void alignWithinClan(String exportLocation, String clansLocation)
832           throws IOException, InterruptedException
833   {
834     int alignmentsExported = 0;
835     for (int clan = 0; clan < 604; clan++)
836     {
837       System.out.println(clan);
838       int famCount = 0;
839       String clanPath = clansLocation + "/Clan" + clan;
840       int numberOfFamilies;
841       BufferedReader br = new BufferedReader(
842               new FileReader(clanPath + "/NumberOfFamilies.txt"));
843       String line = br.readLine();
844       numberOfFamilies = Integer.parseInt(line);
845       br.close();
846       if (numberOfFamilies == 1)
847       {
848         continue;
849       }
850       final String commandExportLocation = exportLocation + "/Clan" + clan;
851       createFolders(commandExportLocation);
852       for (int family = 0; family < numberOfFamilies; family++)
853       {
854         famCount++;
855         ArrayList<Integer> indexes = new ArrayList<>();
856         for (int i = 0; i < numberOfFamilies; i++)
857         {
858           if (i != family)
859           {
860             indexes.add(i);
861           }
862         }
863
864         int hmmIndex = getRandom(indexes);
865         String famPath = clanPath + "/Families/Fam" + family + ".sto";
866         String hmmPath = clanPath + "/HMMs/HMM" + hmmIndex + ".hmm";
867         String command = "/media/sf_Shared_Folder/hmmer/binaries/hmmalign --mapali "
868                 + clanPath + "/Families/Fam" + hmmIndex + ".sto"
869                 + " --trim ";
870         command += hmmPath + " ";
871         command += famPath;
872         final int familyIndex = family;
873         final Process p = Runtime.getRuntime().exec(command);
874
875         new Thread(new Runnable()
876         {
877           @Override
878           public void run()
879           {
880             BufferedReader input = new BufferedReader(
881                     new InputStreamReader(p.getInputStream()));
882             String line = null;
883
884             try
885             {
886               PrintWriter writer = new PrintWriter(commandExportLocation
887                       + "/Families/Fam" + familyIndex + ".sto");
888               String lastLine = "";
889               boolean dataFound = false;
890               while ((line = input.readLine()) != null)
891               {
892                 if (line.contains("#=GR") && !dataFound)
893                 {
894                   writer.println(lastLine);
895                   dataFound = true;
896                 }
897                 if (line.contains("#") || dataFound || " ".equals(line)
898                         || "".equals(line) || "//".equals(line))
899                 {
900                   writer.println(line);
901                 }
902                 lastLine = line;
903               }
904               writer.close();
905             } catch (IOException e)
906             {
907               e.printStackTrace();
908             }
909           }
910         }).start();
911
912         p.waitFor();
913
914         BufferedReader hmmExporter = new BufferedReader(
915                 new FileReader(hmmPath));
916
917         exportFile(hmmExporter,
918                 commandExportLocation + "/HMMs/HMM" + family + ".hmm",
919                 false);
920
921         alignmentsExported++;
922
923
924       }
925       PrintWriter writer = new PrintWriter(
926               commandExportLocation + "/NumberOfFamilies.txt");
927       writer.print(famCount);
928       writer.close();
929     }
930
931   }
932
933   public boolean atEnd(BufferedReader br) throws IOException
934   {
935     boolean end = false;
936     br.mark(80);
937     String line = br.readLine();
938     if ("".equals(line) || line == null)
939     {
940       end = true;
941     }
942     br.reset();
943     return end;
944   }
945
946   public int getRandom(ArrayList<Integer> list)
947   {
948     if (!(list.size() > 0))
949     {
950       System.out.println("Error - size = " + list.size());
951     }
952     int index = generator.nextInt(list.size());
953     int value = list.get(index);
954     list.remove(index);
955     return value;
956   }
957
958   public void createFolders(String clanPath)
959   {
960     File clanFolder = new File(clanPath);
961     if (!clanFolder.exists())
962     {
963       clanFolder.mkdir();
964     }
965
966     File famFolder = new File(clanPath + "/Families");
967     File hmmFolder = new File(clanPath + "/HMMs");
968     if (!famFolder.exists())
969     {
970       famFolder.mkdir();
971       hmmFolder.mkdir();
972     }
973   }
974 }
975
976
977
978