6c1932acabda8bfdc7680d68ef762b93293dea9f
[jalview.git] / src / jalview / util / HMMProbabilityDistributionAnalyser.java
1 package jalview.util;
2
3 import jalview.datamodel.HiddenMarkovModel;
4 import jalview.datamodel.SequenceI;
5 import jalview.io.DataSourceType;
6 import jalview.io.FileParse;
7 import jalview.io.HMMFile;
8 import jalview.io.StockholmFile;
9 import jalview.schemes.ResidueProperties;
10
11 import java.io.BufferedReader;
12 import java.io.File;
13 import java.io.FileNotFoundException;
14 import java.io.FileOutputStream;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.io.PrintWriter;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Scanner;
23 import java.util.Vector;
24
25 /**
26  * Processes probability data. The file indexes used in this program represent
27  * the index of the location of a family or hmm in their respective files,
28  * starting from 0.
29  * 
30  * @author TZVanaalten
31  *
32  */
33 public class HMMProbabilityDistributionAnalyser
34 {
35
36   Vector<SequenceI> sequences;
37
38   HiddenMarkovModel hmm;
39
40   // contains the raw data produced
41   List<ArrayList<Double>> raw = new ArrayList<>();
42
43   // contains binned data
44   Map<String, Double> binned = new HashMap<>();
45
46   // location of the family file
47   String families = "H:/Desktop/PFAM/Family/SeedFamilies.seed";
48
49   // location of the file containing the family-clan links
50   final static String FAMILIESTOCLAN = "H:/Desktop/PFAM/Family/Clanlinks.dat";
51
52   // location of the HMM file
53   String hmms = "H:/Desktop/PFAM/HMMs/Pfam-A.hmm";
54
55   // suffix for raw file
56   final static String RAW = "/Raw.csv";
57
58   // suffix for binned file
59   final static String BINNED = "/Binned.csv";
60
61   // normalisation scale
62   final static double SCALE = 1;
63
64   // current position in file
65   int currentFilePosition = 0;
66
67   final static String NL = "\n";
68
69   // current directory
70   String currentFolder;
71
72   boolean keepRaw = false;
73
74   /**
75    * Sets the working directory.
76    * 
77    * @param path
78    */
79   public void setFolder(String path)
80   {
81     currentFolder = path;
82   }
83
84   /**
85    * Moves a buffered reader forward in the file by a certain amount of entries.
86    * Each entry in the file is delimited by '//'.
87    * 
88    * @param index
89    *          The index of the location in the file.
90    * @param br
91    * @throws IOException
92    */
93   public void moveLocationBy(int index, BufferedReader br)
94           throws IOException
95   {
96     for (int i = 0; i < index; i++)
97     {
98       String line = br.readLine();
99       while (!"//".equals(line))
100       {
101         line = br.readLine();
102       }
103     }
104
105   }
106   
107   /**
108    * Analyses a specified number of families and then saves the data. Before
109    * analysing the data, the previous saved data will be imported and after
110    * analysing this, the data is exported back into the file.
111    * 
112    * @param increments
113    *          The number of families to read before saving.
114    * @throws IOException
115    */
116   public void run(int increments, boolean keepRawData) throws IOException
117   {
118     keepRaw = keepRawData;
119     try
120     {
121       readPreviousData(currentFolder);
122       BufferedReader posReader = new BufferedReader(
123               new FileReader(currentFolder + "/CurrentPosition.txt"));
124
125       String line = posReader.readLine();
126       posReader.close();
127       currentFilePosition = Integer.parseInt(line);
128     } catch (Exception e)
129     {
130       System.out.println("No previous data found");
131     }
132
133
134
135     BufferedReader inputSTO = new BufferedReader(new FileReader(families));
136     BufferedReader inputHMM = new BufferedReader(new FileReader(hmms));
137
138
139
140     moveLocationBy(currentFilePosition, inputHMM);
141     moveLocationBy(currentFilePosition, inputSTO);
142
143     int filesRead = 0;
144     int i = 0;
145     while (filesRead < increments)
146     {
147
148       FileParse parserSTO = new FileParse(inputSTO, "",
149               DataSourceType.FILE);
150       readStockholm(parserSTO);
151
152       FileParse parserHMM = new FileParse(inputHMM, "",
153               DataSourceType.FILE);
154       readHMM(parserHMM);
155
156         int count = countValidResidues();
157         processData(count);
158         filesRead++;
159
160       currentFilePosition++;
161       System.out.println(i);
162       i++;
163     }
164
165     PrintWriter p = new PrintWriter(
166             new File(currentFolder + "/CurrentPosition.txt"));
167     p.print(currentFilePosition);
168     p.close();
169     exportData(currentFolder);
170     raw.clear();
171     binned.clear();
172
173   }
174
175   /**
176    * Analyses all families and then saves the data. Before analysing the data,
177    * the previous saved data will be imported and after analysing this, the data
178    * is exported back into the file.
179    * 
180    * @param increments
181    *          The number of families to read before saving.
182    * @throws IOException
183    */
184   public void runToEnd(boolean keepRawData) throws IOException
185   {
186     keepRaw = keepRawData;
187     BufferedReader inputSTO = null;
188     BufferedReader inputHMM = null;
189     int size = 0;
190     try
191     {
192       readPreviousData(currentFolder);
193       BufferedReader posReader = new BufferedReader(
194               new FileReader(currentFolder + "/CurrentPosition.txt"));
195
196       String line = posReader.readLine();
197       posReader.close();
198       currentFilePosition = Integer.parseInt(line);
199       readPreviousData(currentFolder);
200       
201       inputSTO = new BufferedReader(new FileReader(families));
202       inputHMM = new BufferedReader(new FileReader(hmms));
203     } catch (Exception e)
204     {
205       System.out.println("No or incomplete previous data found");
206     }
207
208     
209
210     moveLocationBy(currentFilePosition, inputHMM);
211     moveLocationBy(currentFilePosition, inputSTO);
212
213     int filesRead = 0;
214     int i = 0;
215     inputSTO.mark(20);
216     String check = inputSTO.readLine();
217     inputSTO.reset();
218     while (!"".equals(check) && !" ".equals(check) && check != null)
219       {
220       inputSTO.mark(20);
221       String line = inputSTO.readLine();
222       inputSTO.reset();
223
224         FileParse parserSTO = new FileParse(inputSTO, "",
225                 DataSourceType.FILE);
226         readStockholm(parserSTO);
227
228         FileParse parserHMM = new FileParse(inputHMM, "",
229                 DataSourceType.FILE);
230         readHMM(parserHMM);
231
232         int count = countValidResidues();
233         processData(count);
234         filesRead++;
235
236         currentFilePosition++;
237         System.out.println(i);
238         i++;
239       inputSTO.mark(20);
240       check = inputSTO.readLine();
241       inputSTO.reset();
242       }
243
244
245     PrintWriter p = new PrintWriter(
246             new File(currentFolder + "/CurrentPosition.txt"));
247     p.print(currentFilePosition);
248     p.close();
249     exportData(currentFolder);
250     raw.clear();
251     binned.clear();
252
253   }
254
255   /**
256    * Reads the previous data from both files
257    * 
258    * @param source
259    * @throws IOException
260    */
261   public void readPreviousData(String source) throws IOException
262   {
263     readBinned(source);
264     if (keepRaw)
265     {
266       readRaw(source);
267     }
268   }
269
270   /**
271    * Reads the previous data from the binned file.
272    * 
273    * @param source
274    * @throws IOException
275    */
276   public void readBinned(String source) throws IOException
277   {
278     BufferedReader input = new BufferedReader(
279             new FileReader(source + BINNED));
280     String line = input.readLine();
281     binned = new HashMap<>();
282     while (!("".equals(line) || line == null))
283     {
284       Scanner scanner = new Scanner(line);
285       scanner.useDelimiter(",");
286       String key = scanner.next();
287       String value = scanner.next();
288       binned.put(key, Double.valueOf(value));
289       scanner.close();
290       line = input.readLine();
291     }
292
293     input.close();
294   }
295
296   /**
297    * Reads the previous data from the raw file.
298    * 
299    * @param source
300    * @throws IOException
301    */
302   public void readRaw(String source) throws IOException
303   {
304     BufferedReader input = new BufferedReader(new FileReader(source + RAW));
305     String line = input.readLine();
306     if (line == null)
307     {
308       input.close();
309       return;
310     }
311     Scanner numberScanner = new Scanner(line);
312     numberScanner.useDelimiter(",");
313     raw = new ArrayList<>();
314     while (numberScanner.hasNext())
315     {
316       numberScanner.next();
317       raw.add(new ArrayList<Double>());
318     }
319     numberScanner.close();
320
321     line = input.readLine();
322     while (!("".equals(line) || line == null))
323     {
324       Scanner scanner = new Scanner(line);
325       scanner.useDelimiter(",");
326
327       int i = 0;
328       while (scanner.hasNext())
329       {
330         String value;
331         value = scanner.next();
332         if (!value.equals("EMPTY"))
333         {
334           raw.get(i).add(Double.parseDouble(value));
335         }
336         else
337         {
338           raw.get(i).add(null);
339         }
340
341         i++;
342       }
343       scanner.close();
344       line = input.readLine();
345     }
346
347     input.close();
348   }
349
350   /**
351    * Counts the number of valid residues in the sequence.
352    * 
353    * @return
354    */
355   public int countValidResidues()
356   {
357     int count = 0;
358
359     for (int width = 0; width < sequences.size(); width++)
360     {
361       for (int length = 1; length < hmm.getLength() + 1; length++)
362       {
363         char symbol;
364         int alignPos;
365         alignPos = hmm.getNodeAlignmentColumn(length);
366
367         symbol = sequences.get(width).getCharAt(alignPos);
368         if (ResidueProperties.aminoBackgroundFrequencies
369                 .containsKey(symbol))
370         {
371           count++;
372         }
373       }
374     }
375
376     return count;
377   }
378
379   /**
380    * Processes data, and stores it in both a raw and binned format.
381    * 
382    * @param count
383    */
384   public void processData(int count)
385   {
386     int rawPos = 0;
387     if (keepRaw)
388     {
389       raw.add(new ArrayList<Double>());
390       rawPos = raw.size() - 1;
391     }
392
393     for (int width = 0; width < sequences.size(); width++)
394     {
395       for (int length = 1; length < hmm.getLength() + 1; length++)
396       {
397         char symbol;
398         int alignPos;
399         alignPos = hmm.getNodeAlignmentColumn(length);
400         
401         symbol = sequences.get(width).getCharAt(alignPos);
402         if (ResidueProperties.aminoBackgroundFrequencies
403                 .containsKey(symbol))
404         {
405           Double prob;
406           Float bfreq;
407           Double llr;
408           prob = hmm.getMatchEmissionProbability(alignPos, symbol);
409           bfreq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
410           llr = Math.log(prob / bfreq);
411           if (keepRaw)
412           {
413             raw.get(rawPos).add(llr);
414           }
415
416           String output;
417           output = String.format("%.1f", llr);
418           if ("-0.0".equals(output))
419           {
420             output = "0.0";
421           }
422           if (binned.containsKey(output))
423           {
424             double prev = binned.get(output);
425             prev += (SCALE / count);
426             binned.put(output, prev);
427
428           }
429           else
430           {
431             binned.put(output, SCALE / count);
432           }
433         }
434       }
435     }
436   }
437
438
439   /**
440    * Reads in the sequence data from a Stockholm file.
441    * 
442    * @param source
443    * @throws IOException
444    */
445   public void readStockholm(FileParse source) throws IOException
446   {
447     StockholmFile file = new StockholmFile(source);
448     sequences = file.getSeqs();
449   }
450
451   /**
452    * Reads in the HMM data from a HMMer file.
453    * 
454    * @param source
455    * @throws IOException
456    */
457   public void readHMM(FileParse source) throws IOException
458   {
459
460     HMMFile file = new HMMFile(source);
461     file.parse();
462     hmm = file.getHMM();
463
464   }
465
466   /**
467    * Exports both the binned and raw data into separate files.
468    * 
469    * @param location
470    * @throws FileNotFoundException
471    */
472   public void exportData(String location) throws FileNotFoundException
473   {
474     PrintWriter writerBin = new PrintWriter(new File(location + BINNED));
475     for (Map.Entry<String, Double> entry : binned.entrySet())
476     {
477       writerBin.println(entry.getKey() + "," + entry.getValue());
478     }
479     writerBin.close();
480     if (keepRaw)
481     {
482
483     PrintWriter writerRaw = new PrintWriter(new File(location + RAW));
484     
485     StringBuilder identifier = new StringBuilder();
486     
487     for (int i = 1; i < raw.size() + 1; i++)
488     {
489       identifier.append("Fam " + i + ",");
490     }
491     
492     writerRaw.println(identifier);
493     
494     boolean rowIsEmpty = false;
495     int row = 0;
496     while (!rowIsEmpty)
497     {
498       rowIsEmpty = true;
499       StringBuilder string = new StringBuilder();
500       for (int column = 0; column < raw.size(); column++)
501       {
502         if (raw.get(column).size() <= row)
503         {
504           string.append("EMPTY,");
505         }
506         else
507         {
508           string.append(raw.get(column).get(row) + ",");
509           rowIsEmpty = false;
510         }
511       }
512       row++;
513       writerRaw.println(string);
514     }
515     writerRaw.close();
516
517     }
518
519   }
520
521   /**
522    * Prints the specified family on the console.
523    * 
524    * @param index
525    * @throws IOException
526    */
527   public void printFam(int index) throws IOException
528   {
529     BufferedReader br = new BufferedReader(new FileReader(families));
530
531     moveLocationBy(index, br);
532
533     String line = br.readLine();
534
535     while (!"//".equals(line))
536     {
537       System.out.println(line);
538       line = br.readLine();
539     }
540     System.out.println(line);
541     br.close();
542
543   }
544
545   /**
546    * Prints the specified HMM on the console.
547    * 
548    * @param index
549    * @throws IOException
550    */
551   public void printHMM(int index) throws IOException
552   {
553     BufferedReader br = new BufferedReader(new FileReader(hmms));
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 family to a .sto file.
571    * 
572    * @param index
573    * @throws IOException
574    */
575   public void exportFam(int index, String location) throws IOException
576   {
577     BufferedReader br = new BufferedReader(new FileReader(families));
578
579     moveLocationBy(index, br);
580
581     String line = br.readLine();
582     PrintWriter writer = new PrintWriter(
583             new FileOutputStream(new File(location), true));
584     while (!"//".equals(line))
585     {
586       writer.println(line);
587       line = br.readLine();
588     }
589     writer.println(line);
590     writer.close();
591     br.close();
592
593   }
594
595   public void exportFile(BufferedReader br, String location)
596           throws IOException
597   {
598     String line = br.readLine();
599     PrintWriter writer = new PrintWriter(
600             new FileOutputStream(new File(location), true));
601     while (!"//".equals(line))
602     {
603       writer.println(line);
604       line = br.readLine();
605     }
606     writer.println(line);
607     writer.close();
608
609
610   }
611
612   public String getHMMName(int index) throws IOException
613   {
614     String name;
615
616     BufferedReader nameFinder = new BufferedReader(new FileReader(hmms));
617
618     moveLocationBy(index, nameFinder);
619
620     nameFinder.readLine();
621
622     Scanner scanner = new Scanner(nameFinder.readLine());
623     name = scanner.next();
624     name = scanner.next();
625     scanner.close();
626     return name;
627   }
628
629   public String getFamilyName(int index) throws IOException
630   {
631     String name;
632
633     BufferedReader nameFinder = new BufferedReader(
634             new FileReader(families));
635
636     moveLocationBy(index, nameFinder);
637
638     nameFinder.readLine();
639
640     Scanner scanner = new Scanner(nameFinder.readLine());
641     name = scanner.next();
642     name = scanner.next();
643     name = scanner.next();
644     scanner.close();
645     return name;
646   }
647
648   /**
649    * Prints the specified family to a .hmm file in the current directory.
650    * 
651    * @param index
652    * @throws IOException
653    */
654   public void exportHMM(int index, String location) throws IOException
655   {
656
657
658     BufferedReader br = new BufferedReader(new FileReader(hmms));
659
660     moveLocationBy(index, br);
661
662     String line = br.readLine();
663
664     PrintWriter writer = new PrintWriter(
665             new FileOutputStream(new File(location), true));
666     while (!"//".equals(line))
667     {
668       writer.println(line);
669       line = br.readLine();
670     }
671     writer.println(line);
672     writer.close();
673     br.close();
674
675   }
676   
677   /**
678    * Clears all raw, binned and current position data in the current directory.
679    * 
680    * @throws FileNotFoundException
681    */
682   public void clear() throws FileNotFoundException
683   {
684     PrintWriter pos = new PrintWriter(
685             currentFolder + "/CurrentPosition.txt");
686     pos.println("0");
687     
688     PrintWriter raw = new PrintWriter(currentFolder + RAW);
689     
690     PrintWriter bin = new PrintWriter(currentFolder + BINNED);
691     
692     pos.close();
693     bin.close();
694     raw.close();
695   }
696
697   public void sortIntoClans(String directory) throws IOException
698   {
699     BufferedReader clanFinder = new BufferedReader(new FileReader(FAMILIESTOCLAN));
700     BufferedReader familyReader = new BufferedReader(
701             new FileReader(families));
702     BufferedReader hmmReader = new BufferedReader(new FileReader(hmms));
703     HashMap<String, Integer> clanIndexes = new HashMap<>();
704     int filePos = 0; 
705     int clanCount = 0;
706     String line;
707     line = clanFinder.readLine();
708     
709     while (!"".equals(line) && !" ".equals(line) && line != null)
710     {
711      String clanName;
712       boolean inClan = false;
713      while (!(line.indexOf("//") > -1))
714      {
715        
716       if (line.indexOf("#=GF CL") > -1)
717       {
718           inClan = true;
719         Scanner scanner = new Scanner(line);
720         scanner.next();
721         scanner.next();
722         clanName = scanner.next();
723           scanner.close();
724         
725         if (!clanIndexes.containsKey(clanName))
726         {
727           clanIndexes.put(clanName, clanCount);
728             clanCount++;
729         }
730
731
732           Integer clanI = clanIndexes.get(clanName);
733           String clanPath = directory + "/Clan" + clanI.toString();
734           File clanFolder = new File(clanPath);
735           String famPath = clanPath + "/Families.sto";
736           String hmmPath = clanPath + "/HMMs.hmm";
737           if (!clanFolder.exists())
738         {
739             clanFolder.mkdir();
740         }
741           exportFile(familyReader, famPath);
742           exportFile(hmmReader, hmmPath);
743
744       }
745         line = clanFinder.readLine();
746       }
747       if (!inClan)
748       {
749         moveLocationBy(1, familyReader);
750         moveLocationBy(1, hmmReader);
751       }
752       filePos++;
753       System.out.println(filePos + " files read.");
754       line = clanFinder.readLine();
755
756      }
757     clanFinder.close();
758       
759     }
760
761   public String getFamilies()
762   {
763     return families;
764   }
765
766   public void setFamilies(String families)
767   {
768     this.families = currentFolder + families;
769   }
770
771   public String getHmms()
772   {
773     return hmms;
774   }
775
776   public void setHmms(String hmms)
777   {
778     this.hmms = currentFolder + hmms;
779   }
780     
781
782
783   }
784
785