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

edu.cmu.tetradapp.editor.datamanip.DiscretizationParamsEditor 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.editor.datamanip;

import edu.cmu.tetrad.data.*;
import edu.cmu.tetrad.graph.Node;
import edu.cmu.tetrad.util.Parameters;
import edu.cmu.tetradapp.editor.FinalizingParameterEditor;
import edu.cmu.tetradapp.model.DataWrapper;
import edu.cmu.tetradapp.util.IntSpinner;
import edu.cmu.tetradapp.workbench.LayoutUtils;
import org.apache.commons.math3.util.FastMath;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.List;
import java.util.*;

/**
 * Allows the user to specify how a selected list of columns should be discretized.
 *
 * @author Tyler Gibson
 * @author josephramsey
 * @version $Id: $Id
 */
public class DiscretizationParamsEditor extends JPanel implements FinalizingParameterEditor {

    /**
     * A map from nodes to their editors.
     */
    private final Map nodeEditors = new HashMap<>();
    /**
     * The data set that will be discretized.
     */
    private DataSet sourceDataSet;
    /**
     * A tabbed pane to store the editors in.
     */
    private JTabbedPane editorPane;

    /**
     * The parameters that will be returned by this editor.
     */
    private Parameters parameters;


    /**
     * Constructs a new editor that will allow the user to specify how to discretize each of the columns in the given
     * list. The editor will return the discretized data set.
     */
    public DiscretizationParamsEditor() {

    }

    //============================= Public Methods ===================================//

    private static List getSelected(JList list) {
        List selected = list.getSelectedValuesList();
        List nodes = new LinkedList<>();
        if (selected != null) {
            for (Object o : selected) {
                nodes.add((Node) o);
            }
        }
        return nodes;
    }

    /**
     * Sets up the GUI.
     */
    public void setup() {
        System.out.println("setup");

        List variables = this.sourceDataSet.getVariables();
        List allVariables = new LinkedList<>();
        List discretizeVars = new LinkedList<>();

        for (Node node : variables) {
            discretizeVars.add(node);
            allVariables.add(node);
        }

        for (Node node : allVariables) {
            this.nodeEditors.put(node, createEditor(node));
        }

        finalizeEdit();

        // create discretized ar list.
        /*
      The list of variables to discretize.
     */
        JList discretizeVariableList = new JList(new VariableListModel(allVariables));
        discretizeVariableList.setCellRenderer(new VariableBoxRenderer());
        discretizeVariableList.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        discretizeVariableList.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                JList list = (JList) e.getSource();
                List selected = DiscretizationParamsEditor.getSelected(list);

                finalizeEdit();

                if (selected.size() == 1) {
                    DiscretizationParamsEditor.this.editorPane.removeAll();
                    Node node = selected.get(0);
                    DiscretizationParamsEditor.this.editorPane.add(node.getName(), (JPanel) DiscretizationParamsEditor.this.nodeEditors.get(node));
                } else if (1 < selected.size()) {
                    if (allContinuous(selected)) {
                        DiscretizationParamsEditor.this.editorPane.removeAll();
                        Node first = selected.get(0);
                        Node last = selected.get(selected.size() - 1);
                        String label = first.getName() + " - " + last.getName();
                        DiscretizationParamsEditor.this.editorPane.add(label, new VariableSelectionEditor(selected));
                    } else {
                        DiscretizationParamsEditor.this.editorPane.removeAll();
                    }
                }
            }

