From 4eebac05a4a118382813afe454aa95bc27018c34 Mon Sep 17 00:00:00 2001
From: Kyle <kyle.c.klenk@gmail.com>
Date: Thu, 29 Jun 2023 18:41:44 +0000
Subject: [PATCH] Add execute_command function and general cleanup

Added a new function to reduce repeat code.

Added more comments, and better formatted the code
---
 README.md                                     |   6 +
 runS1S2.py => legacy_scripts/runS1S2_other.py |   0
 main.cpp                                      | 141 ++++++++----------
 test.py                                       |  13 --
 4 files changed, 66 insertions(+), 94 deletions(-)
 rename runS1S2.py => legacy_scripts/runS1S2_other.py (100%)
 delete mode 100644 test.py

diff --git a/README.md b/README.md
index 1d87f64..b938dcf 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,9 @@ To compile the actors program, run the following commands:
 - make
 
 Upon success a binary will be created in the top-level directory.
+
+
+### Running the actor program
+
+To run the actors program to find the S1 threshold, run the following command:
+- ./my_program --S1-min 100 --S1-max 200
diff --git a/runS1S2.py b/legacy_scripts/runS1S2_other.py
similarity index 100%
rename from runS1S2.py
rename to legacy_scripts/runS1S2_other.py
diff --git a/main.cpp b/main.cpp
index af06b5d..50d264b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -32,6 +32,26 @@ class config : public actor_system_config {
         }
 };
 
