diff --git a/pred_src/pred.c b/pred_src/pred.c index 41f05f3..6b7879d 100644 --- a/pred_src/pred.c +++ b/pred_src/pred.c @@ -43,6 +43,8 @@ int main(int argc, const char *argv[]) { int alarm_time; char* endptr; // used to check for errors on strtod calls + int exit_code = 0; + wind_file_cache_t* file_cache; dictionary* scenario = NULL; @@ -250,8 +252,8 @@ int main(int argc, const char *argv[]) { scenario_launch_time = mktime(&timeval); if(scenario_launch_time <= 0) { - fprintf(stderr, "WARN: Launch time in scenario is invalid, reverting to " - "default timestamp.\n"); + fprintf(stderr, "ERROR: Launch time in scenario is invalid\n"); + exit(1); } else { initial_timestamp = scenario_launch_time; } @@ -281,12 +283,19 @@ int main(int argc, const char *argv[]) { exit(1); } - if (!run_model(file_cache, alt_model, + state = run_model(file_cache, alt_model, initial_lat, initial_lng, initial_alt, initial_timestamp, - rmswinderror)) { + rmswinderror) + if (state == 0) + { fprintf(stderr, "ERROR: error during model run!\n"); exit(1); } + else if (state == 2) + { + fprintf(stderr, "WARN: model run completed by with warnings\n"); + exit_code = 2; + } altitude_model_free(alt_model); } @@ -311,7 +320,7 @@ int main(int argc, const char *argv[]) { // release the file cache resources. wind_file_cache_free(file_cache); - return 0; + return exit_code; } void write_position(float lat, float lng, float alt, int timestamp) { diff --git a/pred_src/run_model.c b/pred_src/run_model.c index 8f945be..6facad1 100644 --- a/pred_src/run_model.c +++ b/pred_src/run_model.c @@ -75,12 +75,12 @@ _advance_one_timestep(wind_file_cache_t* cache, if(!altitude_model_get_altitude(state->alt_model, timestamp - initial_timestamp, &state->alt)) - return 0; + return 0; // alt <= 0; finished. if(!get_wind(cache, state->lat, state->lng, state->alt, timestamp, &wind_v, &wind_u, &wind_var)) { fprintf(stderr, "ERROR: error getting wind data\n"); - return 0; + return -1; } _get_frame(state->lat, state->lng, state->alt, &ddlat, &ddlng); @@ -145,10 +145,16 @@ int run_model(wind_file_cache_t* cache, altitude_model_t* alt_model, long int timestamp = initial_timestamp; int log_counter = 0; // only write position to output files every LOG_DECIMATE timesteps - - while(_advance_one_timestep(cache, TIMESTEP, timestamp, initial_timestamp, - n_states, states, rmswinderror)) + int last_retval = -1; // error + + while(true) { + last_retval = + _advance_one_timestep(cache, TIMESTEP, timestamp, initial_timestamp, + n_states, states, rmswinderror); + if (last_retval != 1) + break; + // Sort the array of models in order of log likelihood. qsort(states, n_states, sizeof(model_state_t), _state_compare_rev); @@ -173,12 +179,16 @@ int run_model(wind_file_cache_t* cache, altitude_model_t* alt_model, free(states); - return 1; + if (last_retval != 0) + return 0; + else + return 1; } int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int timestamp, float* wind_v, float* wind_u, float *wind_var) { - int i; + int i, s; + int state = 1; // 0: error; 1: success; 2: success with warnings float lambda, wu_l, wv_l, wu_h, wv_h; float wuvar_l, wvvar_l, wuvar_h, wvvar_h; wind_file_cache_entry_t* found_entries[] = { NULL, NULL }; @@ -211,10 +221,10 @@ int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int earlier_ts = wind_file_cache_entry_timestamp(found_entries[0]); later_ts = wind_file_cache_entry_timestamp(found_entries[1]); - if(earlier_ts == later_ts) + if(earlier_ts > timestamp || later_ts < timestamp) { - fprintf(stderr, "WARN: Do not have two data files around current time. " - "Expect the results to be wrong!\n"); + fprintf(stderr, "Error: found_entries have bad times.\n"); + return 0; } if(earlier_ts != later_ts) @@ -223,8 +233,22 @@ int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int else lambda = 0.5f; - wind_file_get_wind(found_files[0], lat, lng, alt, &wu_l, &wv_l, &wuvar_l, &wvvar_l); - wind_file_get_wind(found_files[1], lat, lng, alt, &wu_h, &wv_h, &wuvar_h, &wvvar_h); + s = wind_file_get_wind(found_files[0], lat, lng, alt, &wu_l, &wv_l, &wuvar_l, &wvvar_l); + if (s == 0) + { + // hard error + return 0; + } + + if (s == 2) + { + // completed with warnings + state = 2; + } + + s = wind_file_get_wind(found_files[1], lat, lng, alt, &wu_h, &wv_h, &wuvar_h, &wvvar_h); + if (s == 0) return 0; + if (s == 2) state = 2; *wind_u = lambda * wu_h + (1.f-lambda) * wu_l; *wind_v = lambda * wv_h + (1.f-lambda) * wv_l; @@ -233,7 +257,7 @@ int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int // magnitude. *wind_var = 0.5f * (wuvar_h + wuvar_l + wvvar_h + wvvar_l); - return 1; + return state; } // vim:sw=4:ts=4:et:cindent diff --git a/pred_src/wind/wind_file.c b/pred_src/wind/wind_file.c index 6075d93..19b769d 100644 --- a/pred_src/wind/wind_file.c +++ b/pred_src/wind/wind_file.c @@ -173,11 +173,10 @@ _parse_values_line(const char* line, unsigned int n_values, float* values) while(1 == sscanf(record, "%f", &value)) { if(record_idx >= n_values) { - if(verbosity > 0) - fprintf(stderr, "WARN: Read too many values for axis " - "(%i, expected %i). " - "Ignoring them.\n", - record_idx, n_values); + fprintf(stderr, "ERROR: Read too many values for axis " + "(%i, expected %i).\n" + record_idx, n_values); + return 0; } else { values[record_idx] = value; } @@ -473,7 +472,7 @@ _bilinear_interpolate(float ll, float lr, float rl, float rr, float lambda1, flo return _lerp(il,ir,lambda2); } -void +int wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, float* windu, float *windv, float *uvar, float *vvar) { @@ -493,6 +492,8 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, float left_height, right_height; float lat_lambda, lon_lambda, pr_lambda; + int status = 1; // 0: error (returned immediately) 1: ok; 2: ok with warnings + assert(file); assert(windu && windv); @@ -521,9 +522,8 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, if(!_wind_file_axis_find_value(file->axes[1], lat, _float_is_left_of, &left_lat_idx, &right_lat_idx)) { - if(verbosity > 0) - fprintf(stderr, "WARN: Latitude %f is not covered by file.\n", lat); - return; + fprintf(stderr, "ERROR: Latitude %f is not covered by file.\n", lat); + return 0; } left_lat = file->axes[1]->values[left_lat_idx]; right_lat = file->axes[1]->values[right_lat_idx]; @@ -532,9 +532,8 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, if(!_wind_file_axis_find_value(file->axes[2], lon, _longitude_is_left_of, &left_lon_idx, &right_lon_idx)) { - if(verbosity > 0) - fprintf(stderr, "WARN: Longitude %f is not covered by file.\n", lon); - return; + fprintf(stderr, "ERROR: Longitude %f is not covered by file.\n", lon); + return 0; } left_lon = file->axes[2]->values[left_lon_idx]; right_lon = file->axes[2]->values[right_lon_idx]; @@ -645,6 +644,7 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, file->axes[0]->values[left_pr_idx], _wind_file_get_height(file, left_lat_idx, left_lon_idx, left_pr_idx)); + status = 2; } if(right_pr_idx == file->axes[0]->n_values) @@ -658,6 +658,7 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, file->axes[0]->values[right_pr_idx], _wind_file_get_height(file, left_lat_idx, left_lon_idx, right_pr_idx)); + status = 2; } if((left_pr_idx == file->axes[0]->n_values) || @@ -665,7 +666,7 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, { fprintf(stderr, "ERROR: Moved to a totally stupid height (%f). " "Giving up!\n", height); - return; + return 0; } if(verbosity > 1) @@ -780,6 +781,8 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, *uvar = usqmean - umean * umean; *vvar = vsqmean - vmean * vmean; } + + return status; } // Data for God's own editor. diff --git a/pred_src/wind/wind_file.h b/pred_src/wind/wind_file.h index c141388..ca2b3d9 100644 --- a/pred_src/wind/wind_file.h +++ b/pred_src/wind/wind_file.h @@ -29,7 +29,7 @@ wind_file_t *wind_file_new (const char *file); // Free resources associated with 'file'. void wind_file_free (wind_file_t *file); -void wind_file_get_wind (wind_file_t *file, +int wind_file_get_wind (wind_file_t *file, float lat, float lon, float height, diff --git a/pred_src/wind/wind_file_cache.c b/pred_src/wind/wind_file_cache.c index 5a2ed76..cc2844c 100644 --- a/pred_src/wind/wind_file_cache.c +++ b/pred_src/wind/wind_file_cache.c @@ -310,12 +310,6 @@ wind_file_cache_find_entry(wind_file_cache_t *cache, } } } - - if(!*earlier) { *earlier = *later; } - if(!*later) { *later = *earlier; } - - // If all else fails, just choose the first entry. - if(!*earlier) { *earlier = *later = cache->entries[0]; } } const char* diff --git a/predict.py b/predict.py index a675806..34e7e02 100755 --- a/predict.py +++ b/predict.py @@ -53,6 +53,8 @@ progress = { 'gfs_timestamp': '', 'pred_running': False, 'pred_complete': False, + 'warnings': False, + 'pred_output': [], 'error': '', } @@ -279,12 +281,34 @@ def main(): else: alarm_flags = [] - subprocess.call([pred_binary, '-i' + gfs_dir, '-v', '-o'+uuid_path+'flight_path.csv', uuid_path+'scenario.ini'] + alarm_flags) + command = [pred_binary, '-i' + gfs_dir, '-v', '-o'+uuid_path+'flight_path.csv', uuid_path+'scenario.ini'] + alarm_flags + pred_process = subprocess.Popen(command, stdout=subprocess.PIPE) + pred_output = [] + + while True: + line = pred_process.stdout.readline() + if line == '': + break + + # pass through + sys.stdout.write(line) + + if ("WARN" in line or "ERROR" in line) and len(pred_output) < 10: + pred_output.append(line) + + exit_code = pred_process.wait() shutil.rmtree(gfs_dir) - update_progress(pred_running=False, pred_complete=True) - statsd.increment('success') + if exit_code == 0: + update_progress(pred_running=False, pred_complete=True) + statsd.increment('success') + elif exit_code == 1: + update_progress(pred_running=False, error="Predictor exit code: 1", pred_output=pred_output) + statsd.increment('error_exit') + elif exit_code == 2: + update_progress(pred_running=False, pred_complete=True, warnings=True, pred_output=pred_output) + statsd.increment('success_with_warnings') def purge_cache(): """ diff --git a/predict/js/pred/pred.js b/predict/js/pred/pred.js index dd884e7..cfca744 100644 --- a/predict/js/pred/pred.js +++ b/predict/js/pred/pred.js @@ -251,6 +251,8 @@ function getJSONProgress(pred_uuid) { function processProgress(progress) { if ( progress['error'] ) { clearInterval(ajaxEventHandle); + for (var i = 0; i < progress['pred_output'].length; i++) + appendDebug("Pred output: " + progress['pred_output'][i]); appendDebug("There was an error in running the prediction: " + progress['error']); resetGUI(); @@ -272,6 +274,12 @@ function processProgress(progress) { + progress['run_time']); appendDebug("Server said it used the " + progress['gfs_timestamp'] + " GFS model"); + + for (var i = 0; i < progress['pred_output'].length; i++) + appendDebug("Pred output: " + progress['pred_output'][i]); + if (progress['warnings']) + toggleWindow("scenario_template", "showHideDebug", "Show Debug", "Hide Debug", "show"); + writePredictionInfo(current_uuid, progress['run_time'], progress['gfs_timestamp']); addHashLink("uuid="+current_uuid);