            private boolean allContinuous(List selected) {
                for (Node node : selected) {
                    if (!(node instanceof ContinuousVariable)) {
                        return false;
                    }
                }

                return true;
            }
        });
        // Add entries for previously selected variables.
        for (Node node : discretizeVars) {
            if (node instanceof ContinuousVariable continuousVariable) {
                ContinuousDiscretizationEditor editor = new ContinuousDiscretizationEditor(
                        this.sourceDataSet, continuousVariable);
                DiscretizationSpec spec = getSpecs().get(node);
                if (spec == null) continue;
                editor.setDiscretizationSpec(spec);
                this.nodeEditors.put(node, editor);
            } else if (node instanceof DiscreteVariable variable) {
                DiscreteDiscretizationEditor editor = new DiscreteDiscretizationEditor(variable);
                DiscretizationSpec spec = getSpecs().get(node);
                if (spec == null) continue;
                editor.setDiscretizationSpec(spec);
                this.nodeEditors.put(node, editor);
            }
        }

        // set up the tabbed pane
        this.editorPane = new JTabbedPane();

        JScrollPane editorScrollPane = new JScrollPane(this.editorPane);
        editorScrollPane.setPreferredSize(new Dimension(400, 350));

        discretizeVariableList.setSelectedIndex(0);

        Box hBox = Box.createHorizontalBox();
        hBox.add(Box.createHorizontalStrut(5));

        // build the continuous variable box.
        Box selectionBox = Box.createVerticalBox();

        selectionBox.add(Box.createVerticalStrut(5));
        selectionBox.add(Box.createVerticalGlue());

        // build the discrete variable box
        Box discreteSelectionBox = Box.createVerticalBox();
        JLabel discreteLabel = new JLabel("Variables:");

        JScrollPane discreteListPane = new JScrollPane(discretizeVariableList);
        int width2 = FastMath.max(100, discreteLabel.getPreferredSize().width);
        LayoutUtils.setAllSizes(discreteListPane, new Dimension(width2, 350 - discreteLabel.getPreferredSize().height));

        discreteSelectionBox.add(Box.createVerticalStrut(5));
        discreteSelectionBox.add(LayoutUtils.leftAlignJLabel(discreteLabel));
        discreteSelectionBox.add(discreteListPane);
        discreteSelectionBox.add(Box.createVerticalGlue());

        hBox.add(selectionBox);
        hBox.add(Box.createHorizontalStrut(4));
        hBox.add(discreteSelectionBox);
        hBox.add(Box.createHorizontalStrut(8));

        Box vBox = Box.createVerticalBox();
        vBox.add(Box.createVerticalStrut(5));
        vBox.add(editorScrollPane);

        hBox.add(vBox);
        hBox.add(Box.createHorizontalStrut(5));

        add(hBox, BorderLayout.CENTER);
    }

    /**
     * Adds all the discretization info to the params.
     *
     * @return true iff the edit was finalized.
     */
    public boolean finalizeEdit() {
        // if there was no editors, then nothing can be done so return false.
        if (this.nodeEditors.isEmpty()) {
            return false;
        }
        Map map = new HashMap<>();
        for (Node node : this.nodeEditors.keySet()) {
            DiscretizationEditor editor = this.nodeEditors.get(node);
            map.put(node, editor.getDiscretizationSpec());
        }
        this.parameters.set("discretizationSpecs", map);
        return true;
    }

    /**
     * {@inheritDoc}
     * 

* Sets the previous params, must be DiscretizationParams. */ public void setParams(Parameters params) { this.parameters = params; this.parameters.set("discretizationSpecs", new HashMap()); } /** * The parant model should be a DataWrapper. * * @param parentModels an array of {@link java.lang.Object} objects */ public void setParentModels(Object[] parentModels) { if (parentModels == null || parentModels.length == 0) { throw new IllegalArgumentException("There must be parent model"); } DataWrapper data = null; for (Object parent : parentModels) { if (parent instanceof DataWrapper) { data = (DataWrapper) parent; } } if (data == null) { throw new IllegalArgumentException("Should have have a data wrapper as a parent"); } DataModel model = data.getSelectedDataModel(); if (!(model instanceof DataSet)) { throw new IllegalArgumentException("The dataset must be a rectangular dataset"); } this.sourceDataSet = (DataSet) model; } //=============================== Private Methods ================================// /** *

mustBeShown.

