All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.cmu.tetradapp.knowledge_editor.KnowledgeBoxEditor Maven / Gradle / Ivy

The newest version!
///////////////////////////////////////////////////////////////////////////////
// For information as to what this class does, see the Javadoc, below.       //
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,       //
// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard        //
// Scheines, Joseph Ramsey, and Clark Glymour.                               //
//                                                                           //
// This program is free software; you can redistribute it and/or modify      //
// it under the terms of the GNU General Public License as published by      //
// the Free Software Foundation; either version 2 of the License, or         //
// (at your option) any later version.                                       //
//                                                                           //
// This program is distributed in the hope that it will be useful,           //
// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
// GNU General Public License for more details.                              //
//                                                                           //
// You should have received a copy of the GNU General Public License         //
// along with this program; if not, write to the Free Software               //
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA //
///////////////////////////////////////////////////////////////////////////////
package edu.cmu.tetradapp.knowledge_editor;

import edu.cmu.tetrad.data.*;
import edu.cmu.tetrad.graph.LayoutUtil;
import edu.cmu.tetrad.graph.Node;
import edu.cmu.tetrad.graph.NodeVariableType;
import edu.cmu.tetrad.util.JOptionUtils;
import edu.cmu.tetrad.util.TetradLogger;
import edu.cmu.tetradapp.model.ForbiddenGraphModel;
import edu.cmu.tetradapp.model.KnowledgeBoxModel;
import edu.cmu.tetradapp.model.RemoveNonSkeletonEdgesModel;
import org.apache.commons.math3.util.FastMath;

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serial;
import java.util.List;
import java.util.*;
import java.util.prefs.Preferences;

/**
 * Edits knowledge of forbidden and required edges.
 *
 * @author kaalpurush
 * @version $Id: $Id
 */
public class KnowledgeBoxEditor extends JPanel {

    @Serial
    private static final long serialVersionUID = 959706288096545158L;

    /**
     * Edge limit for displaying edges in the edge panel
     */
    private static final long EDGE_LIMIT = 100;

    /**
     * The background color for unselected labels.
     */
    private final Color UNSELECTED_BG = new Color(153, 204, 204);

    /**
     * The background color for selected labels.
     */
    private final Color SELECTED_BG = new Color(255, 204, 102);

    /**
     * Map from variable names to labels.
     */
    private final Map labelMap = new HashMap<>();

    /**
     * The variables in the knowledge.
     */
    private final List vars;

    /**
     * The variables in the first tier.
     */
    private final List firstTierVars = new LinkedList<>();

    /**
     * The variables in the second tier.
     */
    private final List secondTierVars = new LinkedList<>();

    /**
     * The knowledge box model.
     */
    private final KnowledgeBoxModel knowledgeBoxModel;

    /**
     * The tabbed pane.
     */
    private final JTabbedPane tabbedPane;

    /**
     * The knowledge.
     */
    private Knowledge knowledge;

    /**
     * The edge workbench.
     */
    private KnowledgeWorkbench edgeWorkbench;

    /**
     * The number of tiers to display.
     */
    private JPanel tiersPanel;

    /**
     * True if edges explicitly forbidden should be shown.
     */
    private boolean showForbiddenExplicitly;

    /**
     * True if edges required by groups should be shown.
     */
    private boolean showForbiddenByTiers;

    /**
     * True if edges required by groups should be shown.
     */
    private boolean showRequired;

    /**
     * True if edges required by groups should be shown.
     */
    private boolean showRequiredByGroups;

    /**
     * True if edges forbidden by groups should be shown.
     */
    private boolean showForbiddenByGroups;

    /**
     * The number of tiers to display.
     */
    private int numTiers = 3;

