/** Find the dataModel model. (If it's a list, take the one that's selected.) */
  private DataModel getSelectedDataModel(DataWrapper dataWrapper) {
    DataModelList dataModelList = dataWrapper.getDataModelList();

    if (dataModelList.size() > 1) {
      return dataModelList;
    }

    DataModel dataModel = dataWrapper.getSelectedDataModel();

    if (dataModel instanceof DataSet) {
      DataSet dataSet = (DataSet) dataModel;

      if (dataSet.isDiscrete()) {
        return dataSet;
      } else if (dataSet.isContinuous()) {
        return dataSet;
      } else if (dataSet.isMixed()) {
        return dataSet;
      }

      throw new IllegalArgumentException(
          "<html>"
              + "This data set contains a mixture of discrete and continuous "
              + "<br>columns; there are no algorithm in Tetrad currently to "
              + "<br>search over such data sets."
              + "</html>");
    } else if (dataModel instanceof ICovarianceMatrix) {
      return dataModel;
    } else if (dataModel instanceof TimeSeriesData) {
      return dataModel;
    }

    throw new IllegalArgumentException("Unexpected dataModel source: " + dataModel);
  }
  /**
   * Constructs a wrapper for the given DataWrapper. The DatWrapper must contain a DataSet that is
   * either a DataSet or a DataSet or a DataList containing either a DataSet or a DataSet as its
   * selected model.
   *
   * @param knowledgeBoxModel
   */
  public AbstractAlgorithmRunner(
      DataWrapper dataWrapper, Parameters params, KnowledgeBoxModel knowledgeBoxModel) {
    if (dataWrapper == null) {
      throw new NullPointerException();
    }
    if (params == null) {
      throw new NullPointerException();
    }

    this.params = params;
    this.sourceGraph = dataWrapper.getSourceGraph();

    DataModelList dataSource = dataWrapper.getDataModelList();

    //        if (dataSource instanceof ColtDataSet) {
    //            dataSource = new ColtDataSet((ColtDataSet) dataSource);
    //        }

    this.dataWrapper = dataWrapper;

    // temporary workaround to get the knowledge box to coexist with the dataWrapper's knowledge
    if (knowledgeBoxModel == null) {
      getParams().set("knowledge", dataWrapper.getKnowledge());
    } else {
      getParams().set("knowledge", knowledgeBoxModel.getKnowledge());
    }
    List names = dataSource.getVariableNames();
    transferVarNamesToParams(names);
  }
  /** Performs the action of loading a session from a file. */
  public void actionPerformed(ActionEvent e) {
    DataModel dataModel = getDataEditor().getSelectedDataModel();

    if (dataModel instanceof DataSet) {
      DataSet dataSet = (DataSet) dataModel;

      DataFilter interpolator = new ModeInterpolator();
      DataSet newDataSet = interpolator.filter(dataSet);

      DataModelList list = new DataModelList();
      list.add(newDataSet);
      getDataEditor().reset(list);
      getDataEditor().selectFirstTab();
    } else if (dataModel instanceof ICovarianceMatrix) {
      JOptionPane.showMessageDialog(JOptionUtils.centeringComp(), "Must be a tabular data set.");
    }
  }
  public final DataModel getDataModel() {
    if (dataWrapper != null) {
      DataModelList dataModelList = dataWrapper.getDataModelList();

      if (dataModelList.size() == 1) {
        return dataModelList.get(0);
      } else {
        return dataModelList;
      }
    } else if (dataModel != null) {
      return dataModel;
    } else {

      // Do not throw an exception here!
      return null;
    }
  }
  public CopyAllDatasetsWrapper(DataWrapper wrapper) {
    LogDataUtils.logDataModelList(
        "Parent data in which constant columns have been removed.", getDataModelList());

    DataModelList inList = wrapper.getDataModelList();
    DataModelList outList = new DataModelList();

    for (DataModel model : inList) {
      if (!(model instanceof DataSet)) {
        throw new IllegalArgumentException("Not a data set: " + model.getName());
      }

      this.setDataModel(model);
      outList.add(model);
    }

    setDataModel(outList);
    setSourceGraph(wrapper.getSourceGraph());
  }
  /** @return the splitNames selected by the editor. */
  public static DataModel createSplits(DataSet dataSet, SplitCasesParams params) {
    List<Integer> indices = new ArrayList<Integer>(dataSet.getNumRows());
    for (int i = 0; i < dataSet.getNumRows(); i++) {
      indices.add(i);
    }

    if (params.isDataShuffled()) {
      Collections.shuffle(indices);
    }

    SplitCasesSpec spec = params.getSpec();
    int numSplits = params.getNumSplits();
    int sampleSize = spec.getSampleSize();
    int[] breakpoints = spec.getBreakpoints();
    List<String> splitNames = spec.getSplitNames();

    int[] _breakpoints = new int[breakpoints.length + 2];
    _breakpoints[0] = 0;
    _breakpoints[_breakpoints.length - 1] = sampleSize;
    System.arraycopy(breakpoints, 0, _breakpoints, 1, breakpoints.length);

    DataModelList list = new DataModelList();
    int ncols = dataSet.getNumColumns();
    for (int n = 0; n < numSplits; n++) {
      int _sampleSize = _breakpoints[n + 1] - _breakpoints[n];

      DataSet _data = new ColtDataSet(_sampleSize, dataSet.getVariables());
      _data.setName(splitNames.get(n));

      for (int i = 0; i < _sampleSize; i++) {
        int oldCase = indices.get(i + _breakpoints[n]);

        for (int j = 0; j < ncols; j++) {
          _data.setObject(i, j, dataSet.getObject(oldCase, j));
        }
      }

      list.add(_data);
    }

    return list;
  }
  private void createDiscreteTimeSeriesData() {

    // GIVEN: Continuous data set D, maximum lag m.
    Node[] dataVars = dataSet.getVariables().toArray(new Node[0]);
    int n = dataVars.length;
    int m = getNumLags();

    // LetXi, i = 0,...,n-1, be the variables from the data. Let Xi(t) be
    // the variable Xi at time lag t (before 0), t = 0,...,m.
    Node[][] laggedVars = new Node[m + 1][n];
    Knowledge knowledge = new Knowledge();

    for (int s = 0; s <= m; s++) {
      for (int j = 0; j < n; j++) {
        String name1 = dataVars[j].getName();
        String name2 = name1 + "." + (s + 1);
        laggedVars[s][j] = new DiscreteVariable((DiscreteVariable) dataVars[j]);
        laggedVars[s][j].setName(name2);
        laggedVars[s][j].setCenter(80 * j + 50, 80 * (m - s) + 50);
        knowledge.addToTier(s, laggedVars[s][j].getName());
      }
    }

    // 2. Prepare the data the way you did.
    List<Node> variables = new LinkedList<Node>();

    for (int s = 0; s <= m; s++) {
      for (int i = 0; i < n; i++) {
        int[] rawData = new int[dataSet.getNumRows()];

        for (int j = 0; j < dataSet.getNumRows(); j++) {
          rawData[j] = dataSet.getInt(j, i);
        }

        int size = dataSet.getNumRows();

        int[] laggedRaw = new int[size - m + 1];
        System.arraycopy(rawData, m - s, laggedRaw, 0, size - m + 1);
        variables.add(laggedVars[s][i]);
      }
    }

    DataSet _laggedData = new ColtDataSet(dataSet.getNumRows() - m + 1, variables);

    for (int s = 0; s <= m; s++) {
      for (int i = 0; i < n; i++) {
        int[] rawData = new int[dataSet.getNumRows()];

        for (int j = 0; j < dataSet.getNumRows(); j++) {
          rawData[j] = dataSet.getInt(j, i);
        }

        int size = dataSet.getNumRows();

        int[] laggedRaw = new int[size - m + 1];
        System.arraycopy(rawData, m - s, laggedRaw, 0, size - m + 1);
        int _col = _laggedData.getColumn(laggedVars[s][i]);

        for (int j = 0; j < dataSet.getNumRows(); j++) {
          _laggedData.setInt(j, _col, laggedRaw[j]);
        }
      }
    }

    knowledge.setDefaultToKnowledgeLayout(true);
    _laggedData.setKnowledge(knowledge);
    DataModelList list = new DataModelList();
    list.add(_laggedData);
    getDataEditor().reset(list);
    getDataEditor().selectLastTab();
  }