00001 /* 00002 * selstuff.c (to be linked from) ~rick/src/util 00003 * 00004 * library of miscellaneous utility functions for extracting a target data 00005 * set from a series by selecting on parameters, and for extracting 00006 * parameter values from a dataset selection 00007 * 00008 * key_params_from_dspec() 00009 * select_dataset_from_time_interval() 00010 * select_dataset_from_time_range() 00011 * 00012 * Bugs: 00013 * Lots of checking is skipped 00014 * select_dataset_from_time_interval() should just call 00015 * select_dataset_from_time_range(), or vice-versa 00016 * The record selection based on Carrington rotation and longitude gives 00017 * incomplete or screwy results sometimes, especially with HMI data 00018 * Unconditionally uses geocentric ephemeris for Carrington times 00019 * 00020 * Revision history is at end of file 00021 */ 00022 00023 #include "earth_ephem.c" 00024 00025 static int key_params_from_dspec (const char *dspec) { 00026 /* 00027 * Establish whether target times are determined from dataset specifier 00028 * assume that if a bracket is found in the dataset specifier it is a 00029 * set of well-specified records containing a properly ordered input dataset; 00030 * otherwise, a dataseries to be queried 00031 */ 00032 int n, nt = strlen (dspec); 00033 00034 for (n = 0; n < nt; n++) if (dspec[n] == '[') return 1; 00035 return 0; 00036 } 00037 00038 DRMS_RecordSet_t *select_dataset_from_time_range (const char *series, 00039 char *tstrt_str, char *tstop_str) { 00040 /* 00041 * Select a dataset from a series based on specification of target times 00042 * for start and stop 00043 * The target times may be specified as either date_time strings or as CR:CL 00044 */ 00045 DRMS_RecordSet_t *ds = NULL; 00046 TIME tstrt, tstop; 00047 double strt_cl, stop_cl; 00048 int strt_cr, stop_cr; 00049 int status; 00050 char rec_query[DRMS_MAXQUERYLEN]; 00051 /* get required series info from first record in series */ 00052 /* platform, cadence, phase */ 00053 /* not currently implemented */ 00054 /* 00055 snprintf (rec_query, DRMS_MAXQUERYLEN, "%s[#^]", series); 00056 if (!(ds = drms_open_records (drms_env, rec_query, &status))) { 00057 fprintf (stderr, "Error: unable to open input data set %s\n", rec_query); 00058 fprintf (stderr, " status = %d\n", status); 00059 } 00060 rec = ds->records[0]; 00061 drms_close_records (ds, DRMS_FREE_RECORD); 00062 */ 00063 if (sscanf (tstrt_str, "%d:%lf", &strt_cr, &strt_cl) == 2) { 00064 /* tstrt specified as CR:CL : need ephemeris info */ 00065 if (sscanf (tstop_str, "%d:%lf", &stop_cr, &stop_cl) != 2) { 00066 fprintf (stderr, "Error: start and stop times must be specified in same format\n"); 00067 fprintf (stderr, " either Date_Time or CR:CL\n"); 00068 return ds; 00069 } 00070 /* 00071 if (strt_cr == stop_cr) { 00072 snprintf (rec_query, DRMS_MAXQUERYLEN, 00073 "%s[?CAR_ROT = %d and CRLN_OBS <= %f and CRLN_OBS >= %f?]", series, 00074 strt_cr, strt_cl, stop_cl); 00075 } else if ((stop_cr - strt_cr) > 1) { 00076 snprintf (rec_query, DRMS_MAXQUERYLEN, 00077 "%s[?(%s > %d and %s < %d) or (%s = %d and %s <= %f) or (%s = %d and %s >= %f?)]", 00078 series, "CAR_ROT", strt_cr, "CAR_ROT", stop_cr, 00079 "CAR_ROT", strt_cr, "CRLN_OBS", strt_cl, 00080 "CAR_ROT", stop_cr, "CRLN_OBS", stop_cl); 00081 } else { 00082 snprintf (rec_query, DRMS_MAXQUERYLEN, 00083 "%s[?(%s = %d and %s <= %f) or (%s = %d and %s >= %f)?]", 00084 series, "CAR_ROT", strt_cr, "CRLN_OBS", strt_cl, 00085 "CAR_ROT", stop_cr, "CRLN_OBS", stop_cl); 00086 } 00087 */ 00088 tstrt = earth_meridian_crossing (strt_cl, strt_cr); 00089 tstop = earth_meridian_crossing (stop_cl, stop_cr); 00090 } else { 00091 tstrt = sscan_time (tstrt_str); 00092 tstop = sscan_time (tstop_str); 00093 if (time_is_invalid (tstrt) || time_is_invalid (tstop)) { 00094 fprintf (stderr, "Error: start and stop times must be specified in same format\n"); 00095 fprintf (stderr, " either Date_Time or CR:CL\n"); 00096 return ds; 00097 } 00098 } 00099 snprintf (rec_query, 256, "%s[?%s >= %13.6e and %s <= %13.6e?]", series, 00100 /* 00101 trec_key, tstrt - t_eps, trec_key, tstop + t_eps); 00102 */ 00103 "T_REC", tstrt, "T_REC", tstop); 00104 if (!(ds = drms_open_records (drms_env, rec_query, &status))) { 00105 fprintf (stderr, "Error: unable to open input data set %s\n", rec_query); 00106 fprintf (stderr, " status = %d\n", status); 00107 } 00108 return ds; 00109 } 00110 00111 DRMS_RecordSet_t *select_dataset_from_time_interval (const char *series, 00112 char *tmid_str, double intrvl) { 00113 /* 00114 * Select a dataset from a series based on specification of a target time 00115 * and interval length 00116 * The target time may be specified as either a date_time string or as CR:CL 00117 * In the former case, the length specification is expected to be in seconds; 00118 * in the latter case it is expected to be in degrees of Carrington rotation 00119 * NO, this doesn't yet work; need to specify intrvl in seconds 00120 */ 00121 DRMS_RecordSet_t *ds = NULL; 00122 DRMS_Record_t *rec; 00123 TIME tmid, tstrt, tstop; 00124 double tmid_cl, tstrt_cl, tstop_cl; 00125 int tmid_cr, tstrt_cr, tstop_cr; 00126 int status; 00127 char rec_query[DRMS_MAXQUERYLEN]; 00128 char time_str[64]; 00129 /* get required series info from first record in series */ 00130 /* platform, cadence, phase */ 00131 /* not currently implemented */ 00132 /* 00133 snprintf (rec_query, DRMS_MAXQUERYLEN, "%s[#^]", series); 00134 if (!(ds = drms_open_records (drms_env, rec_query, &status))) { 00135 fprintf (stderr, "Error: unable to open input data set %s\n", rec_query); 00136 fprintf (stderr, " status = %d\n", status); 00137 } 00138 rec = ds->records[0]; 00139 drms_close_records (ds, DRMS_FREE_RECORD); 00140 */ 00141 if (sscanf (tmid_str, "%d:%lf", &tmid_cr, &tmid_cl) == 2) { 00142 /* tmid specified as CR:CL */ 00143 tmid = earth_meridian_crossing (tmid_cl, tmid_cr); 00144 tstrt_cr = tstop_cr = tmid_cr; 00145 tstrt_cl = tmid_cl + 0.5 * intrvl; 00146 while (tstrt_cl > 360.0) { 00147 tstrt_cl -= 360.0; 00148 tstrt_cr--; 00149 } 00150 tstop_cl = tmid_cl - 0.5 * intrvl; 00151 while (tstop_cl < 0.0) { 00152 tstop_cl += 360.0; 00153 tstop_cr++; 00154 } 00155 tstrt = earth_meridian_crossing (tstrt_cl, tstrt_cr); 00156 tstop = earth_meridian_crossing (tstop_cl, tstop_cr); 00157 /* 00158 if (stop_cl >= 0.0 && strt_cl <= 360.0) { 00159 snprintf (rec_query, DRMS_MAXQUERYLEN, 00160 "%s[?CAR_ROT = %d and CRLN_OBS <= %f and CRLN_OBS >= %f?]", series, 00161 tmid_cr, strt_cl, stop_cl); 00162 } else { 00163 int strt_cr, stop_cr; 00164 strt_cr = stop_cr = tmid_cr; 00165 while (strt_cl > 360.0) { 00166 strt_cl -= 360.0; 00167 strt_cr--; 00168 } 00169 while (stop_cl < 0.0) { 00170 stop_cl += 360.0; 00171 stop_cr++; 00172 } 00173 if ((stop_cr - strt_cr) > 1) { 00174 snprintf (rec_query, DRMS_MAXQUERYLEN, 00175 "%s[?(%s > %d and %s < %d) or (%s = %d and %s <= %f) or (%s = %d and %s >= %f?)]", 00176 series, "CAR_ROT", strt_cr, "CAR_ROT", stop_cr, 00177 "CAR_ROT", strt_cr, "CRLN_OBS", strt_cl, 00178 "CAR_ROT", stop_cr, "CRLN_OBS", stop_cl); 00179 } else { 00180 snprintf (rec_query, DRMS_MAXQUERYLEN, 00181 "%s[?(%s = %d and %s <= %f) or (%s = %d and %s >= %f)?]", 00182 series, "CAR_ROT", strt_cr, "CRLN_OBS", strt_cl, 00183 "CAR_ROT", stop_cr, "CRLN_OBS", stop_cl); 00184 } 00185 } 00186 */ 00187 } else { 00188 /* tmid specified as normal date-time string */ 00189 tmid = sscan_time (tmid_str); 00190 tstrt = tmid - 0.5 * intrvl; 00191 tstop = tmid + 0.5 * intrvl; 00192 } 00193 snprintf (rec_query, 256, "%s[?%s >= %17.10e and %s <= %17.10e?]", series, 00194 /* 00195 trec_key, tstrt - t_eps, trec_key, tstop + t_eps); 00196 */ 00197 "T_REC", tstrt, "T_REC", tstop); 00198 if (!(ds = drms_open_records (drms_env, rec_query, &status))) { 00199 fprintf (stderr, "Error: unable to open input data set %s\n", rec_query); 00200 fprintf (stderr, " status = %d\n", status); 00201 } 00202 return ds; 00203 } 00204 00205 /* 00206 * Revision History (all mods by Rick Bogart unless otherwise noted) 00207 * 00208 * 10.04.27 created this file from routines already in mtrack and 00209 * rdcover 00210 * 10.05.03 added function select_dataset_from_time_range 00211 * 10.08.19 extended precision of time query in 00212 * select_dataset_from_time_interval 00213 * 00214 */