package beast.app.beauti;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import beast.app.draw.InputEditor;
import beast.app.draw.ListInputEditor;
import beast.core.BEASTInterface;
import beast.core.Input;
import beast.core.MCMC;
import beast.core.State;
import beast.core.StateNode;
import beast.core.StateNodeInitialiser;
import beast.evolution.tree.Tree;
public class StateNodeInitialiserListInputEditor extends ListInputEditor {
private static final long serialVersionUID = 1L;
public StateNodeInitialiserListInputEditor(BeautiDoc doc) {
super(doc);
}
@Override
public Class<?> type() {
return List.class;
}
@Override
public Class<?> baseType() {
return StateNodeInitialiser.class;
}
@Override
public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption,
boolean addButtons) {
super.init(input, beastObject, itemNr, isExpandOption, addButtons);
}
@Override
protected InputEditor addPluginItem(Box itemBox, BEASTInterface beastObject) {
final StateNodeInitialiser currentInitialiser = (StateNodeInitialiser) beastObject;
Input initialInput = beastObject.getInput("initial");
List<BeautiSubTemplate> sAvailablePlugins = doc.getInputEditorFactory().getAvailableTemplates(initialInput,
(BEASTInterface) beastObject, null, doc);
JComboBox<?> comboBox = null;
if (sAvailablePlugins.size() > 0) {
sAvailablePlugins.remove(sAvailablePlugins.size() - 1);
comboBox = new JComboBox<>(sAvailablePlugins.toArray());
String sID = beastObject.getID();
try {
sID = sID.substring(0, sID.indexOf('.'));
} catch (Exception e) {
throw new RuntimeException("Improperly formatted ID: " + sID);
}
for (BeautiSubTemplate template : sAvailablePlugins) {
if (template.matchesName(sID)) {
comboBox.setSelectedItem(template);
}
}
comboBox.setName("Initialiser");
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JComboBox<?> currentComboBox = (JComboBox<?>) e.getSource();
BeautiSubTemplate template = (BeautiSubTemplate) currentComboBox.getSelectedItem();
PartitionContext partitionContext;
partitionContext = doc.getContextFor(beastObject);
try {
Object o = template.createSubNet(partitionContext, true);
StateNodeInitialiser newInitialiser = (StateNodeInitialiser) o;
List<StateNodeInitialiser> inits = (List<StateNodeInitialiser>) m_input.get();
int i = inits.indexOf(currentInitialiser);
inits.set(i, newInitialiser);
System.out.println(inits.size());
} catch (Exception ex) {
ex.printStackTrace();
}
sync();
refreshPanel();
}
});
}
});
}
String name = beastObject.getID();
Object o = beastObject.getInput("initial").get();
if (o instanceof BEASTInterface) {
name = ((BEASTInterface) o).getID();
}
if (name == null || name.length() == 0) {
name = beastObject.getClass().getName();
name = name.substring(name.lastIndexOf('.') + 1);
}
JLabel label = new JLabel("Initial " + name + ":");
itemBox.add(Box.createRigidArea(new Dimension(5, 1)));
itemBox.add(label);
if (comboBox != null) {
itemBox.add(comboBox);
}
itemBox.add(Box.createHorizontalGlue());
return this;
}
public static boolean customConnector(BeautiDoc doc) {
// scrub Tree initialisers
// 0. collect state node info
List<StateNodeInitialiser> inits = ((MCMC)doc.mcmc.get()).initialisersInput.get();
State state = ((MCMC)doc.mcmc.get()).startStateInput.get();
List<StateNode> stateNodes = state.stateNodeInput.get();
List<Tree> trees = new ArrayList<>();
for (StateNode s: stateNodes) {
if (s instanceof Tree) {
trees.add((Tree) s);
}
}
List<List<StateNode>> initStateNodes = new ArrayList<>();
for (StateNodeInitialiser init : inits) {
List<StateNode> initStateNodes0 = new ArrayList<>();
init.getInitialisedStateNodes(initStateNodes0);
for (int i = initStateNodes0.size() - 1; i >= 0; i--) {
if (!(initStateNodes0.get(i) instanceof Tree)) {
initStateNodes0.remove(i);
}
}
initStateNodes.add(initStateNodes0);
}
// 1. remove initialisers that have no stateNode in state
for (int i = inits.size() - 1; i >= 0; i--) {
boolean found = false;
for (StateNode stateNode : initStateNodes.get(i)) {
if (trees.contains(stateNode)) {
found = true;
break;
}
}
if (!found) {
inits.remove(i);
initStateNodes.remove(i);
}
}
// 2. remove initialisers that share stateNodes
for (int i = inits.size() - 1; i >= 0; i--) {
for (int j = i - 1; j >= 0; j--) {
boolean found = false;
for (StateNode stateNode : initStateNodes.get(i)) {
if (initStateNodes.get(j).contains(stateNode)) {
found = true;
break;
}
}
if (found) {
inits.remove(i);
initStateNodes.remove(i);
}
}
}
// 3. add RandomTree for those trees not having a stateNodeInitialiser
boolean [] hasInitialiser = new boolean[trees.size()];
for (int i = inits.size() - 1; i >= 0; i--) {
for (StateNode stateNode : initStateNodes.get(i)) {
int k = trees.indexOf(stateNode);
if (k >= 0) {
hasInitialiser[k] = true;
break;
}
}
}
for (int i = 0; i < hasInitialiser.length; i++) {
if (!hasInitialiser[i]) {
for (BeautiSubTemplate tmp : doc.beautiConfig.subTemplates) {
if (tmp.getID().equals("RandomTree")) {
PartitionContext partition = doc.getContextFor(trees.get(i));
Object o = tmp.createSubNet(partition, false);
inits.add((StateNodeInitialiser) o);
}
}
}
}
return true;
}
}