package statalign.postprocess.plugins;
import java.awt.BorderLayout;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import statalign.base.InputData;
import statalign.base.McmcStep;
import statalign.base.State;
import statalign.base.Utils;
import statalign.postprocess.Postprocess;
import statalign.postprocess.Track;
import statalign.postprocess.gui.AlignmentGUI;
import statalign.ui.ErrorMessage;
/**
* This is the postprocessmanager for showing the current alignment.
*
* @author miklos, novak
*
*/
public class CurrentAlignment extends statalign.postprocess.Postprocess{
public JPanel pan;
public String[] allAlignment;
public String[] leafAlignment;
public String title;
InputData input;
String[] seqNames;
public String[] getSeqNames() { return seqNames; }
String[] leafNames;
/** We will refer to this to get the posterior probabilities of the current alignment. */
MpdAlignment mpdAli;
double[] decoding;
boolean plotPosterior = true;
/** Whether to plot the full alignment with internal nodes. */
public boolean showFullAlignment = true;
AlignmentGUI gui;
/**
* It construct a postprocess that is screenable (=can be shown on the GUI),
* outputable (= can be written into th elog file) but not postprocessable
* (= cannot generate its own output file).
*/
public CurrentAlignment(){
screenable = true;
outputable = true;
postprocessable = true;
postprocessWrite = false;
sampling = true;
rnaAssociated = false;
}
/**
* It constructs a new JPanel, and returns with it
*/
@Override
public JPanel getJPanel() {
pan = new JPanel(new BorderLayout());
return pan;
}
/**
* It generates a new icon based on the figure in file icons/calignment.gif
*/
@Override
public Icon getIcon() {
// return new ImageIcon("icons/calignment.gif");
return new ImageIcon(ClassLoader.getSystemResource("icons/calignment.gif"));
}
/**
* It returns with its tab name, 'Alignment'
*/
@Override
public String getTabName() {
return "Alignment";
}
/**
* It returns with the tip of the tabulated panel 'Current alignment in the Markov chain'
* (shown when mouse is moved over the panel)
*/
@Override
public String getTip() {
return "Current alignment in the Markov chain";
}
@Override
public double getTabOrder() {
return 2.0d;
}
@Override
public String getFileExtension() {
return "ali";
}
/**
* Updates the alignment.
*/
@Override
public void newPeek(State state){
if(show) {
updateAlignment(state);
}
}
private void updateAlignment(State state) {
String[] rows = showFullAlignment ? state.getFullAlign() : state.getLeafAlign();
for(int i = 0; i < rows.length; i++)
//allAlignment[i] = seqNames[i]+'\t'+rows[i];
allAlignment[i] = rows[i];
int ind = 0;
//System.out.println("allAlignment.length = "+allAlignment.length+"leafAlignment.length = "+leafAlignment.length);
for(int i = 0; i < allAlignment.length; i++) {
if (seqNames[i].charAt(0) != ' ') {
leafAlignment[ind] = allAlignment[i];
leafNames[ind] = seqNames[i];
ind++;
}
//leafAlignment[i] = allAlignment[i];
}
//if(allAlignment[i].charAt(0) != ' ')
//leafAlignment[ind++] = allAlignment[i];
if (plotPosterior) decoding = mpdAli.getPosteriorSplus();
if(show) {
gui.alignment = allAlignment;
gui.sequenceNames = seqNames;
if (plotPosterior) gui.decoding = decoding;
gui.repaint();
}
}
/**
* Initializes the graphical interface.
*/
@Override
public void beforeFirstSample(InputData input) {
if(show) {
pan.removeAll();
title = input.title;
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(gui = new AlignmentGUI(title,input.model,this));//, mcmc.tree.printedAlignment()));
gui.title = input.title;
pan.add(scroll, BorderLayout.CENTER);
}
leafAlignment = new String[input.seqs.size()];
leafNames = new String[input.seqs.size()];
this.input = input;
// seqNames
int nl = input.seqs.size();
int nn = nl*2-1, i;
seqNames = new String[nn];
for(i = 0; i < nl; i++) {
seqNames[i] = input.seqs.getSeqNamePadded(i);
leafNames[i] = seqNames[i];
}
StringBuilder b = new StringBuilder();
for(int j = 0; j < seqNames[0].length(); j++)
b.append(' ');
String empty = b.toString();
for(; i < nn; i++)
seqNames[i] = empty;
allAlignment = new String[nn];
}
/**
* At each mcmc sampling point, the current alignment is shown on the GUI.
* Also, it writes the current alignment into the log file when in
* sampling mode.
*/
@Override
public void newSample(State state, int no, int total) {
//System.out.println("THIS IS THE CURRENT ALIGNMENT" + state.getFullAlign());
updateAlignment(state);
if(postprocessWrite) {
try {
String[] alignment = Utils.alignmentTransformation(allAlignment, seqNames, alignmentType, input);
for(int i = 0; i < alignment.length; i++){
if (state.isBurnin) outputFile.write("Burnin "+no+"\tAlignment:"+"\t"+alignment[i]+"\n");
else outputFile.write("Sample "+no+"\tAlignment:"+"\t"+alignment[i]+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
else if(sampling){
try {
String[] alignment = Utils.alignmentTransformation(allAlignment, seqNames, alignmentType, input);
for(int i = 0; i < alignment.length; i++){
if (state.isBurnin) file.write("Burnin "+no+"\tAlignment:"+"\t"+alignment[i]+"\n");
else file.write("Sample "+no+"\tAlignment:"+"\t"+alignment[i]+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Temporary fileprinting method to generate single files containing the current alignment. Used when testing
* the performance of cold and heated chains in mcmcmc.
*/
public void singleFilePrint(int no, int total) {
if(sampling){
try {
System.out.println("Alignment type: "+ alignmentType);
String[] alignment = Utils.alignmentTransformation(allAlignment, seqNames, alignmentType, input);
for(int i = 0; i < alignment.length; i++){
file.write(alignment[i]+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void afterLastSample() {
if (postprocessWrite) {
try {
outputFile.flush();
outputFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Toggles sampling mode.
*/
@Override
public void setSampling(boolean enabled){
sampling = enabled;
}
}