home *** CD-ROM | disk | FTP | other *** search
/ ftp.hitl.washington.edu / ftp.hitl.washington.edu.tar / ftp.hitl.washington.edu / pub / people / peter / ER / BP_trend_driver.cxx < prev    next >
C/C++ Source or Header  |  1998-07-07  |  10KB  |  376 lines

  1. /*
  2.  BP_trend_driver.cc
  3. */
  4.  
  5. #include "BP_trend_driver.h"
  6.  
  7. #include <iostream.h>
  8. #include <vector.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11.  
  12. #include "v3dSystem.h"
  13. #include "v3dUniverse.h"
  14.  
  15. //#define TIMESTAMP       // Time-stamp data changes.
  16.  
  17. #ifdef TIMESTAMP
  18. #include "timestamp.h"
  19. #endif
  20.  
  21. ///////////////////////////
  22. //    BPTrendDriver    //
  23. /////////////////////////
  24.  
  25. //const double BPTrendDriver::ms_Interval = 25.0;    // 25 ms per interval
  26. const double BPTrendDriver::ms_Interval = 40.0;    // 40 ms per interval
  27.  
  28. //static vector <vector <BP_TREND_DATA_TYPE> >    test_BP_values;
  29. static vector <BP_TREND_DATA_TYPE>    BP_trend_values;
  30.  
  31. template<class T>
  32. vector<T> to_vec (int num_values, T *data_ary)
  33. {
  34.         vector<T> new_vec;
  35.         for (int i = 0; i < num_values; ++i)
  36.                 new_vec.push_back (data_ary[i]);
  37.         return new_vec;
  38. }
  39.  
  40. #include <stdio.h>
  41.  
  42. void
  43. BPTrendDriver::InitializeBaseFunctionValues(
  44.     float domain_low, float domain_high,
  45.     float range_low, unsigned int set_size)
  46. {
  47.     float    low = range_low + M_PI_2,
  48.         domain = domain_high - domain_low,
  49.         step = domain / (float)set_size,
  50.         cur_x = domain_low;
  51.  
  52. //cerr << "BP trend step size: " << step << endl;
  53.     for (int i = 0; i < set_size; ++i) {
  54. //cerr << "Element " << i << ": atan (" << cur_x << ") = " << atanf(cur_x) + low << endl;
  55.         BP_trend_values.push_back(atanf(cur_x) + low);
  56.         cur_x += step;
  57.     }
  58. //cerr << "Finished!" << endl;
  59.  
  60.     data_range_.high_threshold_value
  61.         = 0.75 * BP_trend_values[BP_trend_values.size() - 1];
  62.     data_range_.low_threshold_value = -1 * data_range_.high_threshold_value;
  63.  
  64. cerr << "Thresholds: High: " << data_range_.high_threshold_value <<
  65.     " Low: " << data_range_.low_threshold_value << endl;
  66.  
  67.     // The range of random offset is 1/10th the range of the
  68.     // base function's data.
  69.     random_range_ = 0.1 * (data_range_.high_threshold_value -
  70.         data_range_.low_threshold_value);
  71. cerr << "Random range: " << random_range_ << endl;;
  72. }
  73.  
  74. void
  75. BPTrendDriver::SeedTrend(long seed_val)
  76. {
  77.     srand48(seed_val);
  78. }
  79.  
  80. BPTrendDriver::BPTrendDriver()
  81. {
  82.     InitializeBaseFunctionValues(-10, 10, 0, 500);
  83.  
  84.     data_list = 0;
  85.  
  86.     SeedTrend(1);
  87.     Reset();
  88.  
  89.     // Register the driver with the current universe.
  90.     // Later, the universe should be passed as a parameter.
  91.     v3dSystem::GetCurrentUniverse()->RegisterEventSender(this);
  92.  
  93.     // Register an event to tell receivers that new data has arrived.
  94.     RegisterEvent(new BPTrendDataUpdateEvent);
  95.  
  96.     Unpause();
  97. }
  98.  
  99. BPTrendDriver::~BPTrendDriver()
  100. {
  101.     delete data_list;
  102. }
  103.  
  104. void
  105. BPTrendDriver::TestEvents()
  106. {
  107.     // Update the BP trend driver index.
  108.     if (!IsPaused()) {
  109.         update_current_index();
  110.         // Test the events registered with this sender first.
  111.         EventMap::iterator event_iter = events_.begin();
  112.         for (; event_iter != events_.end(); ++event_iter)
  113.             if ((*event_iter).second->IsActive())
  114.                 (*event_iter).second->Test();
  115.     }
  116.  
  117.     // Next, tell all event senders registered with this object to
  118.     // test their events.
  119.     EventSenderVector::iterator event_sender_iter = event_senders_.begin();
  120.     for (; event_sender_iter != event_senders_.end(); ++event_sender_iter)
  121.         (*event_sender_iter)->TestEvents ();
  122. }
  123.  
  124.  
  125. // BPTrendDriver::Reset
  126. //    Resets the BP trend.
  127. void
  128. BPTrendDriver::Reset()
  129. {
  130.     // Create a new set of data.
  131.     CreateData ((int)(100 * drand48()), drand48() > .5 ? true : false, 100 + (int)(100 * drand48()));
  132. }
  133.  
  134. BP_TREND_DATA_RANGE
  135. BPTrendDriver::switch_data (int set_no, int new_set_size)
  136. {
  137. #if 0
  138.     if (set_no < 0) 
  139.         ++current_set_;
  140.     else
  141.         current_set_ = set_no;
  142.  
  143.     // Choose set 0 if the specified set is out of range.
  144.     if (current_set_ >= BP_trend_values.size())
  145.         current_set_ = 0;
  146. #endif
  147. }
  148.  
  149. BP_TREND_DATA_RANGE
  150. BPTrendDriver::CreateData(unsigned int zero_set_size, bool trend_up,
  151.     unsigned int trend_set_size)
  152. {
  153.     // If the new set size is 0, then use the base function's set size.
  154.     int    set_size = BP_trend_values.size();
  155.     if (trend_set_size == 0)
  156.         trend_set_size = set_size;
  157.     max_index_ = trend_set_size + zero_set_size;
  158. cerr << "BP set size: " << trend_set_size << " Max index: " << max_index_ << endl;
  159.  
  160.     // Allocate a new array to hold the data values.
  161.     delete [] data_list;
  162.  
  163.     data_list = new BP_TREND_DATA_TYPE [max_index_];
  164.  
  165.     // Create the pre-trend zero line with random offset.
  166.     for (int i = 0; i < zero_set_size; ++i)
  167.         data_list[i] = (0.5 - drand48()) * random_range_;
  168.  
  169.     // Copy the function values from the base function value vector,
  170.     // and add a random offset.
  171.     float    step_size = set_size / (1.0 * trend_set_size),
  172.         real_index = 0.5;
  173.     int    cur_index = 0;
  174.     threshold_cross_index_ = 0;
  175.  
  176. cerr << "Step size: " << step_size << endl;
  177.     if (trend_up) {
  178.         for (int i = zero_set_size; i < max_index_; ++i) {
  179.             data_list[i] = BP_trend_values[cur_index];
  180.             data_list[i] += (0.5 - drand48()) * random_range_;
  181.             if (!threshold_cross_index_ &&
  182.                 (data_list[i] >= data_range_.high_threshold_value))
  183.                 threshold_cross_index_ = i;
  184.             real_index += step_size;
  185.             cur_index = (int)ftrunc(real_index);
  186.         }
  187.     } else {
  188.         for (int i = zero_set_size; i < max_index_; ++i) {
  189.             data_list[i] = -BP_trend_values[cur_index];
  190.             data_list[i] += (0.5 - drand48()) * random_range_;
  191.             if (!threshold_cross_index_ &&
  192.                 (data_list[i] <= data_range_.low_threshold_value))
  193.                 threshold_cross_index_ = i;
  194.             real_index += step_size;
  195.             cur_index = (int)ftrunc(real_index);
  196.         }
  197.     }
  198. cerr << "Theshold cross index: " << threshold_cross_index_ << endl;;
  199.  
  200.     // Set the index to the start of the data.
  201.     reset_current_index();
  202.  
  203.     // Get the ranges of the data.
  204.     data_range_.maximum_value = data_list[0];
  205.     data_range_.minimum_value = data_list[0];
  206.     for (int i = 1; i < max_index_; ++i) {
  207.         if (data_list[i] > data_range_.maximum_value)
  208.             data_range_.maximum_value = data_list[i];
  209.         if (data_list[i] < data_range_.minimum_value)
  210.             data_range_.minimum_value = data_list[i];
  211.     }
  212.  
  213.     return data_range_;
  214. }
  215.  
  216. void
  217. BPTrendDriver::CreatePostThresholdData (bool high_threshold)
  218. {
  219.     BP_TREND_DATA_TYPE    base_number;
  220.  
  221.     if (high_threshold)
  222.         base_number = BP_trend_values[BP_trend_values.size() - 1];
  223.     else
  224.         base_number = -BP_trend_values[BP_trend_values.size() - 1];
  225.  
  226.     // Create the post-trend zero-slope line with random offset.
  227.     for (int i = 0; i < max_index_; ++i)
  228.         data_list[i] = base_number + (0.5 - drand48()) * random_range_;
  229. }
  230.  
  231. void
  232. BPTrendDriver::BP_update_callback(const v3dEventMessage *message)
  233. {
  234.     ((BPTrendDriver *)message->GetEventReceiver())->update_current_index();
  235. }
  236.  
  237. // usec_diff
  238. //    Calculate the difference in microseconds between the two times
  239. //    passed in.
  240. inline float
  241. usec_diff (const timeval& current_time, const timeval& past_time)
  242. {
  243.     return (current_time.tv_sec - past_time.tv_sec) * 1000000 +
  244.         current_time.tv_usec - past_time.tv_usec;
  245. }
  246.  
  247. // BPTrendDriver::update_current_index
  248. //    Changes the current index to the BP data depending on how much
  249. //    time has elapsed since the last update.
  250. //    Each value in the array represents a piece of BP data read at
  251. //    40ms intervals.
  252. int
  253. BPTrendDriver::update_current_index ()
  254. {
  255. #ifdef TIMESTAMP
  256. static TrackedEvent low_threshold_crossed_event(TrackedEvent::SystemEvent,
  257.             24, "Blood pressure low threshold crossed");
  258. static TrackedEvent high_threshold_crossed_event(TrackedEvent::SystemEvent,
  259.             23, "Blood pressure high threshold crossed");
  260. #endif    // TIMESTAMP
  261.  
  262.     if (IsPaused()) return current_index_;
  263.  
  264.     timeval current_time;
  265.  
  266. //cerr << "clock / sec: " << CLOCKS_PER_SEC;
  267.     gettimeofday (¤t_time);
  268. //cerr << " elapsed clock: " << current_time.tv_usec - last_time_.tv_usec;
  269. //cerr << " elapsed int: " << ((current_time.tv_sec - last_time_.tv_sec) *
  270. //        1000000 + current_time.tv_usec - last_time_.tv_usec)
  271. //         / (1000 * ms_Interval);
  272. //cerr << endl;
  273.  
  274. //    true_index_ += ((current_time.tv_sec - last_time_.tv_sec) * 1000000 +
  275. //        current_time.tv_usec - last_time_.tv_usec) /
  276. //        (1000 * ms_Interval);
  277.     true_index_ += usec_diff (current_time, last_time_) /
  278.         (1000 * ms_Interval);
  279.  
  280.     if (true_index_ >= max_index_) {
  281.         CreatePostThresholdData(data_list[max_index_ - 1] > data_range_.high_threshold_value);
  282.         while (true_index_ >= max_index_)
  283.             true_index_ -= max_index_;
  284.     }
  285.  
  286.     current_index_ = (int) ffloor (true_index_);
  287.     if (threshold_cross_index_ && (threshold_cross_index_ < current_index_))
  288.     {
  289. cerr << "Threshold crossed." << endl;
  290. #ifdef TIMESTAMP
  291.         // Timestamp the threshold crossing event.
  292.         if (data_list[current_index_] >= data_range_.high_threshold_value)
  293.             TimestampedEvent::AddEvent(&high_threshold_crossed_event);
  294.         else
  295.             TimestampedEvent::AddEvent(&low_threshold_crossed_event);
  296. #endif    // TIMESTAMP
  297.         threshold_cross_index_ = 0;
  298.     }
  299.  
  300.     last_time_ = current_time;
  301.  
  302. //cerr << " true index: " << true_index_;
  303. //cerr << " current index: " << current_index_ << endl;
  304.     return current_index_;
  305. }
  306.  
  307. int
  308. BPTrendDriver::reset_current_index ()
  309. {
  310. //    last_time_ = clock();
  311.     gettimeofday(&last_time_);
  312.     true_index_ = 0;
  313.     return current_index_ = 0;
  314. }
  315.  
  316. bool
  317. BPTrendDriver::CorrectDown()
  318. {
  319. #ifdef TIMESTAMP
  320. static TrackedEvent bp_corrected_down_event (TrackedEvent::SystemEvent, 25,
  321.             "High blood pressure corrected");
  322. #endif    // TIMESTAMP
  323.     if (threshold_cross_index_) {    // Threshold not crossed yet.
  324.         // ADD: timestamp false correction.
  325.         return false;
  326.     } else if (data_list[current_index_] < data_range_.high_threshold_value) {
  327.         // ADD: timestamp correcting in wrong direction.
  328.         return false;
  329.     }
  330. #ifdef TIMESTAMP
  331.     // Timestamp the correction in the system
  332.     TimestampedEvent::AddEvent(&bp_corrected_down_event);
  333. #endif    // TIMESTAMP
  334.  
  335.     // Reset the BP trend.
  336.     Reset();
  337.  
  338.     return true;
  339. }
  340.  
  341. bool
  342. BPTrendDriver::CorrectUp()
  343. {
  344. #ifdef TIMESTAMP
  345. static TrackedEvent bp_corrected_up_event (TrackedEvent::SystemEvent, 25,
  346.             "Low blood pressure corrected");
  347. #endif    // TIMESTAMP
  348.  
  349.     if (threshold_cross_index_) {    // Threshold not crossed yet.
  350.         // ADD: timestamp false correction.
  351.         return false;
  352.     } else if (data_list[current_index_] > data_range_.low_threshold_value) {
  353.         // ADD: timestamp correcting in wrong direction.
  354.         return false;
  355.     }
  356.  
  357. #ifdef TIMESTAMP
  358.     // Timestamp the correction in the system
  359.     TimestampedEvent::AddEvent(&bp_corrected_up_event);
  360. #endif    // TIMESTAMP
  361.  
  362.     // Reset the BP trend.
  363.     Reset();
  364.  
  365.     return true;
  366. }
  367.  
  368. /////////////////////////////////////////////////////////////////////////////
  369. // Events
  370.  
  371. void BPTrendDataUpdateEvent::Test()
  372. {
  373.     InvokeHandlers(0);
  374. }
  375.  
  376.