Merge remote-tracking branch 'origin/releases/Release_2_10_2_Branch' into features...
[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(boolean keepRawData, boolean forClans)
189           throws IOException
190   {
191     keepRaw = keepRawData;
192     BufferedReader inputSTO = null;
193     BufferedReader inputHMM = null;
194     int size = 0;
195     int files = 1;
196     try
197     {
198     if (forClans)
199     {
200         files = 603;
201     }
202     int filesRead = 0;
203     for (int clan = 0; clan < files; clan++)
204     {
205       System.out.println(clan);
206       String clanPath = "";
207       int numberOfFamilies = 0;
208       if (forClans)
209       {
210         clanPath = currentFolder + "/Clan" + clan;
211           if (!new File(clanPath).exists())
212           {
213             continue;
214           }
215         BufferedReader famCountReader = new BufferedReader(
216                 new FileReader(clanPath + "/NumberOfFamilies.txt"));
217         numberOfFamilies = Integer.parseInt(famCountReader.readLine());
218       }
219       else
220       {
221         numberOfFamilies = 1;
222       }
223       
224       for (int fam = 0; fam < numberOfFamilies; fam++)
225       {
226         if (forClans)
227         {
228           families = clanPath + "/Families/Fam" + fam + ".sto";
229           hmms = clanPath + "/HMMs/HMM" + fam + ".hmm";
230         }
231
232         inputSTO = new BufferedReader(new FileReader(families));
233         inputHMM = new BufferedReader(new FileReader(hmms));
234
235
236         int i = 0;
237         boolean endReached = atEnd(inputSTO);
238         while (!endReached)
239         {
240           readStockholm(inputSTO);
241           readHMM(inputHMM);
242
243         int count = countValidResidues();
244         processData(count);
245         filesRead++;
246           System.out.println(filesRead);
247       endReached = atEnd(inputSTO);
248       }
249       }
250     }
251     } catch (Exception e)
252     {
253       e.printStackTrace();
254     } finally
255     {
256       exportData(currentFolder);
257       raw.clear();
258       binned.clear();
259     }
260   }
261
262   /**
263    * Reads the previous data from both files
264    * 
265    * @param source
266    * @throws IOException
267    */
268   public void readPreviousData(String source) throws IOException
269   {
270     readBinned(source);
271     if (keepRaw)
272     {
273       readRaw(source);
274     }
275   }
276
277   /**
278    * Reads the previous data from the binned file.
279    * 
280    * @param source
281    * @throws IOException
282    */
283   public void readBinned(String source) throws IOException
284   {
285     BufferedReader input = new BufferedReader(
286             new FileReader(source + BINNED));
287     String line = input.readLine();
288     binned = new HashMap<>();
289     while (!("".equals(line) || line == null))
290     {
291       Scanner scanner = new Scanner(line);
292       scanner.useDelimiter(",");
293       String key = scanner.next();
294       String value = scanner.next();
295       binned.put(key, Double.valueOf(value));
296       scanner.close();
297       line = input.readLine();
298     }
299
300     input.close();
301   }
302
303   /**
304    * Reads the previous data from the raw file.
305    * 
306    * @param source
307    * @throws IOException
308    */
309   public void readRaw(String source) throws IOException
310   {
311     BufferedReader input = new BufferedReader(new FileReader(source + RAW));
312     String line = input.readLine();
313     if (line == null)
314     {
315       input.close();
316       return;
317     }
318     Scanner numberScanner = new Scanner(line);
319     numberScanner.useDelimiter(",");
320     raw = new ArrayList<>();
321     while (numberScanner.hasNext())
322     {
323       numberScanner.next();
324       raw.add(new ArrayList<Double>());
325     }
326     numberScanner.close();
327
328     line = input.readLine();
329     while (!("".equals(line) || line == null))
330     {
331       Scanner scanner = new Scanner(line);
332       scanner.useDelimiter(",");
333
334       int i = 0;
335       while (scanner.hasNext())
336       {
337         String value;
338         value = scanner.next();
339         if (!value.equals("EMPTY"))
340         {
341           raw.get(i).add(Double.parseDouble(value));
342         }
343         else
344         {
345           raw.get(i).add(null);
346         }
347
348         i++;
349       }
350       scanner.close();
351       line = input.readLine();
352     }
353
354     input.close();
355   }
356
357   /**
358    * Counts the number of valid residues in the sequence.
359    * 
360    * @return
361    */
362   public int countValidResidues()
363   {
364     int count = 0;
365
366     for (int width = 0; width < sequences.size(); width++)
367     {
368       for (int length = 1; length < hmm.getLength() + 1; length++)
369       {
370         char symbol;
371         int alignPos;
372         alignPos = hmm.getNodeAlignmentColumn(length);
373
374         symbol = sequences.get(width).getCharAt(alignPos);
375         if (ResidueProperties.backgroundFrequencies.get("amino")
376                 .containsKey(symbol))
377         {
378           count++;
379         }
380       }
381     }
382
383     return count;
384   }
385
386   /**
387    * Processes data, and stores it in both a raw and binned format.
388    * 
389    * @param count
390    */
391   public void processData(int count)
392   {
393     int rawPos = 0;
394     if (keepRaw)
395     {
396       raw.add(new ArrayList<Double>());
397       rawPos = raw.size() - 1;
398     }
399     Double total = 0d;
400     for (int width = 0; width < sequences.size(); width++)
401     {
402       for (int length = 1; length < hmm.getLength() + 1; length++)
403       {
404         char symbol;
405         int alignPos;
406         alignPos = hmm.getNodeAlignmentColumn(length);
407         
408         symbol = sequences.get(width).getCharAt(alignPos);
409         if (ResidueProperties.backgroundFrequencies.get("amino")
410                 .containsKey(symbol))
411         {
412           Double prob;
413           Float bfreq;
414           Double llr;
415           prob = hmm.getMatchEmissionProbability(alignPos, symbol);
416           bfreq = ResidueProperties.backgroundFrequencies.get("amino")
417                   .get(symbol);
418           if (prob == 0 || bfreq == 0)
419           {
420             System.out.println("error");
421           }
422           llr = Math.log(prob / bfreq);
423           if (keepRaw)
424           {
425             raw.get(rawPos).add(llr);
426           }
427
428           String output;
429           output = String.format("%.1f", llr);
430           total += Double.parseDouble(output);
431           if ("-0.0".equals(output))
432           {
433             output = "0.0";
434           }
435           if (binned.containsKey(output))
436           {
437             double prev = binned.get(output);
438             prev += (SCALE / count);
439             binned.put(output, prev);
440
441           }
442           else
443           {
444             binned.put(output, SCALE / count);
445           }
446         }
447       }
448     }
449     System.out.println(total / count);
450   }
451
452
453   /**
454    * Reads in the sequence data from a Stockholm file.
455    * 
456    * @param source
457    * @throws IOException
458    */
459   public void readStockholm(BufferedReader inputSTO) throws IOException
460   {
461     FileParse parserSTO = new FileParse(inputSTO, "", DataSourceType.FILE);
462     StockholmFile file = new StockholmFile(parserSTO);
463     Vector<AlignmentAnnotation> annots = file.getAnnotations();
464
465     for (AlignmentAnnotation annot : annots)
466     {
467       if (annot.label.contains("Reference"))
468       {
469         reference = annot;
470       }
471     }
472     sequences = file.getSeqs();
473   }
474
475   /**
476    * Reads in the HMM data from a HMMer file.
477    * 
478    * @param source
479    * @throws IOException
480    */
481   public void readHMM(BufferedReader inputHMM) throws IOException
482   {
483     FileParse parserHMM = new FileParse(inputHMM, "", DataSourceType.FILE);
484     HMMFile file = new HMMFile(parserHMM);
485     hmm = file.getHMM();
486
487
488   }
489
490   /**
491    * Exports both the binned and raw data into separate files.
492    * 
493    * @param location
494    * @throws FileNotFoundException
495    */
496   public void exportData(String location) throws FileNotFoundException
497   {
498     PrintWriter writerBin = new PrintWriter(new File(location + BINNED));
499     for (Map.Entry<String, Double> entry : binned.entrySet())
500     {
501       writerBin.println(entry.getKey() + "," + entry.getValue());
502     }
503     writerBin.close();
504     if (keepRaw)
505     {
506
507     PrintWriter writerRaw = new PrintWriter(new File(location + RAW));
508     
509     StringBuilder identifier = new StringBuilder();
510     
511     for (int i = 1; i < raw.size() + 1; i++)
512     {
513       identifier.append("Fam " + i + ",");
514     }
515     
516     writerRaw.println(identifier);
517     
518     boolean rowIsEmpty = false;
519     int row = 0;
520     while (!rowIsEmpty)
521     {
522       rowIsEmpty = true;
523       StringBuilder string = new StringBuilder();
524       for (int column = 0; column < raw.size(); column++)
525       {
526         if (raw.get(column).size() <= row)
527         {
528           string.append("EMPTY,");
529         }
530         else
531         {
532           string.append(raw.get(column).get(row) + ",");
533           rowIsEmpty = false;
534         }
535       }
536       row++;
537       writerRaw.println(string);
538     }
539     writerRaw.close();
540
541     }
542
543   }
544
545   /**
546    * Prints the specified family on the console.
547    * 
548    * @param index
549    * @throws IOException
550    */
551   public void printFam(int index) throws IOException
552   {
553     BufferedReader br = new BufferedReader(new FileReader(families));
554
555     moveLocationBy(index, br);
556
557     String line = br.readLine();
558
559     while (!"//".equals(line))
560     {
561       System.out.println(line);
562       line = br.readLine();
563     }
564     System.out.println(line);
565     br.close();
566
567   }
568
569   /**
570    * Prints the specified HMM on the console.
571    * 
572    * @param index
573    * @throws IOException
574    */
575   public void printHMM(int index) throws IOException
576   {
577     BufferedReader br = new BufferedReader(new FileReader(hmms));
578
579     moveLocationBy(index, br);
580
581     String line = br.readLine();
582
583     while (!"//".equals(line))
584     {
585       System.out.println(line);
586       line = br.readLine();
587     }
588     System.out.println(line);
589     br.close();
590
591   }
592
593   /**
594    * Prints the specified family to a .sto file.
595    * 
596    * @param index
597    * @throws IOException
598    */
599   public void exportFam(int index, String location) throws IOException
600   {
601     BufferedReader br = new BufferedReader(new FileReader(families));
602
603     moveLocationBy(index, br);
604
605     String line = br.readLine();
606     PrintWriter writer = new PrintWriter(
607             new FileOutputStream(new File(location), true));
608     while (!"//".equals(line))
609     {
610       writer.println(line);
611       line = br.readLine();
612     }
613     writer.println(line);
614     writer.close();
615     br.close();
616
617   }
618
619   public void exportFile(BufferedReader br, String location, boolean append)
620           throws IOException
621   {
622     String line = br.readLine();
623     PrintWriter writer = new PrintWriter(
624             new FileOutputStream(location, append));
625     while (!"//".equals(line))
626     {
627       writer.println(line);
628       line = br.readLine();
629     }
630     writer.println(line);
631     writer.close();
632
633
634   }
635
636   public String getHMMName(int index) throws IOException
637   {
638     String name;
639
640     BufferedReader nameFinder = new BufferedReader(new FileReader(hmms));
641
642     moveLocationBy(index, nameFinder);
643
644     nameFinder.readLine();
645
646     Scanner scanner = new Scanner(nameFinder.readLine());
647     name = scanner.next();
648     name = scanner.next();
649     scanner.close();
650     return name;
651   }
652
653   public String getFamilyName(int index) throws IOException
654   {
655     String name;
656
657     BufferedReader nameFinder = new BufferedReader(
658             new FileReader(families));
659
660     moveLocationBy(index, nameFinder);
661
662     nameFinder.readLine();
663
664     Scanner scanner = new Scanner(nameFinder.readLine());
665     name = scanner.next();
666     name = scanner.next();
667     name = scanner.next();
668     scanner.close();
669     return name;
670   }
671
672   /**
673    * Prints the specified family to a .hmm file.
674    * 
675    * @param index
676    * @throws IOException
677    */
678   public void exportHMM(int index, String location) throws IOException
679   {
680
681
682     BufferedReader br = new BufferedReader(new FileReader(hmms));
683
684     moveLocationBy(index, br);
685
686     String line = br.readLine();
687
688     PrintWriter writer = new PrintWriter(
689             new FileOutputStream(new File(location), true));
690     while (!"//".equals(line))
691     {
692       writer.println(line);
693       line = br.readLine();
694     }
695     writer.println(line);
696     writer.close();
697     br.close();
698
699   }
700   
701   /**
702    * Clears all raw, binned and current position data in the current directory.
703    * 
704    * @throws FileNotFoundException
705    */
706   public void clear() throws FileNotFoundException
707   {
708     PrintWriter pos = new PrintWriter(
709             currentFolder + "/CurrentPosition.txt");
710     pos.println("0");
711     
712     PrintWriter raw = new PrintWriter(currentFolder + RAW);
713     
714     PrintWriter bin = new PrintWriter(currentFolder + BINNED);
715     
716     pos.close();
717     bin.close();
718     raw.close();
719   }
720
721   public void sortIntoClans(String directory) throws IOException
722   {
723     BufferedReader clanFinder = new BufferedReader(new FileReader(FAMILIESTOCLAN));
724     BufferedReader familyReader = new BufferedReader(
725             new FileReader(families));
726     BufferedReader hmmReader = new BufferedReader(new FileReader(hmms));
727     int families = 0;
728     // moveLocationBy(7000, familyReader);
729     // moveLocationBy(7000, clanFinder);
730     // moveLocationBy(7000, hmmReader);
731     HashMap<String, Integer> clanIndexes = new HashMap<>();
732     ArrayList<Integer> familyCounts = new ArrayList<>();
733     int filePos = 0; 
734     int clanCount = 0;
735     String line;
736     line = clanFinder.readLine();
737     
738     while (!"".equals(line) && !" ".equals(line) && line != null)
739     {
740      String clanName;
741       boolean inClan = false;
742      while (!(line.indexOf("//") > -1))
743      {
744        
745       if (line.indexOf("#=GF CL") > -1)
746       {
747           families++;
748           System.out.println(families);
749           inClan = true;
750         Scanner scanner = new Scanner(line);
751         scanner.next();
752         scanner.next();
753         clanName = scanner.next();
754           scanner.close();
755         
756         if (!clanIndexes.containsKey(clanName))
757         {
758           clanIndexes.put(clanName, clanCount);
759             clanCount++;
760             familyCounts.add(0);
761         }
762
763
764           Integer clanI = clanIndexes.get(clanName);
765           String clanPath = directory + "/Clan" + clanI.toString();
766           createFolders(clanPath);
767
768           int index = clanIndexes.get(clanName);
769           exportFile(familyReader,
770                   clanPath + "/Families/Fam" + familyCounts.get(index)
771                           + ".sto",
772                   false);
773           exportFile(hmmReader,
774                   clanPath + "/HMMs/HMM" + familyCounts.get(index) + ".hmm",
775                   false);
776
777           int count = familyCounts.get(index);
778           count++;
779           familyCounts.set(index, count);
780       }
781         line = clanFinder.readLine();
782
783       }
784       if (!inClan)
785       {
786         moveLocationBy(1, familyReader);
787         moveLocationBy(1, hmmReader);
788       }
789       filePos++;
790       // System.out.println(filePos + " files read.");
791       line = clanFinder.readLine();
792
793      }
794     clanFinder.close();
795
796     for (int clan = 0; clan < clanCount; clan++)
797     {
798       PrintWriter writer = new PrintWriter(
799               directory + "/Clan" + clan + "/NumberOfFamilies.txt");
800       int count = familyCounts.get(clan);
801       writer.print(count);
802       writer.close();
803     }
804       
805     }
806
807   public String getFamilies()
808   {
809     return families;
810   }
811
812   public void setFamilies(String families)
813   {
814     this.families = currentFolder + families;
815   }
816
817   public String getHmms()
818   {
819     return hmms;
820   }
821
822   public void setHmms(String hmms)
823   {
824     this.hmms = currentFolder + hmms;
825   }
826     
827   public void alignWithinClan(String exportLocation, String clansLocation)
828           throws IOException, InterruptedException
829   {
830     int alignmentsExported = 0;
831     for (int clan = 0; clan < 604; clan++)
832     {
833       System.out.println(clan);
834       int famCount = 0;
835       String clanPath = clansLocation + "/Clan" + clan;
836       int numberOfFamilies;
837       BufferedReader br = new BufferedReader(
838               new FileReader(clanPath + "/NumberOfFamilies.txt"));
839       String line = br.readLine();
840       numberOfFamilies = Integer.parseInt(line);
841       br.close();
842       if (numberOfFamilies == 1)
843       {
844         continue;
845       }
846       final String commandExportLocation = exportLocation + "/Clan" + clan;
847       createFolders(commandExportLocation);
848       for (int family = 0; family < numberOfFamilies; family++)
849       {
850         famCount++;
851         ArrayList<Integer> indexes = new ArrayList<>();
852         for (int i = 0; i < numberOfFamilies; i++)
853         {
854           if (i != family)
855           {
856             indexes.add(i);
857           }
858         }
859
860         int hmmIndex = getRandom(indexes);
861         String famPath = clanPath + "/Families/Fam" + family + ".sto";
862         String hmmPath = clanPath + "/HMMs/HMM" + hmmIndex + ".hmm";
863         String command = "/media/sf_Shared_Folder/hmmer/binaries/hmmalign --mapali "
864                 + clanPath + "/Families/Fam" + hmmIndex + ".sto"
865                 + " --trim ";
866         command += hmmPath + " ";
867         command += famPath;
868         final int familyIndex = family;
869         final Process p = Runtime.getRuntime().exec(command);
870
871         new Thread(new Runnable()
872         {
873           @Override
874           public void run()
875           {
876             BufferedReader input = new BufferedReader(
877                     new InputStreamReader(p.getInputStream()));
878             String line = null;
879
880             try
881             {
882               PrintWriter writer = new PrintWriter(commandExportLocation
883                       + "/Families/Fam" + familyIndex + ".sto");
884               String lastLine = "";
885               boolean dataFound = false;
886               while ((line = input.readLine()) != null)
887               {
888                 if (line.contains("#=GR") && !dataFound)
889                 {
890                   writer.println(lastLine);
891                   dataFound = true;
892                 }
893                 if (line.contains("#") || dataFound || " ".equals(line)
894                         || "".equals(line) || "//".equals(line))
895                 {
896                   writer.println(line);
897                 }
898                 lastLine = line;
899               }
900               writer.close();
901             } catch (IOException e)
902             {
903               e.printStackTrace();
904             }
905           }
906         }).start();
907
908         p.waitFor();
909
910         BufferedReader hmmExporter = new BufferedReader(
911                 new FileReader(hmmPath));
912
913         exportFile(hmmExporter,
914                 commandExportLocation + "/HMMs/HMM" + family + ".hmm",
915                 false);
916
917         alignmentsExported++;
918
919
920       }
921       PrintWriter writer = new PrintWriter(
922               commandExportLocation + "/NumberOfFamilies.txt");
923       writer.print(famCount);
924       writer.close();
925     }
926
927   }
928
929   public boolean atEnd(BufferedReader br) throws IOException
930   {
931     boolean end = false;
932     br.mark(80);
933     String line = br.readLine();
934     if ("".equals(line) || line == null)
935     {
936       end = true;
937     }
938     br.reset();
939     return end;
940   }
941
942   public int getRandom(ArrayList<Integer> list)
943   {
944     if (!(list.size() > 0))
945     {
946       System.out.println("Error - size = " + list.size());
947     }
948     int index = generator.nextInt(list.size());
949     int value = list.get(index);
950     list.remove(index);
951     return value;
952   }
953
954   public void createFolders(String clanPath)
955   {
956     File clanFolder = new File(clanPath);
957     if (!clanFolder.exists())
958     {
959       clanFolder.mkdir();
960     }
961
962     File famFolder = new File(clanPath + "/Families");
963     File hmmFolder = new File(clanPath + "/HMMs");
964     if (!famFolder.exists())
965     {
966       famFolder.mkdir();
967       hmmFolder.mkdir();
968     }
969   }
970 }
971
972
973
974