/* * Copyright (c) by Allin Cottrell * * 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 * */ #include "libgretl.h" #include #include "tramo_x12a.h" typedef struct _tramo_options tramo_options; struct _tramo_options { int rsa; /* for standard auto setting, rsa = 3 (guide.pdf) */ int iatip; /* correction for outliers? 0=no, 1=auto */ int aio; /* sorts of outliers recognized (codes 1, 2, or 3; 0 is also acceptable in case only tramo is run) */ float va; /* critical value for outliers (or 0.0 for auto) */ /* widgets for dealing with outliers */ GtkWidget *iatip_button; GtkWidget *aio_transitory_button; GtkWidget *aio_shift_button; GtkWidget *aio_innov_button; GtkWidget *va_button; GtkWidget *va_spinner; GtkWidget *aio_label; GtkWidget *va_label; int lam; /* log transformation? (0=logs, 1=levels, -1=auto) */ int imean; /* mean correction? (0=no, 1=yes) */ int inic; /* controls automatic model identification */ int idif; /* ditto */ int auto_arima; /* 1 = ARIMA spec will be left up to TRAMO; 0 for manual specification */ int d; /* number of non-seasonal differences */ int bd; /* number of seasonal differences */ int p; /* number of non-seasonal AR terms */ int bp; /* number of seasonal AR terms */ int q; /* number of non-seasonal MA terms */ int bq; /* number of seasonal MA terms */ /* widgets for dealing with ARIMA terms */ GtkWidget *d_list; GtkWidget *bd_list; GtkWidget *p_list; GtkWidget *bp_list; GtkWidget *q_list; GtkWidget *bq_list; int mq; /* periodicity (12 = monthly; acceptable values are 1, 2, 3, 4, 5, 6 and 12 */ int noadmiss; /* when model "does not accept an admissible decomposition", use an approximation (1) or not (0) */ int seats; /* 0: no SEATS input file created 1: create SEATS file; estimation re-done in SEATS 2: create SEATS file; estimation not re-done in SEATS */ int out; /* verbosity level: 0 = detailed output file per series 1 = reduced output file per series 2 = very brief summary 3 = no output file */ tx_request *request; /* generic tramo/x-12-arima request struct */ }; #define option_widgets_shown(p) (p->va_spinner != NULL) static void tramo_options_set_defaults (tramo_options *opts, int pd) { opts->rsa = 3; /* standard auto analysis */ opts->iatip = 1; /* detect outliers */ opts->aio = 2; /* both transitory changes and level shifts */ opts->va = 0.0; /* let critical value be decided by tramo */ opts->lam = -1; /* leave log/level decision to tramo */ opts->imean = 1; /* mean correction */ opts->auto_arima = 1; /* leave ARIMA spec to tramo */ opts->inic = 3; opts->idif = 3; opts->d = opts->bd = 1; opts->p = opts->bp = 0; opts->q = opts->bq = 1; opts->mq = pd; opts->noadmiss = 1; /* use approximation if needed */ opts->seats = (pd > 1); /* make SEATS file and re-do estimation? */ opts->out = 0; /* verbose */ } static void tramo_custom_tabs_set_sensitive (GtkWidget *notebook, gboolean s) { gint i; GtkWidget *page; for (i=2; i<5; i++) { page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i); gtk_widget_set_sensitive(page, s); } } static void main_auto_callback (GtkWidget *w, GtkWidget *notebook) { tramo_options *opts = g_object_get_data(G_OBJECT(notebook), "opts"); if (w == NULL || GTK_TOGGLE_BUTTON(w)->active) { tramo_custom_tabs_set_sensitive(notebook, FALSE); opts->rsa = 3; } else { tramo_custom_tabs_set_sensitive(notebook, TRUE); opts->rsa = 0; } } static void va_spinner_set_state (tramo_options *opts) { if (!option_widgets_shown(opts)) return; gtk_widget_set_sensitive(opts->va_spinner, GTK_WIDGET_IS_SENSITIVE(opts->va_label) && !GTK_TOGGLE_BUTTON(opts->va_button)->active); } static void outlier_options_set_sensitive (tramo_options *opts, gboolean s) { if (!option_widgets_shown(opts)) return; gtk_widget_set_sensitive(opts->aio_label, s); gtk_widget_set_sensitive(opts->aio_transitory_button, s); gtk_widget_set_sensitive(opts->aio_shift_button, s); gtk_widget_set_sensitive(opts->aio_innov_button, s && opts->seats == 0); gtk_widget_set_sensitive(opts->va_label, s); gtk_widget_set_sensitive(opts->va_button, s); va_spinner_set_state(opts); } static void flip_iatip (GtkWidget *w, tramo_options *opts) { if (!option_widgets_shown(opts)) return; if (GTK_TOGGLE_BUTTON(w)->active) { outlier_options_set_sensitive(opts, TRUE); opts->iatip = 1; } else { outlier_options_set_sensitive(opts, FALSE); opts->iatip = 0; } } static void flip_auto_va (GtkWidget *w, tramo_options *opts) { if (!option_widgets_shown(opts)) return; if (GTK_TOGGLE_BUTTON(w)->active) { gtk_widget_set_sensitive(opts->va_spinner, FALSE); opts->va = 0.0; } else { gtk_widget_set_sensitive(opts->va_spinner, TRUE); } } static void arima_options_set_sensitive (tramo_options *opts, gboolean s) { gtk_widget_set_sensitive(opts->d_list, s); gtk_widget_set_sensitive(opts->p_list, s); gtk_widget_set_sensitive(opts->q_list, s); if (opts->request->pd > 1) { gtk_widget_set_sensitive(opts->bd_list, s); gtk_widget_set_sensitive(opts->bp_list, s); gtk_widget_set_sensitive(opts->bq_list, s); } } static void flip_auto_arima (GtkWidget *w, tramo_options *opts) { if (!option_widgets_shown(opts)) return; if (GTK_TOGGLE_BUTTON(w)->active) { arima_options_set_sensitive(opts, FALSE); opts->auto_arima = 1; } else { arima_options_set_sensitive(opts, TRUE); opts->auto_arima = 0; } } static void tramo_innov_callback (GtkWidget *w, tramo_options *opts) { if (GTK_TOGGLE_BUTTON(w)->active) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(opts->aio_transitory_button), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(opts->aio_shift_button), TRUE); opts->aio = 0; opts->seats = 0; } } static void tramo_aio_callback (GtkWidget *w, tramo_options *opts) { GtkWidget *other_button, *this_button = w; if (!option_widgets_shown(opts)) return; if (this_button == opts->aio_transitory_button) { other_button = opts->aio_shift_button; } else { other_button = opts->aio_transitory_button; } /* must have at least one box checked */ if (!GTK_TOGGLE_BUTTON(this_button)->active && !GTK_TOGGLE_BUTTON(other_button)->active) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(other_button), TRUE); } if (GTK_TOGGLE_BUTTON(opts->aio_transitory_button)->active) { if (GTK_TOGGLE_BUTTON(opts->aio_shift_button)->active) { /* both transitory and level-shifts */ opts->aio = 2; } else { /* only transitory */ opts->aio = 1; } } else { /* only level-shifts */ opts->aio = 3; } } static void seats_specific_widgets_set_sensitive (tramo_options *opts, gboolean s) { tx_request *request = opts->request; int i; if (opts->aio_innov_button != NULL) { gtk_widget_set_sensitive(opts->aio_innov_button, !s); } for (i=0; iopt[i].check != NULL) { gtk_widget_set_sensitive(request->opt[i].check, s); } } } static void real_set_seats (tramo_options *opts, gint val) { if (val > 0) { seats_specific_widgets_set_sensitive(opts, TRUE); } else { seats_specific_widgets_set_sensitive(opts, FALSE); } opts->seats = val; } static void set_seats (GtkWidget *w, tramo_options *opts) { real_set_seats(opts, 1); } static void set_no_seats (GtkWidget *w, tramo_options *opts) { real_set_seats(opts, 0); } static void set_out (GtkWidget *w, tramo_options *opts) { opts->out = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "out_value")); } static void set_lam (GtkWidget *w, tramo_options *opts) { opts->lam = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "lam_value")); } static void set_imean (GtkWidget *w, tramo_options *opts) { opts->imean = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "imean_value")); } static GtkWidget *make_notebook_page_table (GtkWidget *notebook, const gchar *tab_title, gint rows, gint cols) { GtkWidget *box, *tmp, *tbl; box = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(box), 10); gtk_widget_show(box); tmp = gtk_label_new(tab_title); gtk_widget_show(tmp); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), box, tmp); tbl = gtk_table_new(rows, cols, FALSE); gtk_table_set_row_spacings(GTK_TABLE(tbl), 5); gtk_table_set_col_spacings(GTK_TABLE(tbl), 5); gtk_box_pack_start(GTK_BOX(box), tbl, FALSE, FALSE, 0); gtk_widget_show(tbl); return tbl; } static void tramo_tab_general (GtkWidget *notebook, tx_request *request) { GtkWidget *tbl, *tmp; int tbl_len = 4, row = 0; GSList *group = NULL; const char *radio_labels[] = { N_("Time-series model plus seasonal adjustment"), N_("Time-series model only") }; tbl = make_notebook_page_table(notebook, _("General"), tbl_len, 2); /* checkbox for standard default run */ tmp = gtk_check_button_new_with_label(_("Standard automatic analysis")); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), TRUE); g_object_set_data(G_OBJECT(notebook), "opts", request->opts); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(main_auto_callback), notebook); /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* TRAMO + SEATS option */ tmp = gtk_radio_button_new_with_label(NULL, _(radio_labels[0])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (request->pd > 1)); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tmp)); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; if (request->pd == 1) { gtk_widget_set_sensitive(tmp, FALSE); } else { g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(set_seats), request->opts); } /* TRAMO-only option */ tmp = gtk_radio_button_new_with_label(group, _(radio_labels[1])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (request->pd == 1)); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tmp)); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; if (request->pd == 1) { gtk_widget_set_sensitive(tmp, FALSE); } else { g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(set_no_seats), request->opts); } } static void tramo_tab_output (GtkWidget *notebook, tx_request *request) { GtkWidget *tbl, *tmp; int tbl_len = 10, row = 0; GSList *group = NULL; if (request->pd == 1) tbl_len -= 2; tbl = make_notebook_page_table(notebook, _("Output"), tbl_len, 2); /* label for output window detail */ tmp = gtk_label_new(_("Output window:")); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; gtk_widget_show(tmp); /* full detail option */ tmp = gtk_radio_button_new_with_label(NULL, _("Full details")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), TRUE); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tmp)); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(set_out), request->opts); g_object_set_data(G_OBJECT(tmp), "out_value", GINT_TO_POINTER(0)); /* reduced output option */ tmp = gtk_radio_button_new_with_label(group, _("Reduced output")); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(tmp)); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(set_out), request->opts); g_object_set_data(G_OBJECT(tmp), "out_value", GINT_TO_POINTER(1)); /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* label pertaining to saving series */ tmp = gtk_label_new(_("Save to data set:")); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; gtk_widget_show(tmp); if (request->pd > 1) { tmp = gtk_check_button_new_with_label(_("Seasonally adjusted series")); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; request->opt[D11].check = tmp; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), FALSE); } else { request->opt[D11].check = NULL; } tmp = gtk_check_button_new_with_label(_("Trend/cycle")); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; request->opt[D12].check = tmp; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), FALSE); tmp = gtk_check_button_new_with_label(_("Irregular")); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; request->opt[D13].check = tmp; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), FALSE); tmp = gtk_hseparator_new(); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); row++; if (request->pd > 1) { tmp = gtk_check_button_new_with_label(_("Generate graph")); gtk_widget_show(tmp); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1); request->opt[TRIGRAPH].check = tmp; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), TRUE); } else { request->opt[TRIGRAPH].check = NULL; } } static void tramo_tab_transform (GtkWidget *notebook, tramo_options *opts) { GtkWidget *b1, *b2, *b3, *tbl, *tmp; GSList *log_group = NULL, *mean_group = NULL; int tbl_len = 6, row = 0; tbl = make_notebook_page_table(notebook, _("Transformations"), tbl_len, 2); /* logs versus levels: radio group */ /* logs option */ b1 = gtk_radio_button_new_with_label(NULL, _("Log transformation")); log_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); gtk_widget_show(b1); gtk_table_attach_defaults(GTK_TABLE(tbl), b1, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(b1), "clicked", G_CALLBACK(set_lam), opts); g_object_set_data(G_OBJECT(b1), "lam_value", GINT_TO_POINTER(0)); /* no logs option */ b2 = gtk_radio_button_new_with_label(log_group, _("No log transformation")); log_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b2)); gtk_widget_show(b2); gtk_table_attach_defaults(GTK_TABLE(tbl), b2, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(b2), "clicked", G_CALLBACK(set_lam), opts); g_object_set_data(G_OBJECT(b2), "lam_value", GINT_TO_POINTER(1)); /* automatic log/level option */ b3 = gtk_radio_button_new_with_label(log_group, _("Automatic")); log_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b3)); gtk_widget_show(b3); gtk_table_attach_defaults(GTK_TABLE(tbl), b3, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(b3), "clicked", G_CALLBACK(set_lam), opts); g_object_set_data(G_OBJECT(b3), "lam_value", GINT_TO_POINTER(-1)); switch (opts->lam) { case 0: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1), TRUE); break; case 1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2), TRUE); break; case -1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b3), TRUE); break; default: break; } /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* mean correction: radio group */ b1 = gtk_radio_button_new_with_label(NULL, _("Mean correction")); mean_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b1)); gtk_widget_show(b1); gtk_table_attach_defaults(GTK_TABLE(tbl), b1, 0, 2, row, row + 1); row++; g_signal_connect(G_OBJECT(b1), "clicked", G_CALLBACK(set_imean), opts); g_object_set_data(G_OBJECT(b1), "imean_value", GINT_TO_POINTER(1)); b2 = gtk_radio_button_new_with_label(mean_group, _("No mean correction")); mean_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b2)); gtk_widget_show(b2); gtk_table_attach_defaults(GTK_TABLE(tbl), b2, 0, 2, row, row + 1); g_signal_connect(G_OBJECT(b2), "clicked", G_CALLBACK(set_imean), opts); g_object_set_data(G_OBJECT(b2), "imean_value", GINT_TO_POINTER(0)); switch (opts->imean) { case 1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1), TRUE); break; case 0: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2), TRUE); break; default: break; } } static void get_va_value (GtkSpinButton *sb, tramo_options *opts) { opts->va = (float) gtk_spin_button_get_value(sb); } static void tramo_tab_outliers (GtkWidget *notebook, tramo_options *opts) { GtkWidget *tbl, *tmp; GtkObject *adj; int tbl_len = 9, row = 0; tbl = make_notebook_page_table(notebook, _("Outliers"), tbl_len, 2); /* Overall choice: outlier correction or no? */ tmp = gtk_check_button_new_with_label(_("Detect and correct for outliers")); opts->iatip_button = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (opts->iatip != 0)); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(flip_iatip), opts); /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* label pertaining to transitory and level-shift buttons */ tmp = gtk_label_new(_("Besides additive outliers, allow for:")); opts->aio_label = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* "transitory" button */ tmp = gtk_check_button_new_with_label(_("transitory changes")); opts->aio_transitory_button = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (opts->aio < 3)); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(tramo_aio_callback), opts); /* level-shift button */ tmp = gtk_check_button_new_with_label(_("shifts of level")); opts->aio_shift_button = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (opts->aio > 1)); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(tramo_aio_callback), opts); /* innovationals button */ tmp = gtk_check_button_new_with_label(_("innovational outliers")); opts->aio_innov_button = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (opts->aio == 0)); gtk_widget_set_sensitive(tmp, opts->seats == 0); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(tramo_innov_callback), opts); /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* label pertaining to critical value */ tmp = gtk_label_new(_("Critical value for outliers:")); opts->va_label = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* check button for auto critical value */ tmp = gtk_check_button_new_with_label(_("Automatic")); opts->va_button = tmp; gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), (opts->va == 0.0)); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(flip_auto_va), opts); /* spinner for manual critical value */ adj = gtk_adjustment_new((opts->va == 0.0)? 3.3 : opts->va, 2.1, 6.0, 0.1, 1.0, 1.0); tmp = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.1, 1); opts->va_spinner = tmp; gtk_table_attach(GTK_TABLE(tbl), tmp, 0, 1, row, row + 1, 0, 0, 0, 0); gtk_widget_show(tmp); gtk_widget_set_sensitive(tmp, (opts->va != 0.0)); g_signal_connect(G_OBJECT(tmp), "value-changed", G_CALLBACK(get_va_value), opts); } static void tramo_arima_callback (GtkWidget *w, gint *var) { GtkWidget *entry = g_object_get_data(G_OBJECT(w), "entry"); *var = atoi(gtk_entry_get_text(GTK_ENTRY(entry))); } static GtkWidget *make_labeled_combo (const gchar *label, GtkWidget *tbl, gint row, GList *list, gint *var) { GtkWidget *w; char numstr[2]; w = gtk_label_new(label); gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT); gtk_table_attach(GTK_TABLE(tbl), w, 0, 1, row, row + 1, 0, 0, 0, 0); gtk_widget_show(w); w = gtk_combo_new(); gtk_combo_set_popdown_strings(GTK_COMBO(w), list); sprintf(numstr, "%d", *var); gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(w)->entry), numstr); gtk_widget_set_size_request(w, 48, -1); gtk_table_attach(GTK_TABLE(tbl), w, 1, 2, row, row + 1, 0, 0, 0, 0); g_object_set_data(G_OBJECT(GTK_COMBO(w)->list), "entry", GTK_COMBO(w)->entry); g_signal_connect(G_OBJECT(GTK_COMBO(w)->list), "selection-changed", G_CALLBACK(tramo_arima_callback), var); return w; } static void tramo_tab_arima (GtkWidget *notebook, tramo_options *opts, int pd) { GtkWidget *tbl, *tmp; int i, tbl_len = 10, row = 0; GList *onelist = NULL, *twolist = NULL, *threelist = NULL; gchar *intvals[] = { "0", "1", "2", "3" }; if (pd > 1) { for (i=0; i<2; i++) { onelist = g_list_append(onelist, intvals[i]); } } for (i=0; i<3; i++) { twolist = g_list_append(twolist, intvals[i]); } for (i=0; i<4; i++) { threelist = g_list_append(threelist, intvals[i]); } if (pd == 1) tbl_len -= 3; tbl = make_notebook_page_table(notebook, _("ARIMA"), tbl_len, 2); gtk_table_set_homogeneous(GTK_TABLE(tbl), FALSE); /* auto versus manual button */ tmp = gtk_check_button_new_with_label(_("Automatic")); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmp), opts->auto_arima); g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(flip_auto_arima), opts); /* difference terms */ tmp = make_labeled_combo(_("Non-seasonal differences:"), tbl, row, twolist, &opts->d); row++; gtk_widget_show(tmp); opts->d_list = tmp; if (pd > 1) { tmp = make_labeled_combo(_("Seasonal differences:"), tbl, row, onelist, &opts->bd); row++; gtk_widget_show(tmp); opts->bd_list = tmp; } else { opts->bd_list = NULL; } /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* AR terms */ tmp = make_labeled_combo(_("Non-seasonal AR terms:"), tbl, row, threelist, &opts->p); row++; gtk_widget_show(tmp); opts->p_list = tmp; if (pd > 1) { tmp = make_labeled_combo(_("Seasonal AR terms:"), tbl, row, onelist, &opts->bp); row++; gtk_widget_show(tmp); opts->bp_list = tmp; } else { opts->bp_list = NULL; } /* horizontal separator */ tmp = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(tbl), tmp, 0, 2, row, row + 1); row++; gtk_widget_show(tmp); /* MA terms */ tmp = make_labeled_combo(_("Non-seasonal MA terms:"), tbl, row, threelist, &opts->q); row++; gtk_widget_show(tmp); opts->q_list = tmp; if (pd > 1) { tmp = make_labeled_combo(_("Seasonal MA terms:"), tbl, row, onelist, &opts->bq); gtk_widget_show(tmp); opts->bq_list = tmp; } else { opts->bq_list = NULL; } arima_options_set_sensitive(opts, (opts->auto_arima == 0)); } static void real_show_tramo_options (tx_request *request, GtkWidget *vbox) { GtkWidget *notebook; tramo_options *opts = (tramo_options *) request->opts; notebook = gtk_notebook_new(); gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); gtk_widget_show(notebook); tramo_tab_general(notebook, request); tramo_tab_output(notebook, request); tramo_tab_outliers(notebook, opts); tramo_tab_transform(notebook, opts); tramo_tab_arima(notebook, opts, request->pd); if (opts->rsa == 3) { main_auto_callback(NULL, notebook); } } static tramo_options *tramo_options_new (int pd) { tramo_options *opts; opts = malloc(sizeof *opts); if (opts == NULL) return NULL; if (pd == 4 || pd == 12) { tramo_options_set_defaults(opts, pd); } else { tramo_options_set_defaults(opts, 0); } opts->iatip_button = NULL; opts->aio_transitory_button = NULL; opts->aio_shift_button = NULL; opts->va_button = NULL; opts->va_spinner = NULL; opts->aio_label = NULL; opts->va_label = NULL; return opts; } int show_tramo_options (tx_request *request, GtkWidget *vbox) { tramo_options *opts; opts = tramo_options_new(request->pd); if (opts == NULL) return 1; /* mutual pointer hook-up */ request->opts = opts; opts->request = request; real_show_tramo_options(request, vbox); return 0; } /* Below: print then free the tramo options structure. Return an indication of whether seats will be run (1) or not (0) */ int print_tramo_options (tx_request *request, FILE *fp) { tramo_options *opts; if (request->opts == NULL) return 0; opts = request->opts; fputs("$INPUT ", fp); if (opts->rsa == 3) { fputs("rsa=3,", fp); goto set_out; } /* note: if values are at their TRAMO defaults, don't bother printing them */ if (opts->lam != -1) { fprintf(fp, "lam=%d,", opts->lam); } if (opts->imean != 1) { fprintf(fp, "imean=%d,", opts->imean); } fprintf(fp, "iatip=%d,", opts->iatip); if (opts->iatip == 1) { if (opts->aio != 2) { fprintf(fp, "aio=%d,", opts->aio); } if (opts->va != 0.0) { fprintf(fp, "va=%.1f,", opts->va); } } if (!opts->auto_arima) { fprintf(fp, "D=%d,BD=%d,", opts->d, opts->bd); fprintf(fp, "P=%d,BP=%d,", opts->p, opts->bp); fprintf(fp, "Q=%d,BQ=%d,", opts->q, opts->bq); } else { fprintf(fp, "inic=%d,", opts->inic); fprintf(fp, "idif=%d,", opts->idif); } if (opts->mq > 0) { fprintf(fp, "mq=%d,", opts->mq); } if (opts->noadmiss != 1) { fprintf(fp, "noadmiss=%d,", opts->noadmiss); } fprintf(fp, "seats=%d,", opts->seats); set_out: if (opts->out != 0) { fprintf(fp, "out=%d,", opts->out); } fputs("$\n", fp); free(opts); request->opts = NULL; return (opts->seats > 0); }