+/**
+ * Function that takes in a command and
+ * returns the piped output as a string
+*/
+std::string execute_command(std::stringstream &command) {
+    std::string command_output = "";
+    char buffer[128];
+    FILE *pipe;
+
+    pipe = popen(command.str().c_str(), "r");
+    if (!pipe) throw std::runtime_error("popen() failed!");
+    while (!feof(pipe)) {
+        if (fgets(buffer, 128, pipe) != NULL)
+            command_output += buffer;
+    }
+    pclose(pipe);        
+
+    return command_output;
+}
+
 
 
 bool verify_ap(int s1_strength) {
@@ -39,62 +59,38 @@ bool verify_ap(int s1_strength) {
     bool ap_occured = false;
     std::stringstream results_file_path, igbhead_command, igbextract_command, 
     tmp_output_file_path, tmp_output_file;
+    std::string command_output;
+    std::smatch match; // for regex matchin
 
     // Verify the file exists
     results_file_path << "simulations/output/s1_attempt_" << s1_strength << "/vm.igb";
-    std::cout << results_file_path.str() << std::endl;
     std::ifstream file(results_file_path.str().c_str());
-    std::cout << file.good() << std::endl;
+    if (!file.good()) throw std::runtime_error("Failed to find the results file");
 
     // Find the number of nodes in the mesh
     igbhead_command << "igbhead " << results_file_path.str().c_str();
-    FILE* pipe = popen(igbhead_command.str().c_str(), "r"); 
-    if (!pipe) std::cerr << "popen() failed!" << std::endl;
-    char buffer[128];
-    std::string result = "";
-    while (!feof(pipe)) {
-        if (fgets(buffer, 128, pipe) != NULL)
-            result += buffer;
-    }
-    pclose(pipe); // close the pipe
-
-    // std::cout << result << std::endl;
+    command_output = execute_command(igbhead_command);
+    
     std::regex rgx("x dimension:\\s+(\\d+)");
-    std::smatch match;
-    if (std::regex_search(result, match, rgx)) {
+    if (std::regex_search(command_output, match, rgx)) {
         num_nodes = std::stoi(match[1]);
     } else {
-        std::cout << "No match" << std::endl;
+        throw std::runtime_error("Failed to find the number of nodes in the mesh");
     }
 
     tmp_output_file_path << "simulations/output/s1_attempt_" << s1_strength << "/tmp/";
-    if (std::filesystem::create_directories(tmp_output_file_path.str().c_str())) {
-        std::cout << "Created directory: " << tmp_output_file_path.str() << std::endl;
-    } else {
-        std::cout << "Failed to create directory: " << tmp_output_file_path.str() << std::endl;
-    }
+    if (!std::filesystem::create_directories(tmp_output_file_path.str().c_str()))
+        throw std::runtime_error("Failed to create temp output directory");
 
     for (int i = 0; i < num_nodes; i++) {
         tmp_output_file << tmp_output_file_path.str() << "node" << i << ".bin";
-        igbextract_command << "igbextract " << "-o binary -l " << i << " " <<
+            igbextract_command << "igbextract " << "-o binary -l " << i << " " <<
             results_file_path.str() << " -O " << tmp_output_file.str();
-
-        // std::cout << igbextract_command.str() << "\n\n\n\n\n";
         
-        pipe = popen(igbextract_command.str().c_str(), "r"); 
-        if (!pipe) std::cerr << "popen() failed!" << std::endl;
-        char buffer[128];
-        std::string result = "";
-        while (!feof(pipe)) {
-            if (fgets(buffer, 128, pipe) != NULL)
-                result += buffer;
-        }
-        pclose(pipe); // close the pipe
-
+        command_output = execute_command(igbextract_command);
 
         // Read in the values from the tmp_output_file
         std::vector<float> node_data;
-
         std::ifstream tmp_output_file_in(tmp_output_file.str().c_str(), std::ios::binary);
         tmp_output_file_in.seekg(0, std::ios::end);
         std::streampos tmp_output_file_size = tmp_output_file_in.tellg();
@@ -118,23 +114,27 @@ bool verify_ap(int s1_strength) {
     return ap_occured;
 }
 
+/**
+ * Function that takes in the min and max values of S1 strength
+ * and returns the midpoint of the two values
+*/
 int bisection(int s1_min, int s1_max) {
     int s1_mid = (s1_max - s1_min) / 2.0 + s1_min;
     return s1_mid;
 }
 
 
-
-
+/**
+ * Actor that finds the S1 threshold using bisection
+*/
 behavior s1_actor(event_based_actor* self) {
     return {
         [=](int duration, int s1_strength_min,  int s1_strength_max, int tol) {
             // Initialize the variables
             std::stringstream python_command, log_file;
-            FILE *pipe;
-            char buffer[128];
-            std::string result = "";
+            std::string command_output = "";
             int current_guess;
+            std::ofstream out_stream;
 
             // Verify S1_min does not cause an AP
             aout(self) << "Verifying S1_min does not cause an AP\n";
@@ -144,24 +144,18 @@ behavior s1_actor(event_based_actor* self) {
                << " --S1-strength " << s1_strength_min;
 
             log_file << "simulations/logs/output" << s1_strength_min << ".txt";
-            
-            pipe = popen(python_command.str().c_str(), "r");
-            if (!pipe) throw std::runtime_error("popen() failed!");
-            while (!feof(pipe)) {
-                if (fgets(buffer, 128, pipe) != NULL)
-                    result += buffer;
-            }
-            pclose(pipe);
 
-            std::ofstream out(log_file.str().c_str());
-            out << result;
-            out.close();
+            // Run S1 By calling the python script
+            command_output = execute_command(python_command);
 
-            if (verify_ap(s1_strength_min)) {
-                aout(self) << "AP occured at S1_min\n";
-                throw std::runtime_error("AP occured at S1_min - Select a new S1_min");
-            }
+            // Log Ouput
+            out_stream.open(log_file.str().c_str()); 
+            out_stream << command_output;
+            out_stream.close();
 
+            if (verify_ap(s1_strength_min))
+                throw std::runtime_error("AP occured at S1_min - Select a new S1_min");
+            
             python_command.str("");
             log_file.str("");
 
@@ -174,23 +168,15 @@ behavior s1_actor(event_based_actor* self) {
             
             log_file << "simulations/logs/output" << s1_strength_max << ".txt";
 
-            pipe = popen(python_command.str().c_str(), "r");
-            if (!pipe) throw std::runtime_error("popen() failed!");
-            while (!feof(pipe)) {
-                if (fgets(buffer, 128, pipe) != NULL)
-                    result += buffer;
-            }
-            pclose(pipe);
+            command_output = execute_command(python_command);
 
-            out.open(log_file.str().c_str());
-            out << result;
-            out.close();
+            out_stream.open(log_file.str().c_str());
+            out_stream << command_output;
+            out_stream.close();
 
-            if (!verify_ap(s1_strength_max)) {
-                aout(self) << "AP did not occur at S1_max\n";
+            if (!verify_ap(s1_strength_max))
                 throw std::runtime_error("AP did not occur at S1_max - Select a new S1_max");
-            }
-
+        
             python_command.str("");
             log_file.str("");
 
@@ -208,17 +194,11 @@ behavior s1_actor(event_based_actor* self) {
                 
                 log_file << "simulations/logs/output" << current_guess << ".txt";
 
-                pipe = popen(python_command.str().c_str(), "r");
-                if (!pipe) throw std::runtime_error("popen() failed!");
-                while (!feof(pipe)) {
-                    if (fgets(buffer, 128, pipe) != NULL)
-                        result += buffer;
-                }
-                pclose(pipe);
+                command_output = execute_command(python_command);
 
-                out.open(log_file.str().c_str());
-                out << result;
-                out.close();
+                out_stream.open(log_file.str().c_str());
+                out_stream << command_output;
+                out_stream.close();
 
                 if (verify_ap(current_guess)) {
                     aout(self) << "AP occured at current guess\n";
@@ -231,12 +211,11 @@ behavior s1_actor(event_based_actor* self) {
                 current_guess = bisection(s1_strength_min, s1_strength_max);
                 python_command.str("");
                 log_file.str("");
-                result = "";
+                command_output = "";
             }
 
             aout(self) << "Final S1_strength: " << s1_strength_max << "\n";
 
-
         }
     };
 }
diff --git a/test.py b/test.py
deleted file mode 100644
index 61224c8..0000000
--- a/test.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from thespian.actors import *
-
-class MyActor(Actor):
-    def __init__(self, name):
-        self.name = name
-
-    def receiveMessage(self, message, sender):
-        print(f"My name is {self.name} and I received {message} from {sender}")
-
-system = ActorSystem()
-
-actor = system.createActor(MyActor.__init__("test", 5))
-system.tell(actor, "Hello")
\ No newline at end of file
-- 
GitLab