* * @return true */ public boolean mustBeShown() { return true; } private DiscretizationEditor createEditor(Node node) { if (node instanceof ContinuousVariable) { return new ContinuousDiscretizationEditor(this.sourceDataSet, (ContinuousVariable) node ); } else if (node instanceof DiscreteVariable) { return new DiscreteDiscretizationEditor((DiscreteVariable) node); } throw new IllegalStateException(); } /** * Changes the number of categories on the editors for the given nodes. */ private void changeNumberOfCategories(int numOfCats, List nodes) { for (Node node : nodes) { DiscretizationEditor editor = this.nodeEditors.get(node); if (editor instanceof ContinuousDiscretizationEditor) { ((ContinuousDiscretizationEditor) editor).setNumCategories(numOfCats); } } } /** * Changes the method of the editor. */ private void changeMethod(List nodes, ContinuousDiscretizationEditor.Method method) { for (Node node : nodes) { DiscretizationEditor editor = nodeEditors.get(node); if (editor instanceof ContinuousDiscretizationEditor) { ((ContinuousDiscretizationEditor) editor).setMethod(method); } } } /** * @return the common mehtod if there is one. */ private ContinuousDiscretizationEditor.Method getCommonMethod(List nodes) { ContinuousDiscretizationEditor.Method method = null; for (Node node : nodes) { DiscretizationEditor editor = nodeEditors.get(node); if (editor instanceof ContinuousDiscretizationEditor _editor) { if (method != null && method != _editor.getMethod()) { return null; } method = _editor.getMethod(); } } return method; } /** * @return the default category num to use for the given nodes. If they all have the same number then its returned * otherwise 3 is returned (or something else?) */ private int getDefaultCategoryNum(List nodes) { if (nodes.isEmpty()) { return 3; } DiscretizationEditor editor = nodeEditors.get(nodes.get(0)); if (editor instanceof ContinuousDiscretizationEditor _editor) { int value = _editor.getNumCategories(); for (int i = 1; i < nodes.size(); i++) { // editor = this.nodeEditors.get(nodes.get(i)); if (value != _editor.getNumCategories()) { return 3; } } return value; } return -1; } /** *

getSpecs.

* * @return a {@link java.util.Map} object */ public Map getSpecs() { return (Map) parameters.get("discretizationSpecs"); } //============================= Inner class ===============================// private static class VariableListModel extends AbstractListModel { private final Vector variables; public VariableListModel(List variables) { this.variables = new Vector<>(variables); } public int getSize() { return this.variables.size(); } public Object getElementAt(int index) { return this.variables.get(index); } } private static class VariableBoxRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Node node = (Node) value; if (node == null) { this.setText(""); } else { this.setText(node.getName()); } if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } return this; } } /** * Editor that edits a collection of variables. */ private class VariableSelectionEditor extends JPanel { private final List nodes; public VariableSelectionEditor(List vars) { this.setLayout(new BorderLayout()); nodes = vars; IntSpinner spinner = new IntSpinner(DiscretizationParamsEditor.this.getDefaultCategoryNum(vars), 1, 3); ContinuousDiscretizationEditor.Method method = DiscretizationParamsEditor.this.getCommonMethod(vars); spinner.setMin(2); spinner.setFilter((oldValue, newValue) -> { DiscretizationParamsEditor.this.changeNumberOfCategories(newValue, nodes); return newValue; }); Box vBox = Box.createVerticalBox(); vBox.add(new JLabel("Discretization Method: ")); JRadioButton none = new JRadioButton("Don't Discretize", method == ContinuousDiscretizationEditor.Method.NONE); JRadioButton equalBuckets = new JRadioButton("Evenly Distributed Values", method == ContinuousDiscretizationEditor.Method.EQUAL_SIZE_BUCKETS); JRadioButton equalInterval = new JRadioButton("Evenly Distributed Intervals", method == ContinuousDiscretizationEditor.Method.EVENLY_DIVIDED_INTERNVALS); none.setHorizontalTextPosition(SwingConstants.RIGHT); equalBuckets.setHorizontalTextPosition(SwingConstants.RIGHT); equalInterval.setHorizontalTextPosition(SwingConstants.RIGHT); none.addActionListener(e -> DiscretizationParamsEditor.this.changeMethod(nodes, ContinuousDiscretizationEditor.Method.NONE)); equalBuckets.addActionListener(e -> DiscretizationParamsEditor.this.changeMethod(nodes, ContinuousDiscretizationEditor.Method.EQUAL_SIZE_BUCKETS)); equalInterval.addActionListener(e -> DiscretizationParamsEditor.this.changeMethod(nodes, ContinuousDiscretizationEditor.Method.EVENLY_DIVIDED_INTERNVALS)); ButtonGroup group = new ButtonGroup(); group.add(none); group.add(equalBuckets); group.add(equalInterval); vBox.add(none); vBox.add(equalBuckets); vBox.add(equalInterval); none.setSelected(true); Box buttons = Box.createHorizontalBox(); buttons.add(vBox); buttons.add(Box.createHorizontalGlue()); buttons.setBorder(new EmptyBorder(15, 5, 5, 5)); Box cats = Box.createHorizontalBox(); cats.add(new JLabel(" Change number of categories: ")); cats.add(spinner); cats.add(Box.createHorizontalGlue()); cats.setBorder(new EmptyBorder(5, 5, 5, 5)); Box vBox1 = Box.createVerticalBox(); vBox1.add(buttons); vBox1.add(cats); vBox1.add(Box.createVerticalGlue()); this.add(vBox1, BorderLayout.NORTH); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy