1 |
/** |
2 |
@defgroup jsoc_getJP2images jsoc_getJP2images get paths of existing jp2000 images |
3 |
@ingroup su_util |
4 |
|
5 |
@brief process a DRMS query for AIA data and return paths wrt JSOC /web/jsoc/htdocs/data/aia/images |
6 |
|
7 |
@par Synopsis: |
8 |
@code |
9 |
jsoc_getJP2images {t=0} {j=0} in=aia lev1 query |
10 |
@endcode |
11 |
|
12 |
This is a special purpose module that takes an aia lev1 query and return the paths |
13 |
to existing jpeg2000 images that match the query. It uses the export module method |
14 |
to enable the "@cadence" style query for aia.lev1 data. |
15 |
|
16 |
The json output (j=1) is 3 objects, "images", "count", and "status". |
17 |
the "images" object is an array of individual image objects each of which |
18 |
contains 3 or 4 strings: "time", "wave", "url", and optionally "HMItag". |
19 |
"time" is of the form yyyymmdd_hhmmss |
20 |
and wave is the AIA wavelength. "url" is a complete url to fetch the image. |
21 |
If the flag "t=1" from an html call, or the flag -t on command line then |
22 |
the HMI time tag for the nearest 15m slot is shown. |
23 |
|
24 |
@par Flags: |
25 |
@c |
26 |
-j create output in json with proper html header, else ascii with html header. |
27 |
-t add timetag for nearest HMI 15m slot. |
28 |
|
29 |
@par GEN_FLAGS: |
30 |
Ubiquitous flags present in every module. |
31 |
@ref jsoc_main |
32 |
|
33 |
@param in The AIA lev1 record-set spec. |
34 |
|
35 |
@par Exit_Status: |
36 |
If json output is requested "count" and "status" keys will be provided. |
37 |
Status is non zero on failures. |
38 |
|
39 |
@par Example: |
40 |
get AIA data on 15m ticks. |
41 |
@code |
42 |
jsoc_getJP2images in='aia.lev1[2013.10.20/1d@15m]' -j |
43 |
@endcode |
44 |
|
45 |
@par Example: |
46 |
Get timetag, wavelength, URL, nearest HMI timetag for some EUV data near 0 UT on one day, via cgi-bin. |
47 |
@code |
48 |
http://jsoc.stanford.edu/cgi-bin/ajax/jsoc_getJP2images?in=aia.lev1_euv_12s[2015.08.27/40s][171,335,211]&j=1&t=1 |
49 |
@endcode |
50 |
Response is: |
51 |
@code |
52 |
{"images":[ |
53 |
{"time":"20150826_235958","wave":"211","url":"http://jsoc.stanford.edu/data/aia/images/2015/08/26/211/2015_08_26__23_59_58_62__SDO_AIA_AIA_211.jp2","HMItag":"20150827_000000"} |
54 |
,{"time":"20150827_000013","wave":"335","url":"http://jsoc.stanford.edu/data/aia/images/2015/08/27/335/2015_08_27__00_00_13_63__SDO_AIA_AIA_335.jp2","HMItag":"20150827_000000"} |
55 |
,{"time":"20150827_000034","wave":"171","url":"http://jsoc.stanford.edu/data/aia/images/2015/08/27/171/2015_08_27__00_00_34_34__SDO_AIA_AIA_171.jp2","HMItag":"20150827_000000"} |
56 |
], "count":3, "status":0} |
57 |
@endcode |
58 |
@bug |
59 |
None known so far. |
60 |
|
61 |
*/ |
62 |
|
63 |
#include "jsoc.h" |
64 |
#include "jsoc_main.h" |
65 |
#include <unistd.h> |
66 |
|
67 |
static char x2c (char *what) |
68 |
{ |
69 |
char digit; |
70 |
digit = (char)(what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); |
71 |
digit *= 16; |
72 |
digit = (char)(digit + (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'))); |
73 |
return (digit); |
74 |
} |
75 |
|
76 |
static void CGI_unescape_url (char *url) |
77 |
{ |
78 |
int x, y; |
79 |
for (x = 0, y = 0; url[y]; ++x, ++y) |
80 |
{ |
81 |
if ((url[x] = url[y]) == '%') |
82 |
{ |
83 |
url[x] = x2c (&url[y+1]); |
84 |
y += 2; |
85 |
} |
86 |
} |
87 |
url[x] = '\0'; |
88 |
} |
89 |
|
90 |
char *module_name = "jsoc_getJP2images"; |
91 |
|
92 |
#define DIE(msg) {printf("%s\n",(json ? "{\"status\":-1}" : ""));\ |
93 |
fflush(stdout);\ |
94 |
fprintf(stderr,"%s, status=%d\n",msg,status);\ |
95 |
return(-1);} |
96 |
|
97 |
ModuleArgs_t module_args[] = |
98 |
{ |
99 |
{ARG_STRING, "times", "NOT SPECIFIED", "AIA times desired."}, |
100 |
{ARG_INT, "wave", "0", "AIA wavelength in Angstroms"}, |
101 |
{ARG_STRING, "cadence", "0", "AIA cadence spec, e.g. '15m' or '60s' style"}, |
102 |
{ARG_STRING, "QUERY_STRING", "NOT SPECIFIED", "Params from web GET"}, |
103 |
{ARG_FLAG, "j", "0", "Generate json formatted output, plain ascii otherwise"}, |
104 |
{ARG_FLAG, "t", "0", "Generate HMI timetag nearest to each aia image found"}, |
105 |
{ARG_END} |
106 |
}; |
107 |
|
108 |
int DoIt(void) |
109 |
{ |
110 |
int status = DRMS_SUCCESS; |
111 |
DRMS_RecordSet_t *inRS; |
112 |
DRMS_Record_t *inRec; |
113 |
char date__obs[MAXSTR]; |
114 |
char wave[MAXSTR]; |
115 |
char HMItag[MAXSTR]; |
116 |
char fname[MAXSTR]; |
117 |
char timetag[MAXSTR]; |
118 |
char path[MAXSTR]; |
119 |
char testpath[MAXSTR]; |
120 |
char showpath[MAXSTR]; |
121 |
int year, month, day, hour, minute, sec, fsec; |
122 |
int irec, nrecs, ngood; |
123 |
int from_web; |
124 |
char *web_query; |
125 |
char *cadence, *p; |
126 |
char *in_filename = NULL; |
127 |
int json, wantHMItime; |
128 |
const char *inQuery; |
129 |
char Query[1024]; |
130 |
int iwave; |
131 |
int step, jp2step; |
132 |
int mul; |
133 |
int rec_step; |
134 |
|
135 |
web_query = strdup (cmdparams_get_str (&cmdparams, "QUERY_STRING", NULL)); |
136 |
from_web = strcmp (web_query, "NOT SPECIFIED") != 0; |
137 |
|
138 |
if (from_web) |
139 |
{ |
140 |
|
141 |
char *getstring, *p; |
142 |
CGI_unescape_url(web_query); |
143 |
getstring = strdup (web_query); |
144 |
for (p=strtok(getstring,"&"); p; p=strtok(NULL, "&")) |
145 |
{ |
146 |
char *key=p, *val=index(p,'='); |
147 |
if (!val) |
148 |
{ |
149 |
json = 1; // assume in case of error |
150 |
DIE("Bad QUERY_STRING"); |
151 |
} |
152 |
*val++ = '\0'; |
153 |
cmdparams_set(&cmdparams, key, val); |
154 |
} |
155 |
free(getstring); |
156 |
} |
157 |
|
158 |
iwave = params_get_int(&cmdparams, "wave"); |
159 |
json = params_get_int(&cmdparams, "j"); |
160 |
wantHMItime = params_get_int(&cmdparams, "t"); |
161 |
inQuery = (char *)params_get_str(&cmdparams, "times"); |
162 |
cadence = (char *)params_get_str(&cmdparams, "cadence"); |
163 |
int n = strtol(cadence, &p, 10); // get digits only |
164 |
if (*p == 's') mul = 1; |
165 |
else if (*p == 'm') mul = 60; |
166 |
else if (*p == 'h') mul = 3600; |
167 |
else if (*p == 'd') mul = 86400; |
168 |
n *= mul; // number of seconds per cadence |
169 |
|
170 |
// cadence of UV is 24s, of VIS is 1 hour, of EUV is 12s |
171 |
// but jp2 images made for every second UV, every 3rd EUV, and every VIS image. |
172 |
// step is the seconds per possible image for desired wavelength |
173 |
step = (iwave == 1600 || iwave == 1700 ? 24: (iwave == 4500 ? 3600 : 12)); |
174 |
// jp2step is number of possible images skipped for jp2000 image cadence |
175 |
jp2step = (iwave == 1600 || iwave == 1700 ? 2: (iwave == 4500 ? 1 : 3)); |
176 |
rec_step = n/(step); // rec_step is number of records to skip for the desired cadence |
177 |
|
178 |
|
179 |
if (json) |
180 |
{ |
181 |
printf("Content-type: application/json\n\n"); |
182 |
} |
183 |
else |
184 |
{ |
185 |
printf("Content-type: text/plain\n\n"); |
186 |
} |
187 |
|
188 |
char *at = index(inQuery, '@'); |
189 |
if (at) |
190 |
DIE("Use cadence param instead of @ syntax"); |
191 |
sprintf(Query,"aia.lev1_nrt2[%s][?WAVELNTH=%d?]", inQuery, iwave); |
192 |
fprintf(stderr,"query=%s\n",Query); |
193 |
inRS = drms_open_records(drms_env, Query, &status); |
194 |
if (status || inRS->n == 0) |
195 |
DIE("No input data found"); |
196 |
|
197 |
nrecs = inRS->n; |
198 |
|
199 |
if (wave == 0) |
200 |
DIE("The wave parameter must be provided"); |
201 |
|
202 |
if (json) |
203 |
{ |
204 |
printf("{\"images\":[\n"); |
205 |
} |
206 |
|
207 |
ngood = 0; |
208 |
irec = 0; |
209 |
|
210 |
int trysteps[] = {0, -1, 1, -2, 2, -3, 3}; |
211 |
int try; |
212 |
int found = 0; |
213 |
while (irec < nrecs) |
214 |
{ |
215 |
for (try=0; try<7; try++) |
216 |
{ |
217 |
int tryrec; |
218 |
tryrec = irec + trysteps[try]; |
219 |
if (tryrec < 0) tryrec = 0; |
220 |
if (tryrec >= nrecs) tryrec = nrecs - 1; |
221 |
inRec = inRS->records[tryrec]; |
222 |
strncpy(date__obs, drms_getkey_string(inRec, "DATE__OBS", NULL), MAXSTR); |
223 |
strncpy(wave, drms_getkey_string(inRec, "WAVELNTH", NULL), MAXSTR); |
224 |
sscanf(date__obs, "%4d-%2d-%2dT%2d:%2d:%2d.%2d", &year,&month,&day,&hour,&minute,&sec,&fsec); |
225 |
sprintf(fname, "%4d_%02d_%02d__%02d_%02d_%02d_%02d__SDO_AIA_AIA_%s.jp2", |
226 |
year,month,day,hour,minute,sec,fsec,wave); |
227 |
sprintf(path, "data/aia/images/%4d/%02d/%02d/%s/%s", year, month, day, wave, fname); |
228 |
sprintf(testpath, "/web/jsoc/htdocs/%s", path); |
229 |
if (access(testpath, R_OK) == 0) |
230 |
{ |
231 |
found = 1; |
232 |
break; |
233 |
} |
234 |
} |
235 |
if (found) |
236 |
{ |
237 |
if (wantHMItime) |
238 |
{ // get nearest HMI 15m time slot. |
239 |
TIME t_rec = drms_getkey_time(inRec, "T_REC", NULL); |
240 |
t_rec = (t_rec + 450.0) / 900.0; |
241 |
int slot = floor(t_rec); |
242 |
t_rec = 900.0 * slot; |
243 |
char HMIt_rec[MAXSTR]; |
244 |
sprint_time(HMIt_rec, t_rec, "TAI", 0); |
245 |
int y,m,d,h,M,s; |
246 |
sscanf(HMIt_rec, "%4d.%02d.%02d_%02d:%02d:%02d",&y,&m,&d,&h,&M,&s); |
247 |
sprintf(HMItag, "%4d%02d%02d_%02d%02d%02d",y,m,d,h,M,s); |
248 |
} |
249 |
sprintf(timetag, "%4d%02d%02d_%02d%02d%02d", year,month,day,hour,minute,sec); |
250 |
sprintf(showpath, "http://jsoc.stanford.edu/%s", path); |
251 |
if (json) |
252 |
{ |
253 |
if (wantHMItime) |
254 |
printf("%s{\"time\":\"%s\",\"wave\":\"%s\",\"url\":\"%s\",\"HMItag\":\"%s\"}\n", |
255 |
(ngood ? "," : " "), timetag, wave, showpath, HMItag); |
256 |
else |
257 |
printf("%s{\"time\":\"%s\",\"wave\":\"%s\",\"url\":\"%s\"}\n", |
258 |
(ngood ? "," : " "), timetag, wave, showpath); |
259 |
} |
260 |
else |
261 |
{ |
262 |
printf("%s\n",testpath); |
263 |
} |
264 |
ngood++; |
265 |
} |
266 |
irec += rec_step; |
267 |
} |
268 |
|
269 |
if (json) |
270 |
{ |
271 |
printf("], \"count\":%d, \"status\":0}\n", ngood); |
272 |
} |
273 |
else |
274 |
{ |
275 |
} |
276 |
drms_close_records(inRS, DRMS_FREE_RECORD); |
277 |
return (DRMS_SUCCESS); |
278 |
} // end of DoIt |
279 |
|