    /**
     * 

Constructor for KnowledgeBoxEditor.

* * @param knowledgeBoxModel a {@link edu.cmu.tetradapp.model.ForbiddenGraphModel} object */ public KnowledgeBoxEditor(ForbiddenGraphModel knowledgeBoxModel) { this((KnowledgeBoxModel) knowledgeBoxModel); } /** *

Constructor for KnowledgeBoxEditor.

* * @param knowledgeBoxModel a {@link edu.cmu.tetradapp.model.RemoveNonSkeletonEdgesModel} object */ public KnowledgeBoxEditor(RemoveNonSkeletonEdgesModel knowledgeBoxModel) { this((KnowledgeBoxModel) knowledgeBoxModel); } /** * Constructs a Knowledge editor for the given knowledge, variable names (that is, the list of all variable names to * be considered, which may vary from object to object even for the same knowledge), and possible source graph. The * source graph is used only to arrange nodes in the edge panel. * * @param knowledgeBoxModel a {@link edu.cmu.tetradapp.model.KnowledgeBoxModel} object */ public KnowledgeBoxEditor(KnowledgeBoxModel knowledgeBoxModel) { this.vars = knowledgeBoxModel.getVariables(); this.knowledge = knowledgeBoxModel.getKnowledge(); this.knowledgeBoxModel = knowledgeBoxModel; setLayout(new BorderLayout()); JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.LEFT); this.tabbedPane = tabbedPane; resetTabbedPane(); add(tabbedPane, BorderLayout.CENTER); setPreferredSize(new Dimension(640, 500)); add(menuBar(), BorderLayout.NORTH); addComponentListener(new ComponentAdapter() { @Override public void componentHidden(ComponentEvent e) { TetradLogger.getInstance().log("Edited Knowledge:"); String message = KnowledgeBoxEditor.this.knowledge.toString(); TetradLogger.getInstance().log(message); } }); initComponents(); setNumDisplayTiers(this.knowledge.getNumTiers()); } private void initComponents() { getKnowledge().getVariables().forEach(e -> this.labelMap.put(e, createJLabel(e))); getKnowledge().getVariablesNotInTiers().forEach(e -> this.labelMap.put(e, createJLabel(e))); } private JLabel createJLabel(String name) { JLabel label = new JLabel(String.format(" %s ", name)); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); label.setBorder(new CompoundBorder(new MatteBorder(2, 2, 2, 2, Color.WHITE), new LineBorder(Color.BLACK))); label.setForeground(Color.BLACK); label.setBackground(this.UNSELECTED_BG); return label; } private JMenuBar menuBar() { JMenuBar menuBar = new JMenuBar(); JMenu file = new JMenu("File"); menuBar.add(file); JMenuItem loadKnowledge = new JMenuItem("Load Knowledge..."); JMenuItem saveKnowledge = new JMenuItem("Save Knowledge..."); file.add(loadKnowledge); file.add(saveKnowledge); loadKnowledge.addActionListener((e) -> { JFileChooser chooser = new JFileChooser(); String sessionSaveLocation = Preferences.userRoot().get("fileSaveLocation", ""); chooser.setCurrentDirectory(new File(sessionSaveLocation)); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); int ret1 = chooser.showOpenDialog(JOptionUtils.centeringComp()); if (!(ret1 == JFileChooser.APPROVE_OPTION)) { return; } File selectedFile = chooser.getSelectedFile(); if (selectedFile == null) { return; } Preferences.userRoot().put("fileSaveLocation", selectedFile.getParent()); try { Knowledge knowledge = SimpleDataLoader.loadKnowledge(selectedFile, DelimiterType.WHITESPACE, "//"); setKnowledge(knowledge); resetTabbedPane(); } catch (Exception e1) { JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), e1.getMessage()); e1.printStackTrace(); } }); saveKnowledge.addActionListener((e) -> { JFileChooser chooser = new JFileChooser(); String sessionSaveLocation = Preferences.userRoot().get("fileSaveLocation", ""); chooser.setCurrentDirectory(new File(sessionSaveLocation)); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); int ret1 = chooser.showSaveDialog(JOptionUtils.centeringComp()); if (!(ret1 == JFileChooser.APPROVE_OPTION)) { return; } File selectedFile = chooser.getSelectedFile(); if (selectedFile == null) { return; } Preferences.userRoot().put("fileSaveLocation", selectedFile.getParent()); try { DataWriter.saveKnowledge(this.knowledge, new FileWriter(selectedFile)); } catch (Exception e1) { JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), e1.getMessage()); } }); return menuBar; } /** *

resetTabbedPane.

*/ public void resetTabbedPane() { this.tabbedPane.removeAll(); this.tabbedPane.add("Tiers", tierDisplay()); this.tabbedPane.add("Other Groups", new OtherGroupsEditor(this.knowledge, this.knowledge.getVariables())); this.tabbedPane.add("Edges", edgeDisplay()); this.tabbedPane.addChangeListener((e) -> { JTabbedPane pane = (JTabbedPane) e.getSource(); if (pane.getSelectedIndex() == 0) { setNumDisplayTiers(FastMath.max(getNumTiers(), this.knowledge.getNumTiers())); } else if (pane.getSelectedIndex() == 2) { resetEdgeDisplay(null); } }); } private Box tierDisplay() { if (getNumTiers() < 0) { int numTiers = getKnowledge().getNumTiers(); int _default = (int) (FastMath.pow(this.vars.size(), 0.5) + 1); numTiers = FastMath.max(numTiers, _default); setNumDisplayTiers(numTiers); } Box b = Box.createVerticalBox(); b.setBorder(new EmptyBorder(5, 5, 5, 5)); Box b1 = Box.createHorizontalBox(); b1.add(new JLabel("Not in tier:")); b1.add(Box.createHorizontalGlue()); b1.add(new JLabel("# Tiers = ")); SpinnerNumberModel spinnerNumberModel = new SpinnerNumberModel( getNumTiers(), 2, 100, 1); spinnerNumberModel.addChangeListener((e) -> { SpinnerNumberModel model = (SpinnerNumberModel) e.getSource(); int numTiers = model.getNumber().intValue(); setNumDisplayTiers(numTiers); setNumTiers(numTiers); model.setValue(numTiers); for (int i = getNumTiers(); i <= getKnowledge() .getMaxTierForbiddenWithin(); i++) { getKnowledge().setTierForbiddenWithin(i, false); } notifyKnowledge(); }); JSpinner spinner = new JSpinner(spinnerNumberModel); spinner.setMaximumSize(spinner.getPreferredSize()); b1.add(spinner); b.add(b1); this.tiersPanel = new JPanel(); this.tiersPanel.setLayout(new BorderLayout()); this.tiersPanel.add(getTierBoxes(getNumTiers()), BorderLayout.CENTER); b.add(this.tiersPanel); Box c = Box.createHorizontalBox(); c.add(new JLabel("Use shift key to select multiple items.")); c.add(Box.createGlue()); b.add(c); return b; } private void setNumDisplayTiers(int numTiers) { if (numTiers < 2) { int knowledgeTiers = getKnowledge().getNumTiers(); int defaultTiers = (int) (FastMath.pow(getVarNames().size(), 0.5) + 1); numTiers = FastMath.max(knowledgeTiers, defaultTiers); } setNumTiers(numTiers); for (int i = numTiers; i < getKnowledge().getNumTiers(); i++) { List vars = getKnowledge().getTier(i); for (String var : vars) { getKnowledge().removeFromTiers(var); } } this.tiersPanel.removeAll(); this.tiersPanel.add(getTierBoxes(getNumTiers()), BorderLayout.CENTER); this.tiersPanel.revalidate(); this.tiersPanel.repaint(); } /** * If the knowledge box sees interventional variables it automatically places those variables in the first tier and * the rest of domain variables in second tier - Zhou */ private void checkInterventionalVariables() { this.vars.forEach(e -> { if ((e.getNodeVariableType() == NodeVariableType.INTERVENTION_STATUS) || (e.getNodeVariableType() == NodeVariableType.INTERVENTION_VALUE)) { this.firstTierVars.add(e.getName()); } else { if (e.getAttribute("fullyDeterminisedDomainVar") != null) { // Also put domain variables that have the "fullyDeterminisedDomainVar" set as true into the first tier if ((boolean) e.getAttribute("fullyDeterminisedDomainVar")) { this.firstTierVars.add(e.getName()); } } else { this.secondTierVars.add(e.getName()); } } }); } private Box getTierBoxes(int numTiers) { // Handling interventional variables checkInterventionalVariables(); // Only for dataset with interventional variables and the first time // we open the knowledge box - Zhou if (getKnowledge().isEmpty() && !this.firstTierVars.isEmpty()) { // Display interventional variables in first tier and the rest in second tier getKnowledge().setTier(0, this.firstTierVars); getKnowledge().setTier(1, this.secondTierVars); } for (Node var : this.vars) { getKnowledge().addVariable(var.getName()); } // Overall container Box container = Box.createVerticalBox(); // Vars not in tier. Reinitialize in case the variables in knowledge have changed. initComponents(); List varsNotInTiers = getKnowledge().getVariablesNotInTiers(); JList varsNotInTiersList = new DragDropList(varsNotInTiers, -1); varsNotInTiersList.setBorder(null); Box varsNotInTiersBox = Box.createHorizontalBox(); JScrollPane jScrollPane1 = new JScrollPane(varsNotInTiersList); jScrollPane1.setPreferredSize(new Dimension(640, 50)); varsNotInTiersBox.add(jScrollPane1); Box tiersBox = Box.createVerticalBox(); // Use this list so we can set the first tier forbidden within tier with interventional variables handling - Zhou List forbiddenCheckboxes = new LinkedList<>(); for (int tier = 0; tier < numTiers; tier++) { Box textRow = Box.createHorizontalBox(); textRow.add(new JLabel("Tier " + (tier))); int _tier = tier; textRow.add(Box.createHorizontalGlue()); JButton regexAdd = new JButton("Find"); JCheckBox forbiddenCheckbox = new JCheckBox("Forbid Within Tier", getKnowledge().isTierForbiddenWithin(_tier)); JCheckBox causesOnlyNextTierCheckbox = new JCheckBox("Can Cause Only Next Tier", getKnowledge().isOnlyCanCauseNextTier(_tier)); JComponent upReference = this; forbiddenCheckbox.addActionListener((e) -> { JCheckBox checkbox = (JCheckBox) e.getSource(); try { getKnowledge().setTierForbiddenWithin(_tier, checkbox.isSelected()); } catch (Exception e1) { checkbox.setSelected(false); JOptionPane.showMessageDialog(upReference, e1.getMessage()); } notifyKnowledge(); }); forbiddenCheckboxes.add(forbiddenCheckbox); textRow.add(regexAdd); regexAdd.addActionListener((e) -> { String regex = JOptionPane.showInputDialog("Search Cpdag"); try { getKnowledge().removeFromTiers(regex); getKnowledge().addToTier(_tier, regex); } catch (IllegalArgumentException iae) { JOptionPane.showMessageDialog(upReference, iae.getMessage()); } notifyKnowledge(); this.tiersPanel.removeAll(); this.tiersPanel.add(getTierBoxes(getNumTiers()), BorderLayout.CENTER); this.tiersPanel.revalidate(); this.tiersPanel.repaint(); }); textRow.add(forbiddenCheckbox); causesOnlyNextTierCheckbox.addActionListener((e) -> { JCheckBox checkbox = (JCheckBox) e.getSource(); try { getKnowledge().setOnlyCanCauseNextTier(_tier, checkbox.isSelected()); } catch (Exception e1) { checkbox.setSelected(false); JOptionPane.showMessageDialog(upReference, e1.getMessage()); } notifyKnowledge(); }); if (tier + 2 < numTiers) textRow.add(causesOnlyNextTierCheckbox); tiersBox.add(textRow); List tierNames = getKnowledge().getTier(tier); JList tierList = new DragDropList(tierNames, tier); Box tierBox = Box.createHorizontalBox(); JScrollPane jScrollPane = new JScrollPane(tierList); jScrollPane.setPreferredSize(new Dimension(600, 50)); tierBox.add(jScrollPane); tiersBox.add(tierBox); } // Add all tiers to a scroll pane JScrollPane tiersScrollPane = new JScrollPane(tiersBox); tiersScrollPane.setPreferredSize(new Dimension(640, 400)); // Also check "Forbin Within Tier" for the first tier variables if (!this.firstTierVars.isEmpty()) { forbiddenCheckboxes.get(0).setSelected(true); getKnowledge().setTierForbiddenWithin(0, true); } // Finally add to container container.add(varsNotInTiersBox); container.add(Box.createVerticalStrut(5)); container.add(tiersScrollPane); return container; } private JPanel edgeDisplay() { KnowledgeGraph graph = new KnowledgeGraph(getKnowledge()); graph.addPropertyChangeListener((evt) -> { if ("modelChanged".equals(evt.getPropertyName())) { notifyKnowledge(); } }); this.edgeWorkbench = new KnowledgeWorkbench(graph); resetEdgeDisplay(null); JCheckBox showForbiddenByTiersCheckbox = new JCheckBox("Show Forbidden By Tiers", this.showForbiddenByTiers); JCheckBox showForbiddenGroupsCheckBox = new JCheckBox("Show Forbidden by Groups", this.showForbiddenByGroups); JCheckBox showForbiddenExplicitlyCheckbox = new JCheckBox("Show Forbidden Explicitly", this.showForbiddenExplicitly); JCheckBox showRequiredGroupsCheckBox = new JCheckBox("Show Required by Groups", this.showRequiredByGroups); JCheckBox showRequiredExplicitlyCheckbox = new JCheckBox("Show Required Explicitly", this.showRequired); showRequiredGroupsCheckBox.addActionListener((e) -> { JCheckBox box = (JCheckBox) e.getSource(); this.showRequiredByGroups = box.isSelected(); resetEdgeDisplay(showRequiredGroupsCheckBox); }); showForbiddenGroupsCheckBox.addActionListener((e) -> { JCheckBox box = (JCheckBox) e.getSource(); this.showForbiddenByGroups = box.isSelected(); resetEdgeDisplay(showForbiddenGroupsCheckBox); }); showForbiddenByTiersCheckbox.addActionListener((e) -> { JCheckBox checkBox = (JCheckBox) e.getSource(); setShowForbiddenByTiers(checkBox.isSelected()); resetEdgeDisplay(showForbiddenByTiersCheckbox); }); showForbiddenExplicitlyCheckbox.addActionListener((e) -> { JCheckBox checkBox = (JCheckBox) e.getSource(); setShowForbiddenExplicitly(checkBox.isSelected()); resetEdgeDisplay(showForbiddenExplicitlyCheckbox); }); showRequiredExplicitlyCheckbox.addActionListener((e) -> { JCheckBox checkBox = (JCheckBox) e.getSource(); setShowRequired(checkBox.isSelected()); resetEdgeDisplay(showRequiredExplicitlyCheckbox); }); JPanel workbenchPanel = new JPanel(); workbenchPanel.setLayout(new BorderLayout()); workbenchPanel.add(new JScrollPane(this.edgeWorkbench), BorderLayout.CENTER); workbenchPanel.setBorder(new TitledBorder("Forbidden and Required Edges")); JPanel display = new JPanel(); display.setPreferredSize(new Dimension(640, 450)); display.setLayout(new BorderLayout()); JPanel b2 = new KnowledgeEditorToolbar(this.edgeWorkbench, this.edgeWorkbench.getSourceGraph()); display.add(b2, BorderLayout.WEST); display.add(workbenchPanel, BorderLayout.CENTER); Box showOptionsBox = Box.createVerticalBox(); Box forbiddenOptionsBox = Box.createHorizontalBox(); forbiddenOptionsBox.add(showForbiddenByTiersCheckbox); forbiddenOptionsBox.add(showForbiddenGroupsCheckBox); forbiddenOptionsBox.add(showForbiddenExplicitlyCheckbox); forbiddenOptionsBox.add(Box.createHorizontalGlue()); Box requiredOptionsBox = Box.createHorizontalBox(); requiredOptionsBox.add(showRequiredGroupsCheckBox); requiredOptionsBox.add(showRequiredExplicitlyCheckbox); requiredOptionsBox.add(Box.createHorizontalGlue()); showOptionsBox.add(forbiddenOptionsBox); showOptionsBox.add(requiredOptionsBox); display.add(showOptionsBox, BorderLayout.SOUTH); return display; } private void resetEdgeDisplay(JCheckBox checkBox) { Knowledge knowledge = getKnowledge(); KnowledgeGraph graph = new KnowledgeGraph(getKnowledge()); getVarNames().forEach(e -> { knowledge.addVariable(e); graph.addNode(new KnowledgeModelNode(e)); }); if (this.showRequiredByGroups) { List list = knowledge.getListOfRequiredEdges(); if (list.size() > KnowledgeBoxEditor.EDGE_LIMIT) { this.showRequiredByGroups = false; if (checkBox != null) { checkBox.setSelected(false); } String errMsg = String.format("The number of edges to show exceeds the limit %d.", KnowledgeBoxEditor.EDGE_LIMIT); JOptionPane.showMessageDialog(this, errMsg, "Unable To Display Edges", JOptionPane.ERROR_MESSAGE); } else { list.forEach(e -> { String from = e.getFrom(); String to = e.getTo(); if (knowledge.isRequiredByGroups(from, to)) { KnowledgeModelNode fromNode = (KnowledgeModelNode) graph .getNode(from); KnowledgeModelNode toNode = (KnowledgeModelNode) graph .getNode(to); graph.addEdge(new KnowledgeModelEdge(fromNode, toNode, KnowledgeModelEdge.REQUIRED_BY_GROUPS)); } }); } } if (this.showForbiddenByGroups) { List list = knowledge.getListOfForbiddenEdges(); if (list.size() > KnowledgeBoxEditor.EDGE_LIMIT) { this.showForbiddenByGroups = false; if (checkBox != null) { checkBox.setSelected(false); } String errMsg = String.format("The number of edges to show exceeds the limit %d.", KnowledgeBoxEditor.EDGE_LIMIT); JOptionPane.showMessageDialog(this, errMsg, "Unable To Display Edges", JOptionPane.ERROR_MESSAGE); } else { list.forEach(e -> { String from = e.getFrom(); String to = e.getTo(); if (knowledge.isForbiddenByGroups(from, to)) { KnowledgeModelNode fromNode = (KnowledgeModelNode) graph .getNode(from); KnowledgeModelNode toNode = (KnowledgeModelNode) graph .getNode(to); graph.addEdge(new KnowledgeModelEdge(fromNode, toNode, KnowledgeModelEdge.FORBIDDEN_BY_GROUPS)); } }); } } if (this.showRequired) { List list = knowledge.getListOfExplicitlyRequiredEdges(); if (list.size() > KnowledgeBoxEditor.EDGE_LIMIT) { this.showRequired = false; if (checkBox != null) { checkBox.setSelected(false); } String errMsg = String.format("The number of edges to show exceeds the limit %d.", KnowledgeBoxEditor.EDGE_LIMIT); JOptionPane.showMessageDialog(this, errMsg, "Unable To Display Edges", JOptionPane.ERROR_MESSAGE); } else { list.forEach(e -> { String from = e.getFrom(); String to = e.getTo(); KnowledgeModelNode fromNode = (KnowledgeModelNode) graph .getNode(from); KnowledgeModelNode toNode = (KnowledgeModelNode) graph .getNode(to); if (!(fromNode == null || toNode == null)) { graph.addEdge(new KnowledgeModelEdge(fromNode, toNode, KnowledgeModelEdge.REQUIRED)); } }); } } if (this.showForbiddenByTiers) { List list = knowledge.getListOfForbiddenEdges(); if (list.size() > KnowledgeBoxEditor.EDGE_LIMIT) { this.showForbiddenByTiers = false; if (checkBox != null) { checkBox.setSelected(false); } String errMsg = String.format("The number of edges to show exceeds the limit %d.", KnowledgeBoxEditor.EDGE_LIMIT); JOptionPane.showMessageDialog(this, errMsg, "Unable To Display Edges", JOptionPane.ERROR_MESSAGE); } else { list.forEach(e -> { String from = e.getFrom(); String to = e.getTo(); if (knowledge.isForbiddenByTiers(from, to)) { KnowledgeModelNode fromNode = (KnowledgeModelNode) graph .getNode(from); KnowledgeModelNode toNode = (KnowledgeModelNode) graph .getNode(to); if (fromNode == null) { graph.addNode(new KnowledgeModelNode(from)); fromNode = (KnowledgeModelNode) graph.getNode(from); } if (toNode == null) { graph.addNode(new KnowledgeModelNode(to)); toNode = (KnowledgeModelNode) graph.getNode(to); } KnowledgeModelEdge knowledgeModelEdge = new KnowledgeModelEdge( fromNode, toNode, KnowledgeModelEdge.FORBIDDEN_BY_TIERS); graph.addEdge(knowledgeModelEdge); } }); } } if (this.showForbiddenExplicitly) { List list = knowledge.getListOfExplicitlyForbiddenEdges(); if (list.size() > KnowledgeBoxEditor.EDGE_LIMIT) { this.showForbiddenExplicitly = false; if (checkBox != null) { checkBox.setSelected(false); } String errMsg = String.format("The number of edges to show exceeds the limit %d.", KnowledgeBoxEditor.EDGE_LIMIT); JOptionPane.showMessageDialog(this, errMsg, "Unable To Display Edges", JOptionPane.ERROR_MESSAGE); } else { list.forEach(e -> { String from = e.getFrom(); String to = e.getTo(); KnowledgeModelNode fromNode = (KnowledgeModelNode) graph .getNode(from); KnowledgeModelNode toNode = (KnowledgeModelNode) graph .getNode(to); KnowledgeModelEdge edge = new KnowledgeModelEdge(fromNode, toNode, KnowledgeModelEdge.FORBIDDEN_EXPLICITLY); if (!graph.containsEdge(edge)) { graph.addEdge(edge); } }); } } boolean arrangedAll = LayoutUtil.arrangeBySourceGraph(graph, this.edgeWorkbench.getGraph()); if (!arrangedAll) { LayoutUtil.defaultLayout(graph); } this.edgeWorkbench.setGraph(graph); notifyKnowledge(); } private void notifyKnowledge() { firePropertyChange("modelChanged", null, null); } private Knowledge getKnowledge() { return this.knowledge; } /** *

Setter for the field knowledge.

* * @param knowledge a {@link edu.cmu.tetrad.data.Knowledge} object */ public void setKnowledge(Knowledge knowledge) { if (knowledge == null) { throw new NullPointerException(); } this.knowledge = knowledge; this.knowledgeBoxModel.setKnowledge(knowledge); } private List getVarNames() { return this.knowledge.getVariables(); } private void setShowForbiddenExplicitly(boolean showForbiddenExplicitly) { this.showForbiddenExplicitly = showForbiddenExplicitly; } private void setShowRequired(boolean showRequired) { this.showRequired = showRequired; } private void setShowForbiddenByTiers(boolean showForbiddenByTiers) { this.showForbiddenByTiers = showForbiddenByTiers; } private int getNumTiers() { return this.numTiers; } private void setNumTiers(int numTiers) { this.numTiers = numTiers; } private class DragDropList extends JList { private static final long serialVersionUID = 7240458207688841986L; private final List items; private final int tier; public DragDropList(List items, int tier) { this.items = items; this.tier = tier; initComponents(); } private void initComponents() { setLayoutOrientation(JList.HORIZONTAL_WRAP); setVisibleRowCount(0); setDropMode(DropMode.ON_OR_INSERT); setDragEnabled(true); setCellRenderer((JList list, String value, int index, boolean isSelected, boolean cellHasFocus) -> { JLabel label = KnowledgeBoxEditor.this.labelMap.get(value); if (label == null) { label = new JLabel(); } label.setBackground(isSelected ? KnowledgeBoxEditor.this.SELECTED_BG : KnowledgeBoxEditor.this.UNSELECTED_BG); return label; }); setTransferHandler(new TransferHandler() { private static final long serialVersionUID = 3109256773218160485L; @Override public boolean canImport(TransferSupport info) { return info.isDataFlavorSupported(ListTransferable.DATA_FLAVOR); } @Override protected Transferable createTransferable(JComponent c) { JList source = (JList) c; List list = source.getSelectedValuesList(); if (list == null) { getToolkit().beep(); list = Collections.EMPTY_LIST; } return new ListTransferable(list); } @Override public int getSourceActions(JComponent c) { return TransferHandler.COPY_OR_MOVE; } @Override public boolean importData(TransferSupport info) { if (!info.isDrop()) { return false; } JList source = (JList) info.getComponent(); DefaultListModel listModel = (DefaultListModel) source.getModel(); Knowledge knowledge = getKnowledge(); Transferable transferable = info.getTransferable(); try { List list = (List) transferable.getTransferData(ListTransferable.DATA_FLAVOR); list.forEach(name -> { if (DragDropList.this.tier >= 0) { try { knowledge.removeFromTiers(name); knowledge.addToTier(DragDropList.this.tier, name); notifyKnowledge(); listModel.addElement(name); sort(listModel); } catch (IllegalStateException e) { JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), e.getMessage()); } } else { knowledge.removeFromTiers(name); notifyKnowledge(); listModel.addElement(name); sort(listModel); } }); } catch (IOException | UnsupportedFlavorException exception) { exception.printStackTrace(System.err); return false; } return true; } @Override protected void exportDone(JComponent c, Transferable data, int action) { if (action == TransferHandler.MOVE) { JList source = (JList) c; DefaultListModel listModel = (DefaultListModel) source.getModel(); try { List list = (List) data.getTransferData(ListTransferable.DATA_FLAVOR); list.forEach(listModel::removeElement); } catch (IOException | UnsupportedFlavorException ignored) { } } } }); DefaultListModel listModel = new DefaultListModel<>(); this.items.forEach(listModel::addElement); setModel(listModel); } private void sort(DefaultListModel listModel) { Object[] elements = listModel.toArray(); String[] values = new String[elements.length]; for (int i = 0; i < elements.length; i++) { values[i] = (String) elements[i]; } Arrays.sort(values, (o1, o2) -> { String[] tokens1 = o1.split(":"); String[] tokens2 = o2.split(":"); if (tokens1.length == 1) { tokens1 = new String[]{tokens1[0], "0"}; } if (tokens2.length == 1) { tokens2 = new String[]{tokens2[0], "0"}; } int i1 = tokens1[1].compareTo(tokens2[1]); int i0 = tokens1[0].compareTo(tokens2[0]); if (i1 == 0) { return i0; } else { return i1; } }); listModel.clear(); Arrays.stream(values).forEach(listModel::addElement); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy