/*
* Copyright (c) 2010 Pentaho Corporation. All rights reserved.
* This software was developed by Pentaho Corporation and is provided under the terms
* of the GNU Lesser General Public License, Version 2.1. You may not use
* this file except in compliance with the license. If you need a copy of the license,
* please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is Time Series
* Forecasting. The Initial Developer is Pentaho Corporation.
*
* Software distributed under the GNU Lesser Public License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
* the license for the specific language governing your rights and limitations.
*/
/*
* SimpleConfigPanel.java
* Copyright (C) 2010 Pentaho Corporation
*/
package weka.classifiers.timeseries.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import weka.classifiers.timeseries.WekaForecaster;
import weka.classifiers.timeseries.core.TSLagMaker;
import weka.classifiers.timeseries.eval.TSEvaluation;
import weka.core.Attribute;
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Remove;
import weka.gui.AttributeSelectionPanel;
/**
* Class that renders a simple configuration panel for configuring a time series
* forecaster.
*
* @author Mark Hall (mhall{[at]}pentaho{[dot]}com)
* @version $Revision: 50889 $
*/
public class SimpleConfigPanel extends JPanel {
/**
* For serialization
*/
private static final long serialVersionUID = 4339062970124604791L;
/** The training instances to operate on */
protected Instances m_instances;
/** The forecaster to configure */
protected WekaForecaster m_forecaster;
/**
* Holds the header of the training instances after all but numeric attributes
* are removed (for target selection purposes
*/
protected Instances m_targetHeader;
/** Combo box for selecting the time stamp attribute */
protected JComboBox m_timeStampCombo = new JComboBox();
/** Combo box for selecting the periodicity */
protected JComboBox m_periodicityCombo = new JComboBox();
/** Panel for selecting targets to forecast */
protected AttributeSelectionPanel m_targetPanel = new AttributeSelectionPanel();
/** Checkbox for computing confidence intervals */
protected JCheckBox m_computeConfidence = new JCheckBox();
/** Spinner for selecting the number of steps to forecast */
protected JSpinner m_horizonSpinner;
/** Spinner for selecting the confidence interval */
protected JSpinner m_confidenceLevelSpinner;
/** Checkbox for selecting whether to perform evaluation */
protected JCheckBox m_performEvaluation = new JCheckBox();
/** A reference to the advanced config panel */
protected AdvancedConfigPanel m_advancedConfig;
/**
* Text field for entering date time stamp values that should be "skipped" -
* i.e. not considered as a time step
*/
protected JTextField m_skipText = new JTextField(18);
/** A reference to the parent panel */
protected ForecastingPanel m_parentPanel;
/**
* Constructor
*
* @param parent the parent ForecastingPanel
*/
public SimpleConfigPanel(ForecastingPanel parent) {
m_parentPanel = parent;
setLayout(new BorderLayout());
JPanel colSelect = new JPanel();
colSelect.setLayout(new BorderLayout());
colSelect.setBorder(BorderFactory.createTitledBorder("Target Selection"));
JPanel tempHolder1 = new JPanel();
tempHolder1.setLayout(new BorderLayout());
tempHolder1.add(m_targetPanel, BorderLayout.NORTH);
colSelect.add(tempHolder1, BorderLayout.NORTH);
m_targetPanel.setPreferredScrollableViewportSize(new Dimension(250, 80));
SpinnerNumberModel snm = new SpinnerNumberModel();
snm.setValue(1);
snm.setMinimum(1);
m_horizonSpinner = new JSpinner(snm);
Dimension spinD = m_horizonSpinner.getPreferredSize();
spinD = new Dimension((int) (spinD.getWidth() * 1.5),
(int) spinD.getHeight());
m_horizonSpinner.setPreferredSize(spinD);
JPanel spinnerHolder = new JPanel();
spinnerHolder.setBorder(BorderFactory.createEmptyBorder(0, 0, 1, 0));
spinnerHolder.setLayout(new BorderLayout());
spinnerHolder.add(m_horizonSpinner, BorderLayout.EAST);
spinnerHolder.add(new JLabel("Number of time units to forecast ",
JLabel.LEFT), BorderLayout.CENTER);
// tempHolder1.add(spinnerHolder, BorderLayout.CENTER);
// JPanel spacer = new JPanel();
// spacer.setMinimumSize(spinD);
// tempHolder1.add(spacer, BorderLayout.SOUTH);
add(colSelect, BorderLayout.CENTER);
Box comboHolder = new Box(BoxLayout.PAGE_AXIS);
comboHolder.add(spinnerHolder);
JPanel timeHolder = new JPanel();
timeHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
timeHolder.setLayout(new BorderLayout());
// timeHolder.setBorder(BorderFactory.createTitledBorder("Time stamp"));
timeHolder.add(new JLabel("Time stamp ", JLabel.RIGHT), BorderLayout.WEST);
timeHolder.add(m_timeStampCombo, BorderLayout.EAST);
comboHolder.add(timeHolder);
JPanel periodicityHolder = new JPanel();
periodicityHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
periodicityHolder.setLayout(new BorderLayout());
// periodicityHolder.setBorder(BorderFactory.createTitledBorder("Periodicity"));
periodicityHolder.add(new JLabel("Periodicity", JLabel.RIGHT),
BorderLayout.WEST);
periodicityHolder.add(m_periodicityCombo, BorderLayout.EAST);
comboHolder.add(periodicityHolder);
m_periodicityCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
checkSkipEnabledStatus();
checkPeriodicity(null);
}
});
//
JPanel skipPanel = new JPanel();
skipPanel.setLayout(new BorderLayout());
skipPanel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
String skipTipText = "<html>Set date time stamp values that should be 'skipped'<br>"
+ "i.e. times that shouldn't count as a time step increment.<br><br>"
+ "E.g. financial trading does not occur on the weekend, so the <br>"
+ "difference between Friday and the following Monday is actually one<br>"
+ "time step (not three).<br><br>Examples:<br><br>"
+ "\"sat,weekend,aug,2011-01-11@yyyy-MM-dd\"</html>";
JLabel skipLab = new JLabel("Skip list", JLabel.RIGHT);
skipLab.setToolTipText(skipTipText);
skipPanel.add(skipLab, BorderLayout.WEST);
skipPanel.add(m_skipText, BorderLayout.EAST);
m_skipText.setToolTipText(skipTipText);
comboHolder.add(skipPanel);
m_computeConfidence.setHorizontalTextPosition(SwingConstants.LEFT);
JPanel confHolder = new JPanel();
confHolder.setLayout(new BorderLayout());
confHolder.add(new JLabel("Confidence intervals", JLabel.RIGHT),
BorderLayout.WEST);
confHolder.add(m_computeConfidence, BorderLayout.EAST);
comboHolder.add(confHolder);
JPanel confLevHolder = new JPanel();
confLevHolder.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
confLevHolder.setLayout(new BorderLayout());
final JLabel levelLab = new JLabel("Level (%) ", JLabel.RIGHT);
levelLab.setEnabled(false);
snm = new SpinnerNumberModel();
snm.setValue(95);
snm.setMinimum(1);
snm.setMaximum(99);
m_confidenceLevelSpinner = new JSpinner(snm);
m_confidenceLevelSpinner.setEnabled(false);
confLevHolder.add(m_confidenceLevelSpinner, BorderLayout.EAST);
confLevHolder.add(levelLab, BorderLayout.CENTER);
comboHolder.add(confLevHolder);
m_computeConfidence.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean enable = m_computeConfidence.isSelected();
levelLab.setEnabled(enable);
m_confidenceLevelSpinner.setEnabled(enable);
}
});
JPanel evalHolder = new JPanel();
evalHolder.setLayout(new BorderLayout());
evalHolder.add(new JLabel("Perform evaluation", JLabel.RIGHT),
BorderLayout.WEST);
m_performEvaluation.setHorizontalAlignment(SwingConstants.LEFT);
evalHolder.add(m_performEvaluation, BorderLayout.EAST);
comboHolder.add(evalHolder);
m_performEvaluation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
m_advancedConfig.m_trainingCheckBox.setSelected(m_performEvaluation
.isSelected());
// don't enable test set evaluation, only disable
if (!m_performEvaluation.isSelected()) {
m_advancedConfig.m_holdoutCheckBox.setSelected(false);
}
}
});
// comboHolder.add(m_horizon);
JPanel temp = new JPanel();
temp.setLayout(new BorderLayout());
temp.setBorder(BorderFactory.createTitledBorder("Parameters"));
temp.add(comboHolder, BorderLayout.NORTH);
add(temp, BorderLayout.EAST);
m_timeStampCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (m_advancedConfig != null) {
m_advancedConfig.updateDateDerivedPanel();
checkSkipEnabledStatus();
}
}
});
/*
* m_periodicityCombo.addActionListener(new ActionListener() { public void
* actionPerformed(ActionEvent e) { if (m_forecaster != null) {
*
* } } });
*/
// m_targetPanel
/*
* Dimension d = tempHolder1.getPreferredSize(); Dimension d2 =
* spinnerHolder.getPreferredSize(); tempHolder1.setMinimumSize(new
* Dimension(tempHolder1.getPreferredSize().width, d.height + d2.height));
* tempHolder1.setPreferredSize(new
* Dimension(tempHolder1.getPreferredSize().width, d.height + d2.height));
*/
}
private void checkSkipEnabledStatus() {
boolean enable = false;
if (m_instances != null) {
if (m_timeStampCombo.getSelectedItem() != null) {
String timeName = m_timeStampCombo.getSelectedItem().toString();
Attribute timeAtt = m_instances.attribute(timeName);
if (timeAtt != null) {
if (m_periodicityCombo.getSelectedItem() != null) {
String periodicity = m_periodicityCombo.getSelectedItem()
.toString();
enable = (timeAtt.isDate() && !periodicity.equals("<Unknown>") && !periodicity
.equals("<Detect automatically>"));
}
}
}
}
m_skipText.setEnabled(enable);
}
/**
* Get the title for this panel suitable for displaying in a tab.
*
* @return the title for this panel.
*/
public String getTabTitle() {
return "Basic configuration";
}
/**
* Get the tool tip for this panel.
*
* @return the tool tip for this panel.
*/
public String getTabTitleToolTip() {
return "Basic configuration";
}
/**
* Get the value in the horizon spinner (i.e. the number of steps to forecast)
*
* @return the number of steps to forecast.
*/
public int getHorizonValue() {
SpinnerNumberModel snm = (SpinnerNumberModel) m_horizonSpinner.getModel();
return snm.getNumber().intValue();
}
/**
* Set a reference to the advanced configuration panel.
*
* @param adv a reference to the advanced configuration panel.
*/
public void setAdvancedConfig(AdvancedConfigPanel adv) {
m_advancedConfig = adv;
}
/**
* Set the WekaForecaster that is to be configured by this panel.
*
* @param forecaster the WekaForecaster that is to be configured by this
* panel.
*/
public void setForecaster(WekaForecaster forecaster) {
m_forecaster = forecaster;
if (m_instances != null) {
if (!m_forecaster.getTSLagMaker().getAdjustForTrends()) {
m_timeStampCombo.setSelectedItem("<None>");
m_periodicityCombo.setSelectedIndex(0);
} else {
if (m_forecaster.getTSLagMaker().isUsingAnArtificialTimeIndex()) {
m_timeStampCombo.setSelectedItem("<Use an artificial time index>");
} else if (m_forecaster.getTSLagMaker().getTimeStampField() != null
&& m_forecaster.getTSLagMaker().getTimeStampField().length() > 0) {
m_timeStampCombo.setSelectedItem(m_forecaster.getTSLagMaker()
.getTimeStampField());
}
}
int maxLag = m_forecaster.getTSLagMaker().getMaxLag();
if (maxLag == 24) {
m_periodicityCombo.setSelectedItem("Hourly");
}
if (maxLag == 7) {
m_periodicityCombo.setSelectedItem("Daily");
}
if (maxLag == 5) {
m_periodicityCombo.setSelectedItem("Weekly");
}
if (maxLag == 12) {
m_periodicityCombo.setSelectedItem("Monthly");
}
if (maxLag == 4) {
m_periodicityCombo.setSelectedItem("Quarterly");
}
if (maxLag == 5) {
m_periodicityCombo.setSelectedItem("Yearly");
} else {
m_periodicityCombo.setSelectedItem("<Unknown>");
}
}
}
/**
* Returns true if the forecaster is using a time stamp defined in the data
* (rather than no time stamp or an artificially generated one)
*
* @return true if a native time stamp is in use.
*/
public boolean isUsingANativeTimeStamp() {
String selected = m_timeStampCombo.getSelectedItem().toString();
if (!selected.equals("<None>")
&& !selected.equals("<Use an artificial time index>")) {
return true;
}
return false;
}
/**
* Get the selected time stamp field name.
*
* @return the selected time stamp field name.
*/
public String getSelectedTimeStampField() {
return m_timeStampCombo.getSelectedItem().toString();
}
/**
* Get the WekaForecaster that is being configured.
*
* @return the WekaForecaster that is being configured.
*/
public WekaForecaster getForecaster() {
return m_forecaster;
}
/**
* Set the horizon (i.e. the number of steps to forecast).
*
* @param horizon the number of steps to forecast.
*/
public void setHorizon(int horizon) {
m_horizonSpinner.setValue(horizon);
}
/**
* Get the horizon (i.e. the number of steps to forecast)
*
* @return the number of steps to forecast
*/
public int getHorizon() {
SpinnerNumberModel model = (SpinnerNumberModel) m_horizonSpinner.getModel();
return model.getNumber().intValue();
}
/**
* Set the instances that will be used to train and/or test the forecaster.
*
* @param insts the instances for training/testing
* @throws Exception if a problem occurs while configuring based on the
* supplied instances.
*/
public void setInstances(Instances insts) throws Exception {
m_instances = insts;
String removeList = "";
for (int i = 0; i < m_instances.numAttributes(); i++) {
if (m_instances.attribute(i).isDate()
|| m_instances.attribute(i).isNominal()
|| m_instances.attribute(i).isString()
|| m_instances.attribute(i).isRelationValued()) {
removeList += (i + 1) + ",";
}
}
m_targetHeader = new Instances(m_instances, 0);
if (removeList.length() > 0) {
removeList = removeList.substring(0, removeList.lastIndexOf(","));
Remove r = new Remove();
r.setAttributeIndices(removeList);
r.setInputFormat(m_instances);
m_targetHeader = Filter.useFilter(m_instances, r);
m_targetHeader = new Instances(m_targetHeader, 0);
}
m_targetPanel.setInstances(m_targetHeader);
if (m_targetHeader.numAttributes() == 1) {
// auto select the only target
m_targetPanel.setSelectedAttributes(new boolean[] { true });
if (m_parentPanel != null) {
m_parentPanel.enableStartButton(true);
}
}
setupTimeCombo();
setupPeriodicityCombo();
}
/**
* Initialize the time stamp combo box
*/
protected void setupTimeCombo() {
Vector<String> candidateNames = new Vector<String>();
candidateNames.add("<Use an artificial time index>");
candidateNames.add("<None>");
String firstDateName = null;
for (int i = 0; i < m_instances.numAttributes(); i++) {
if (m_instances.attribute(i).isNumeric()) {
candidateNames.add(m_instances.attribute(i).name());
}
if (m_instances.attribute(i).isDate() && firstDateName == null) {
firstDateName = m_instances.attribute(i).name();
}
}
m_timeStampCombo.setModel(new DefaultComboBoxModel(candidateNames));
if (firstDateName != null) {
m_timeStampCombo.setSelectedItem(firstDateName);
}
}
/**
* Initialize the periodicity combo box
*/
protected void setupPeriodicityCombo() {
Vector<String> candidateNames = new Vector<String>();
candidateNames.add("<Unknown>");
candidateNames.add("<Detect automatically>");
candidateNames.add("Hourly");
candidateNames.add("Daily");
candidateNames.add("Weekly");
candidateNames.add("Monthly");
candidateNames.add("Quarterly");
candidateNames.add("Yearly");
m_periodicityCombo.setModel(new DefaultComboBoxModel(candidateNames));
// check to see if a date is set in the time combo and, if so, select
// <detect automatically> by default
String timeSelected = (String) m_timeStampCombo.getSelectedItem();
System.err.println("Selected " + timeSelected);
if (timeSelected != null && timeSelected.length() > 0
&& !timeSelected.equals("<None>")
&& !timeSelected.equals("<Use an artificial time index>")
&& m_instances.attribute(timeSelected).isDate()) {
m_periodicityCombo.setSelectedItem("<Detect automatically>");
}
}
/**
* Make some default settings for lag lengths based on the selected
* periodicity.
*
* @param forecaster the forecaster to configure.
*/
protected void checkPeriodicity(WekaForecaster forecaster) {
if (m_advancedConfig != null) {
String timeStampSelected = m_timeStampCombo.getSelectedItem().toString();
String selectedP = m_periodicityCombo.getSelectedItem().toString();
if (selectedP.equals("<Detect automatically>")
&& !timeStampSelected.equals("<Use an artificial time index>")
&& !timeStampSelected.equals("<None>") && forecaster != null) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.UNKNOWN);
TSLagMaker.PeriodicityHandler detected = TSLagMaker
.determinePeriodicity(m_instances, forecaster.getTSLagMaker()
.getTimeStampField(), forecaster.getTSLagMaker()
.getPeriodicity());
switch (detected.getPeriodicity()) {
case HOURLY:
selectedP = "Hourly";
break;
case DAILY:
selectedP = "Daily";
break;
case WEEKLY:
selectedP = "Weekly";
break;
case MONTHLY:
selectedP = "Monthly";
break;
case QUARTERLY:
selectedP = "Quarterly";
break;
case YEARLY:
selectedP = "Yearly";
break;
}
}
if (forecaster != null) {
if (selectedP.equals("Hourly")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.HOURLY);
} else if (selectedP.equals("Daily")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.DAILY);
} else if (selectedP.equals("Weekly")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.WEEKLY);
} else if (selectedP.equals("Monthly")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.MONTHLY);
} else if (selectedP.equals("Quarterly")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.QUARTERLY);
} else if (selectedP.equals("Yearly")) {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.YEARLY);
} else {
forecaster.getTSLagMaker().setPeriodicity(
TSLagMaker.Periodicity.UNKNOWN);
}
if (m_skipText.isEnabled() && m_skipText.getText() != null
&& m_skipText.getText().length() > 0) {
forecaster.getTSLagMaker()
.setSkipEntries(m_skipText.getText().trim());
} else {
forecaster.getTSLagMaker().setSkipEntries(""); // clear any previously
// set ones
}
}
// only set these defaults if the user is not using custom lag lengths!
if (!m_advancedConfig.isUsingCustomLags()) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMinLag(1);
}
m_advancedConfig.m_minLagSpinner.setValue(1);
if (selectedP.equals("Hourly")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 24));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 24));
} else if (selectedP.equals("Daily")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 7));
// forecaster.getTSLagMaker().setSkipEntries("sat,sun");
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 7));
} else if (selectedP.equals("Weekly")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 52));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 52));
} else if (selectedP.equals("Monthly")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 12));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 12));
} else if (selectedP.equals("Quarterly")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 4));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 4));
} else if (selectedP.equals("Yearly")) {
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 5));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 5));
} else {
// default (<Unknown>)
if (forecaster != null) {
forecaster.getTSLagMaker().setMaxLag(
Math.min(m_instances.numInstances() / 2, 12));
}
m_advancedConfig.m_maxLagSpinner.setValue(Math.min(
m_instances.numInstances() / 2, 12));
}
}
if (!m_advancedConfig.getCustomizeDateDerivedPeriodics()
&& forecaster != null) {
// configure defaults based on the above periodicity
if (selectedP.equals("Hourly")) {
forecaster.getTSLagMaker().setAddAMIndicator(true);
} else if (selectedP.equals("Daily")) {
forecaster.getTSLagMaker().setAddDayOfWeek(true);
forecaster.getTSLagMaker().setAddWeekendIndicator(true);
} else if (selectedP.equals("Weekly")) {
forecaster.getTSLagMaker().setAddMonthOfYear(true);
forecaster.getTSLagMaker().setAddQuarterOfYear(true);
} else if (selectedP.equals("Monthly")) {
forecaster.getTSLagMaker().setAddMonthOfYear(true);
forecaster.getTSLagMaker().setAddQuarterOfYear(true);
}
}
}
}
/**
* Apply the selected settings of this panel to the supplied WekaForecaster.
*
* @param forecaster the WekaForecaster to configure
* @throws Exception if there is a problem configuring.
*/
public void applyToForecaster(WekaForecaster forecaster) throws Exception {
if (forecaster != null) {
TSLagMaker lagMaker = forecaster.getTSLagMaker();
String selected = m_timeStampCombo.getSelectedItem().toString();
if (!selected.equals("<Use an artificial time index>")
&& !selected.equals("<None>")) {
lagMaker.setTimeStampField(selected);
} else {
lagMaker.setTimeStampField("");
}
if (selected.equals("<None>")) {
lagMaker.setAdjustForTrends(false);
} else {
lagMaker.setAdjustForTrends(true);
}
if (m_periodicityCombo.getSelectedItem().toString()
.equals("<Detect automatically>")
&& (selected.equals("<Use an artificial time index>") && !m_advancedConfig
.isUsingCustomLags())) {
/*
* JOptionPane.showConfirmDialog(this,
* "Cannot automatically detect periodicity" +
* " when using an artificial time index.", "Forecasting",
* JOptionPane.OK_OPTION);
*/
throw new Exception(
"Cannot automatically detect periodicity when using "
+ "an artificial time index.");
}
if (m_periodicityCombo.getSelectedItem().toString()
.equals("<Detect automatically>")
&& !selected.equals("<Use an artificial time index>")
&& !selected.equals("<None>")
&& (!m_instances.attribute(selected).isDate() && !m_advancedConfig
.isUsingCustomLags())) {
throw new Exception(
"Cannot automatically detect periodicity when using "
+ "a non-date time stamp (select manually or use custom lags.");
}
// reset any date-derived periodics to false
lagMaker.setAddAMIndicator(false);
lagMaker.setAddDayOfWeek(false);
lagMaker.setAddMonthOfYear(false);
lagMaker.setAddQuarterOfYear(false);
lagMaker.setAddWeekendIndicator(false);
if (!selected.equals("<None>")) {
checkPeriodicity(forecaster);
}
if (m_computeConfidence.isSelected()) {
forecaster.setCalculateConfIntervalsForForecasts(getHorizon());
double confLevel = ((SpinnerNumberModel) m_confidenceLevelSpinner
.getModel()).getNumber().doubleValue();
forecaster.setConfidenceLevel(confLevel / 100.0);
} else {
forecaster.setCalculateConfIntervalsForForecasts(0);
}
int[] selectedTargets = m_targetPanel.getSelectedAttributes();
StringBuffer targetBuf = new StringBuffer();
for (int i = 0; i < selectedTargets.length; i++) {
targetBuf.append(m_targetHeader.attribute(selectedTargets[i]).name())
.append(",");
}
String temp = targetBuf.substring(0, targetBuf.lastIndexOf(","));
if (temp.length() == 0) {
throw new Exception("You must select some fields to forecast!");
}
forecaster.setFieldsToForecast(temp);
}
}
/**
* Apply the selected settings of this panel to the supplied evaluation module
* with respect to the supplied forecaster
*
* @param eval the evaluation module to configure
* @param forecaster the forecaster in use
* @throws Exception if a problem occurs during configuration.
*/
public void applyToEvaluation(TSEvaluation eval, WekaForecaster forecaster)
throws Exception {
int horizon = ((SpinnerNumberModel) m_horizonSpinner.getModel())
.getNumber().intValue();
if (horizon < 1) {
throw new Exception("Must specify a non-zero number of steps to"
+ "forecast into the future");
}
eval.setHorizon(horizon);
eval.setPrimeWindowSize(forecaster.getTSLagMaker().getMaxLag());
}
/**
* Tests the simple config panel from the command line.
*
* @param args must contain the name of an arff file to load.
*/
public static void main(String[] args) {
try {
if (args.length == 0) {
throw new Exception("supply the name of an arff file");
}
Instances i = new Instances(new java.io.BufferedReader(
new java.io.FileReader(args[0])));
SimpleConfigPanel scp = new SimpleConfigPanel(null);
scp.setInstances(i);
final javax.swing.JFrame jf = new javax.swing.JFrame(
"Simple Config Panel");
jf.getContentPane().setLayout(new BorderLayout());
jf.getContentPane().add(scp, BorderLayout.CENTER);
jf.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
jf.dispose();
System.exit(0);
}
});
jf.pack();
jf.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.getMessage());
}
}
}