package beast.app.beauti; import java.awt.Color; import java.util.ArrayList; import java.util.List; import javax.swing.Box; import javax.swing.JCheckBox; import javax.swing.JTextField; import beast.app.draw.ListInputEditor; import beast.app.draw.SmallLabel; import beast.core.BEASTInterface; import beast.core.Input; import beast.core.MCMC; import beast.core.Operator; import beast.core.parameter.IntegerParameter; import beast.core.parameter.RealParameter; import beast.core.util.Log; import beast.evolution.alignment.Alignment; import beast.evolution.branchratemodel.BranchRateModel; import beast.evolution.operators.DeltaExchangeOperator; public class ClockModelListInputEditor extends ListInputEditor { private static final long serialVersionUID = 1L; List<JTextField> textFields = new ArrayList<>(); List<Operator> operators = new ArrayList<>(); public ClockModelListInputEditor(BeautiDoc doc) { super(doc); } @Override public Class<?> type() { return List.class; } @Override public Class<?> baseType() { // disable this editor return ClockModelListInputEditor.class; //return BranchRateModel.Base.class; } JCheckBox fixMeanRatesCheckBox; DeltaExchangeOperator operator; protected SmallLabel fixMeanRatesValidateLabel; @Override public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) { fixMeanRatesCheckBox = new JCheckBox("Fix mean rate of clock models"); m_buttonStatus = ButtonStatus.NONE; super.init(input, beastObject, itemNr, isExpandOption, addButtons); List<Operator> operators = ((MCMC) doc.mcmc.get()).operatorsInput.get(); fixMeanRatesCheckBox.addActionListener(e -> { JCheckBox averageRatesBox = (JCheckBox) e.getSource(); boolean averageRates = averageRatesBox.isSelected(); List<Operator> operators2 = ((MCMC) doc.mcmc.get()).operatorsInput.get(); if (averageRates) { // connect DeltaExchangeOperator if (!operators2.contains(operator)) { operators2.add(operator); } // set up relative weights setUpOperator(); } else { operators2.remove(operator); fixMeanRatesValidateLabel.setVisible(false); repaint(); } }); operator = (DeltaExchangeOperator) doc.pluginmap.get("FixMeanRatesOperator"); if (operator == null) { operator = new DeltaExchangeOperator(); try { operator.setID("FixMeanRatesOperator"); operator.initByName("weight", 2.0, "delta", 0.75); } catch (Exception e1) { // ignore initAndValidate exception } doc.addPlugin(operator); } fixMeanRatesCheckBox.setSelected(operators.contains(operator)); Box box = Box.createHorizontalBox(); box.add(fixMeanRatesCheckBox); box.add(Box.createHorizontalGlue()); fixMeanRatesValidateLabel = new SmallLabel("x", Color.GREEN); fixMeanRatesValidateLabel.setVisible(false); box.add(fixMeanRatesValidateLabel); if (((List<?>) input.get()).size() > 1 && operator != null) { add(box); } setUpOperator(); } @Override public void validateInput() { super.validateInput(); Log.warning.println("validateInput()"); } /** set up relative weights and parameter input **/ private void setUpOperator() { String weights = ""; List<RealParameter> parameters = operator.parameterInput.get(); parameters.clear(); double commonClockRate = -1; boolean isAllClocksAreEqual = true; try { for (int i = 0; i < doc.alignments.size(); i++) { Alignment data = doc.alignments.get(i); int weight = data.getSiteCount(); BranchRateModel.Base clockModel = (BranchRateModel.Base) doc.clockModels.get(i); RealParameter clockRate = clockModel.meanRateInput.get(); //clockRate.m_bIsEstimated.setValue(true, clockRate); if (clockRate.isEstimatedInput.get()) { if (commonClockRate < 0) { commonClockRate = clockRate.valuesInput.get().get(0); } else { if (Math.abs(commonClockRate - clockRate.valuesInput.get().get(0)) > 1e-10) { isAllClocksAreEqual = false; } } weights += weight + " "; parameters.add(clockRate); } //doc.autoSetClockRate = false; } if (!fixMeanRatesCheckBox.isSelected()) { fixMeanRatesValidateLabel.setVisible(false); return; } if (parameters.size() == 0) { fixMeanRatesValidateLabel.setVisible(true); fixMeanRatesValidateLabel.m_circleColor = Color.red; fixMeanRatesValidateLabel.setToolTipText("The model is invalid: At least one clock rate should be estimated."); return; } IntegerParameter weightParameter = new IntegerParameter(weights); weightParameter.setID("weightparameter"); weightParameter.isEstimatedInput.setValue(false, weightParameter); operator.parameterWeightsInput.setValue(weightParameter, operator); if (!isAllClocksAreEqual) { fixMeanRatesValidateLabel.setVisible(true); fixMeanRatesValidateLabel.m_circleColor = Color.orange; fixMeanRatesValidateLabel.setToolTipText("Not all clocks are equal. Are you sure this is what you want?"); } else if (parameters.size() == 1) { fixMeanRatesValidateLabel.setVisible(true); fixMeanRatesValidateLabel.m_circleColor = Color.orange; fixMeanRatesValidateLabel.setToolTipText("At least 2 clock models should have their rate estimated"); } else if (parameters.size() < doc.alignments.size()) { fixMeanRatesValidateLabel.setVisible(true); fixMeanRatesValidateLabel.m_circleColor = Color.orange; fixMeanRatesValidateLabel.setToolTipText("Not all partitions have their rate estimated"); } else { fixMeanRatesValidateLabel.setVisible(false); } repaint(); //doc.autoSetClockRate = true; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // OperatorListInputEditor