From 1fc73b9510f9bd25c438a9e5e5f5b9875f9bb707 Mon Sep 17 00:00:00 2001 From: Daniel Richman Date: Tue, 25 Dec 2012 00:28:42 +0000 Subject: [PATCH] Fix bugs, tidy, add UI stuff --- pred_src/pred.c | 15 ++-------- pred_src/run_model.c | 46 ++++++++++-------------------- pred_src/wind/wind_file.c | 8 ++---- predict.py | 29 +++++++++++++------ predict/includes/config.inc.php | 6 ++-- predict/js/pred/pred-ui.js | 1 + predict/js/pred/pred.js | 50 ++++++++++++++++++++------------- 7 files changed, 75 insertions(+), 80 deletions(-) diff --git a/pred_src/pred.c b/pred_src/pred.c index 6b7879d..0633b1d 100644 --- a/pred_src/pred.c +++ b/pred_src/pred.c @@ -43,8 +43,6 @@ 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; @@ -283,19 +281,12 @@ int main(int argc, const char *argv[]) { exit(1); } - state = run_model(file_cache, alt_model, + if (!run_model(file_cache, alt_model, initial_lat, initial_lng, initial_alt, initial_timestamp, - rmswinderror) - if (state == 0) - { + rmswinderror)) { 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); } @@ -320,7 +311,7 @@ int main(int argc, const char *argv[]) { // release the file cache resources. wind_file_cache_free(file_cache); - return exit_code; + return 0; } 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 6facad1..401d029 100644 --- a/pred_src/run_model.c +++ b/pred_src/run_model.c @@ -75,13 +75,11 @@ _advance_one_timestep(wind_file_cache_t* cache, if(!altitude_model_get_altitude(state->alt_model, timestamp - initial_timestamp, &state->alt)) - return 0; // alt <= 0; finished. + 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 -1; - } + &wind_v, &wind_u, &wind_var)) + return -1; // error _get_frame(state->lat, state->lng, state->alt, &ddlat, &ddlng); @@ -108,7 +106,7 @@ _advance_one_timestep(wind_file_cache_t* cache, state->loglik += (double)(u_lik + v_lik); } - return 1; + return 1; // OK, and continue } static int _state_compare_rev(const void* a, const void *b) @@ -145,14 +143,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 - int last_retval = -1; // error + int r, return_code = 1; - while(true) + while(1) { - last_retval = - _advance_one_timestep(cache, TIMESTEP, timestamp, initial_timestamp, + r = _advance_one_timestep(cache, TIMESTEP, timestamp, initial_timestamp, n_states, states, rmswinderror); - if (last_retval != 1) + if (r == -1) // error getting wind. Save prediction, but emit error messages + return_code = 0; + + if (r != 1) // 1 = continue break; // Sort the array of models in order of log likelihood. @@ -179,16 +179,12 @@ int run_model(wind_file_cache_t* cache, altitude_model_t* alt_model, free(states); - if (last_retval != 0) - return 0; - else - return 1; + return return_code; } 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, 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 }; @@ -200,7 +196,7 @@ int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int &(found_entries[0]), &(found_entries[1])); if(!found_entries[0] || !found_entries[1]) { - fprintf(stderr, "ERROR: Could not locate appropriate wind data tile for time.\n"); + fprintf(stderr, "ERROR: Do not have wind data for this (lat, lon, alt, time).\n"); return 0; } @@ -234,21 +230,9 @@ int get_wind(wind_file_cache_t* cache, float lat, float lng, float alt, long int lambda = 0.5f; 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; - } - + if (s == 0) return 0; // hard error 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; @@ -257,7 +241,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 state; + return 1; } // vim:sw=4:ts=4:et:cindent diff --git a/pred_src/wind/wind_file.c b/pred_src/wind/wind_file.c index 19b769d..50b4f69 100644 --- a/pred_src/wind/wind_file.c +++ b/pred_src/wind/wind_file.c @@ -174,7 +174,7 @@ _parse_values_line(const char* line, unsigned int n_values, float* values) if(record_idx >= n_values) { fprintf(stderr, "ERROR: Read too many values for axis " - "(%i, expected %i).\n" + "(%i, expected %i).\n", record_idx, n_values); return 0; } else { @@ -492,8 +492,6 @@ 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); @@ -644,7 +642,6 @@ 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,7 +655,6 @@ 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) || @@ -782,7 +778,7 @@ wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, *vvar = vsqmean - vmean * vmean; } - return status; + return 1; } // Data for God's own editor. diff --git a/predict.py b/predict.py index 34e7e02..b34f6c4 100755 --- a/predict.py +++ b/predict.py @@ -282,7 +282,7 @@ def main(): 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_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pred_output = [] while True: @@ -293,22 +293,33 @@ def main(): # pass through sys.stdout.write(line) + if "ERROR: Do not have wind data" in line: + pred_output.append("Either the latitude, longitude deltas were too small, or " + "the prediction ran for more than 5 hours.") + pred_output.append("If it is the former, please re-run your prediction with larger deltas.") + pred_output.append("") + if ("WARN" in line or "ERROR" in line) and len(pred_output) < 10: - pred_output.append(line) + pred_output.append(line.strip()) exit_code = pred_process.wait() shutil.rmtree(gfs_dir) - if exit_code == 0: + if exit_code == 1: + # Hard error from the predictor. Tell the javascript it completed, so that it will show the trace, + # but pop up a 'warnings' window with the error messages + update_progress(pred_running=False, pred_complete=True, warnings=True, pred_output=pred_output) + statsd.increment('success_serious_warnings') + elif pred_output: + # Soft error (altitude too low error, typically): pred_output being set forces the debug + # window open with the messages in + update_progress(pred_running=False, pred_complete=True, pred_output=pred_output) + statsd.increment('success_minor_warnings') + else: + assert 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/includes/config.inc.php b/predict/includes/config.inc.php index 6c04796..7368bd8 100644 --- a/predict/includes/config.inc.php +++ b/predict/includes/config.inc.php @@ -4,15 +4,15 @@ define("GMAPS_API_KEY", "ABQIAAAA4T7AS90KUqGrNPOsl6eyCBS4mbmQPYGFaQoYTVDm_qb3IIB-WBSwfZE_KhJy2GpxCqBbVm7PoSKM9Q"); // Who should we email about errors etc? -define("ADMIN_EMAIL", "jon@hexoc.com"); +define("ADMIN_EMAIL", "daniel@habhub.org"); define("LOCATION_SAVE_ENABLE", true); // Path to the root of the git repo inc. trailing / -define("ROOT", "/var/www/hab/predict/"); +define("ROOT", "/var/www/cusf-standalone-predictor/"); // Path to python virtualenv to use -// define("PYTHON", ROOT . "ENV/bin/python"); +define("PYTHON", ROOT . "venv/bin/python"); // Path to prediction data dir from predict/ define("PREDS_PATH", "preds/"); diff --git a/predict/js/pred/pred-ui.js b/predict/js/pred/pred-ui.js index af5aac4..b5782ab 100644 --- a/predict/js/pred/pred-ui.js +++ b/predict/js/pred/pred-ui.js @@ -43,6 +43,7 @@ function throwError(data) { // Reset the GUI to a onLoad state ready for a new prediction to be shown function resetGUI() { $("#status_message").fadeOut(500); + $("#error_window").fadeOut(500); // now clear the status window $("#prediction_status").html(""); $("#prediction_progress").progressbar("options", "value", 0); diff --git a/predict/js/pred/pred.js b/predict/js/pred/pred.js index cfca744..4b26118 100644 --- a/predict/js/pred/pred.js +++ b/predict/js/pred/pred.js @@ -57,12 +57,11 @@ function displayOld() { appendDebug("The prediction was not completed" + " correctly, quitting"); } else { - appendDebug("JSON said the prediction completed " - + "without errors"); + appendDebug("JSON said the prediction completed"); + processCompletedPrediction(progress); writePredictionInfo(current_uuid, progress['run_time'], progress['gfs_timestamp']); - getCSV(current_uuid); } }); } @@ -74,6 +73,8 @@ function displayOld() { function predSub() { appendDebug(null, 1); // clear debug window appendDebug("Sending data to server..."); + // Gets in the way of #status_message + $("#error_window").fadeOut(250); // Initialise progress bar $("#prediction_progress").progressbar({ value: 0 }); $("#prediction_status").html("Sending data to server..."); @@ -214,6 +215,7 @@ function getCSV(pred_uuid) { function getJSONProgress(pred_uuid) { $.ajax({ url:"preds/"+pred_uuid+"/progress.json", + cache: false, dataType:'json', timeout: ajaxTimeout, error: function(xhr, status, error) { @@ -245,14 +247,37 @@ function getJSONProgress(pred_uuid) { }); } +function processCompletedPrediction(progress) { + // parse the data + getCSV(current_uuid); + appendDebug("Server gave a prediction run timestamp of " + + progress['run_time']); + appendDebug("Server said it used the " + + progress['gfs_timestamp'] + " GFS model"); + + var warnings = "The prediction completed, but with warnings!
" + + "The prediction may be unreliable!


"; + for (var i = 0; i < progress['pred_output'].length; i++) { + appendDebug("Pred output: " + progress['pred_output'][i]); + warnings += progress['pred_output'][i] + "
"; + } + + if (progress['pred_output'].length != 0) + toggleWindow("scenario_template", "showHideDebug", "Show Debug", "Hide Debug", "show"); + + if (progress['warnings']) + throwError(warnings); + + writePredictionInfo(current_uuid, progress['run_time'], + progress['gfs_timestamp']); +} + // The contents of progress.json are given to this function to process // If the prediction has completed, reset the GUI and display the new // prediction; otherwise update the progress window 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(); @@ -268,20 +293,7 @@ function processProgress(progress) { resetGUI(); // stop polling for JSON clearInterval(ajaxEventHandle); - // parse the data - getCSV(current_uuid); - appendDebug("Server gave a prediction run timestamp of " - + 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']); + processCompletedPrediction(progress); addHashLink("uuid="+current_uuid); } else if ( progress['pred_running'] != true ) { $("#prediction_status").html("Waiting for predictor to run...");