// Returns a new CubicSpline setting array lengths to n and all array values to zero with natural spline default // Primarily for use in BiCubicSpline public virtual CubicSpline zero(int n) { if (n < 3) throw new System.ArgumentException("A minimum of three data points is needed"); CubicSpline aa = new CubicSpline(n); return aa; }
// Create a one dimensional array of cubic spline objects of length n each of array length m // Primarily for use in BiCubicSpline public virtual CubicSpline[] oneDarray(int n, int m) { if (m < 3) throw new System.ArgumentException("A minimum of three data points is needed"); CubicSpline[] a = new CubicSpline[n]; for (int i = 0; i < n; i++) { a[i] = zero(m); } return a; }
public static bool GenerateFeatureVector(double lastTimeStamp) { // Generate a feature vector only, if the next window end has // passed based on the configuration parameters (window size and overlap) // otherwise return false if (lastTimeStamp < Extractor.next_window_end) return false; // the last time stamp is more than the next expected window end // At this point, we have a complete window ready for feature calculation //compute the boundaries for the current window double window_start_time = lastTimeStamp - Extractor.dconfiguration.WindowTime; double window_end_time = lastTimeStamp; double current_time = window_end_time; //compute the end of the next overlapping window next_window_end = window_end_time + (Extractor.dconfiguration.WindowTime * Extractor.dconfiguration.WindowOverlap); #region sensors window grabbing and interpolation // Go through each sensor and extract the collected data within // the current time window for (int j = 0; (j < Extractor.extractorSensorCount); j++) { // Check that the previous sensor in the loop did not report // deteriorated quality for its data #region sensors window quality if (isAcceptableLossRate == false) break; // check if earlier axes reported excessive consecutive loss of data frames if (isAcceptableConsecutiveLoss == false) { Extractor.discardedConsecutiveLossWindows++; break; } #endregion sensors window quality // determine the base index for the current sensor in data array, each sensor has 4 rows (x,y,z,timestamp) int sensor_index = j * 4; int time_index = sensor_index + 3; // determine the last read data sample for the current sensor // by looking at its index int last_sample = 0; if (y_index[j] == 0) last_sample = Extractor.EXPECTED_WINDOW_SIZES[j] - 1; else last_sample = y_index[j] - 1; // int total_data_points = 0, distinct_data_points = 0; int distinct_data_points = 0; //Grab the readings for each axis of a sensor and smoothen it #region sensor window grabbing and interpolation // Go through each axis of the current sensor and smooth // it using the cubic spline for (int axes_num = 0; (axes_num < 3); axes_num++) { //calculate the exact index based on the // base sensor index and the axis number int axes_index = sensor_index + axes_num; //for data array int interpolated_axes_index = j * 3 + axes_num; //for interpolated data array // create 2 arrays to store x and y values for the cubic spline // it is sufficient to have an array of expected sampling rate window size // for 3 mites that would be 180/60 double[] xvals = new double[Extractor.EXPECTED_WINDOW_SIZES[j]]; double[] yvals = new double[Extractor.EXPECTED_WINDOW_SIZES[j]]; //point to the last sample that was read and get its time int sample_index = last_sample; current_time = data[time_index][sample_index]; //copy samples in the last time window // total_data_points = 0; distinct_data_points = 0; // double previous_time = 0; //Grab the values for a specific sensor axes between //window start and window end #region window grabbing // Start going back from the current time (window end) till the start of the window // without exceeding the expected sampling rate and fill in the data in the signal // value for the axis in yvals and the relative time value from the window start while ((current_time >= window_start_time) && (current_time <= window_end_time) && (distinct_data_points < Extractor.EXPECTED_WINDOW_SIZES[j])) { //some time stamps from the mites are identical // for interpolation that will cause an error // simply take the first value for a time point and ignore the // rest, another strategy would be to average over these values //if (current_time == previous_time) //{ // //Get the time of the previous sample and skip the sample // if (sample_index == 0) // sample_index = EXPECTED_WINDOW_SIZE - 1; // else // sample_index--; // current_time = data[time_index][sample_index]; // total_data_points++; // continue; //} // Quality Control // check the time between consecutive data frames and make sure it does // not exceed maximum_consecutive_loss, do not do that for the first // entry of the window // Not suitable for the phone due to time resolution //if (distinct_data_points > 0) //{ // int consecutive_lost_packets = (int)((previous_time - current_time) / EXPECTED_SAMPLES_SPACING); // if (consecutive_lost_packets > Extractor.dconfiguration.MaximumConsecutiveFrameLoss) // { // Extractor.discardedConsecutiveLossWindows++; // unacceptable_consecutive_window_loss_count++; // isAcceptableConsecutiveLoss = false; // break; // } //} //some time stamps from the mites are identical // for interpolation that will cause an error // simply take the first value for a time point and ignore the // rest, another strategy would be to average over these values // we decided, we will spread them out evenly as long as // no excessive loss is experienced // done down in the code xvals[distinct_data_points] = (int)(current_time - window_start_time); //signal value for the current sample and current axis. yvals[distinct_data_points] = data[axes_index][sample_index]; //Point to the previous sample in the current window if (sample_index == 0) sample_index = Extractor.EXPECTED_WINDOW_SIZES[j] - 1; else sample_index--; //store the previous sample time // previous_time = current_time; //Get the time of the new sample current_time = data[time_index][sample_index]; //Point to the next entry in the interpolation array distinct_data_points++; // total_data_points++; } #endregion window grabbing //Check if the captured window has acceptable loss rate #region window quality checks //Do not proceed if there was excessive consecutive loss of data frames if (isAcceptableConsecutiveLoss == false) break; // all data for a specific sensor axis for the current window are stored // in xvals and yvals // check if the data is admissible for feature calculation according to the following // criteria: // 1- total lost data frames are within the loss rate // 2- the number of consecutive lost packets is within our maximum_consecutive_loss parameter if (distinct_data_points < Extractor.EXPECTED_GOOD_SAMPLING_RATES[j]) //discard this whole window of data { Extractor.discardedLossRateWindows++; isAcceptableLossRate = false; unacceptable_window_count++; break; } #endregion window quality checks //smoothen the axis values and store them in interpolated data array #region window interpolation //create 2 arrays with the exact size of the data points for interpolation double[] admissible_xvals = new double[distinct_data_points]; double[] admissible_yvals = new double[distinct_data_points]; double expectedSpacing = Extractor.dconfiguration.WindowTime / (double)distinct_data_points; double startTime = 0.0; for (int k = 0; (k < distinct_data_points); k++) { admissible_xvals[k] = startTime+k*expectedSpacing;//xvals[distinct_data_points - k - 1]; admissible_yvals[k] = yvals[distinct_data_points - k - 1]; } //if (spacingtws == null) // { // spacingtws = new TextWriter[Extractor.sannotation.Sensors.Count]; // for (int i = 0; (i < Extractor.sannotation.Sensors.Count); i++) // { // spacingtws[i] = new StreamWriter("\\test\\" + "SensorSpacing" + i + ".txt"); // } // } // smooth it using a cubic spline CubicSpline cs= new CubicSpline(admissible_xvals, admissible_yvals); //startval = xvals[distinct_data_points - 1].ToString("00.00"); // shrink or expand the data window using interpolation for (int k = 0; (k < INTERPOLATED_SAMPLING_RATE_PER_WINDOW); k++) { interpolated_data[interpolated_axes_index][k] = cs.interpolate(k * INTERPOLATED_SAMPLES_SPACING); //check that the intrepolated values make sense. //if ((interpolated_data[interpolated_axes_index][k] <= 0) || (interpolated_data[interpolated_axes_index][k] > 1024)) if ((interpolated_data[interpolated_axes_index][k] <= -6000) || (interpolated_data[interpolated_axes_index][k] > 6000)) { // errorFlag = 1; return false; } } #endregion window interpolation } #endregion sensor window grabbing and interpolation //spacingtws[j].WriteLine(startval); } #endregion sensors window grabbing and interpolation //If the data is of acceptable quality, calculate the features #region Calculate Feature Vector if ((isAcceptableLossRate == true) && (isAcceptableConsecutiveLoss == true)) { //Extract the features from the interpolated data //Extractor.Extract(interpolated_data); Extractor.Extract(interpolated_data); //Output the data to the ARFF file // tw.WriteLine(Extractor.toString() + "," + current_activity); //num_feature_windows++; // make sure the values of the features make sense... for example distance can // only be -1024---- or so return true; } else //the window is of poor quality, reinitialize and continue { isAcceptableConsecutiveLoss = true; isAcceptableLossRate = true; //errorFlag = 2; return false; } #endregion Calculate Feature Vector }