1 #include "gretl_func.h"
2 #include "gretl_string_table.h" /* for csvdata */
3 #include "csvdata.h"
4
5 /* call hansl code from dbnomics.gfn to get a series bundle */
6
get_dbn_series_bundle(const char * datacode,int * err)7 static gretl_bundle *get_dbn_series_bundle (const char *datacode,
8 int *err)
9 {
10 gretl_bundle *b = NULL;
11 fncall *fc;
12
13 fc = get_pkg_function_call("dbnomics_get_series", "dbnomics", NULL);
14 if (fc == NULL) {
15 *err = E_DATA;
16 } else {
17 *err = push_anon_function_arg(fc, GRETL_TYPE_STRING,
18 (void *) datacode);
19 if (!*err) {
20 *err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, NULL,
21 &b, NULL, NULL);
22 }
23 if (b != NULL) {
24 int dberr = gretl_bundle_get_int(b, "error", NULL);
25
26 if (dberr) {
27 const char *msg =
28 gretl_bundle_get_string(b, "errmsg", NULL);
29
30 *err = E_DATA;
31 if (msg != NULL) {
32 gretl_errmsg_set(msg);
33 } else {
34 gretl_errmsg_sprintf(_("%s: no data found"), datacode);
35 }
36 gretl_bundle_destroy(b);
37 b = NULL;
38 }
39 } else if (!*err) {
40 gretl_errmsg_sprintf(_("%s: no data found"), datacode);
41 *err = E_DATA;
42 }
43 }
44
45 return b;
46 }
47
48 struct dbn_sorter {
49 const char *s;
50 int t;
51 };
52
write_dbn_csv(char ** S,int T,gretl_matrix * v,struct dbn_sorter * ds,FILE * fp)53 static int write_dbn_csv (char **S, int T,
54 gretl_matrix *v,
55 struct dbn_sorter *ds,
56 FILE *fp)
57 {
58 int t, i;
59
60 if (gretl_is_null_matrix(v)) {
61 gretl_errmsg_set("Failed to get data from dbnomics");
62 return E_DATA;
63 }
64
65 gretl_push_c_numeric_locale();
66
67 fputs("obs dbnomics_data\n", fp);
68 for (t=0; t<T; t++) {
69 i = (ds != NULL)? ds[t].t : t;
70 if (i >= v->rows || na(v->val[i])) {
71 fprintf(fp, "%s NA\n", S[i]);
72 } else {
73 fprintf(fp, "%s %.12g\n", S[i], v->val[i]);
74 }
75 }
76
77 gretl_pop_c_numeric_locale();
78
79 return 0;
80 }
81
dbtcomp(const void * a,const void * b)82 static int dbtcomp (const void *a, const void *b)
83 {
84 const struct dbn_sorter *ds1 = a, *ds2 = b;
85
86 return strcmp(ds1->s, ds2->s);
87 }
88
89 /* remedial code for the case where the "periods" in
90 JSON from dbnomics are not actually in temporal
91 order
92 */
93
maybe_reorder_dbn_data(char ** S,int T,gretl_matrix * v,FILE * fp)94 static int maybe_reorder_dbn_data (char **S, int T,
95 gretl_matrix *v,
96 FILE *fp)
97 {
98 struct dbn_sorter *ds;
99 int t, err = 0;
100
101 ds = malloc(T * sizeof *ds);
102 if (ds == NULL) {
103 return E_ALLOC;
104 }
105
106 for (t=0; t<T; t++) {
107 ds[t].s = S[t];
108 ds[t].t = t;
109 }
110
111 qsort(ds, T, sizeof *ds, dbtcomp);
112 err = write_dbn_csv(S, T, v, ds, fp);
113 free(ds);
114
115 return err;
116 }
117
118 /* write the info from @P (periods) and @v (values) to
119 CSV, then grab it back using the gretl CSV reader
120 to populate @dbset
121 */
122
dbn_dset_from_csv(DATASET * dbset,gretl_array * P,gretl_matrix * v)123 static int dbn_dset_from_csv (DATASET *dbset,
124 gretl_array *P,
125 gretl_matrix *v)
126 {
127 PRN *prn = NULL;
128 gchar *fname;
129 FILE *fp;
130 int T, err = 0;
131
132 #if DB_DEBUG
133 prn = gretl_print_new(GRETL_PRINT_STDERR, NULL);
134 #endif
135
136 fname = g_strdup_printf("%sdbnomics_tmp.txt", gretl_dotdir());
137 fp = gretl_fopen(fname, "wb");
138
139 if (fp == NULL) {
140 err = E_FOPEN;
141 } else {
142 char **S = gretl_array_get_strings(P, &T);
143
144 err = write_dbn_csv(S, T, v, NULL, fp);
145 fclose(fp);
146
147 if (!err) {
148 err = import_csv(fname, dbset, OPT_NONE, prn);
149 }
150 if (!err && !dataset_is_time_series(dbset)) {
151 /* try again, after sorting by "period" strings */
152 gretl_remove(fname);
153 fp = gretl_fopen(fname, "wb");
154 if (fp == NULL) {
155 err = E_FOPEN;
156 } else {
157 err = maybe_reorder_dbn_data(S, T, v, fp);
158 fclose(fp);
159 free_Z(dbset);
160 clear_datainfo(dbset, CLEAR_FULL);
161 if (!err) {
162 err = import_csv(fname, dbset, OPT_NONE, prn);
163 }
164 }
165 }
166 gretl_remove(fname);
167 }
168
169 g_free(fname);
170 gretl_print_destroy(prn);
171
172 return err;
173 }
174
175 /* obtain a dbnomics series bundle and process the info
176 it contains into a SERIESINFO struct
177 */
178
179 static int
get_dbnomics_series_info(const char * id,SERIESINFO * sinfo)180 get_dbnomics_series_info (const char *id, SERIESINFO *sinfo)
181 {
182 gretl_bundle *b;
183 DATASET dbset = {0};
184 gretl_array *P;
185 gretl_matrix *v;
186 int T, err = 0;
187
188 /* FIXME check for required form PROV/DSET/SERIES */
189
190 b = get_dbn_series_bundle(id, &err);
191 if (err) {
192 fprintf(stderr, "get_dbn_series_bundle: err=%d\n", err);
193 goto bailout;
194 }
195
196 T = gretl_bundle_get_int(b, "T", &err);
197 P = gretl_bundle_get_array(b, "period", &err);
198 v = gretl_bundle_get_matrix(b, "value", &err);
199 if (!err && (T <= 0 || P == NULL || v == NULL)) {
200 fprintf(stderr, "get_dbnomics_series_info: invalid bundle content\n");
201 err = E_DATA;
202 goto bailout;
203 }
204
205 /* write bundle content as CSV and use CSV reader to
206 construct a one-series dataset */
207 err = dbn_dset_from_csv(&dbset, P, v);
208
209 if (!err) {
210 /* transcribe info to SERIESINFO format */
211 const char *s2 = gretl_bundle_get_string(b, "series_name", NULL);
212 char *rawname = strrchr(id, '/') + 1;
213 gchar *descrip;
214
215 sinfo->t1 = dbset.t1;
216 sinfo->t2 = dbset.t2;
217 sinfo->nobs = dbset.n;
218 sinfo->pd = dbset.pd;
219 strcpy(sinfo->stobs, dbset.stobs);
220 strcpy(sinfo->endobs, dbset.endobs);
221 /* set up name and description */
222 gretl_normalize_varname(sinfo->varname, rawname, 0, 0);
223 descrip = g_strdup_printf("%s: %s", id, s2);
224 series_info_set_description(sinfo, descrip);
225 g_free(descrip);
226 /* steal the data array */
227 sinfo->data = dbset.Z[1];
228 dbset.Z[1] = NULL;
229 }
230
231 free_Z(&dbset);
232 clear_datainfo(&dbset, CLEAR_FULL);
233
234 bailout:
235
236 gretl_bundle_destroy(b);
237
238 return err;
239 }
240
241 /* transfer the data stored on @sinfo into @Z */
242
get_dbnomics_data(const char * fname,SERIESINFO * sinfo,double ** Z)243 static int get_dbnomics_data (const char *fname,
244 SERIESINFO *sinfo,
245 double **Z)
246 {
247 memcpy(Z[1], sinfo->data, sinfo->nobs * sizeof(double));
248 free(sinfo->data);
249 sinfo->data = NULL;
250
251 return 0;
252 }
253