Exemplo n.º 1
0
        public static void toARFF(string aDataDirectory, string masterDirectory, int maxControllers, string sourceFile, int annotators,string[] filter)
        {
            int featureVectorIndex = 0;
            MITesDecoder aMITesDecoder = new MITesDecoder();
            MITesLoggerReader aMITesLoggerReader = new MITesLoggerReader(aMITesDecoder, aDataDirectory);           
            SXML.SensorAnnotation sannotation = null;
            MITesFeatures.core.conf.GeneralConfiguration configuration = null;

            AXML.Annotation[] aannotation = new AXML.Annotation[annotators];
            AXML.Reader[] readers=new AXML.Reader[annotators];
            AXML.Annotation intersection = null;
            AXML.Annotation[] difference = new AXML.Annotation[annotators];
            AXML.Annotation realtimeAnnotation = new AXML.Reader(masterDirectory, aDataDirectory).parse();
            realtimeAnnotation.RemoveData(filter);



            for (int i = 0; (i < annotators); i++)
            {
                readers[i] = new AXML.Reader(masterDirectory, aDataDirectory, sourceFile + i + ".xml");
                aannotation[i] = readers[i].parse();
                aannotation[i].RemoveData(filter);
                aannotation[i].DataDirectory = aDataDirectory;
                if (intersection == null)
                    intersection = aannotation[i];
                else
                    intersection = intersection.Intersect(aannotation[i]);
            }

    
            for (int i = 0; (i < annotators); i++)            
                difference[i] = aannotation[i].Difference(intersection);

            


            SXML.Reader sreader = new SXML.Reader(masterDirectory, aDataDirectory);           
            sannotation = sreader.parse(maxControllers);

            MITesFeatures.core.conf.ConfigurationReader creader = new MITesFeatures.core.conf.ConfigurationReader(aDataDirectory);
            configuration = creader.parse();
  
            Extractor.Initialize(aMITesDecoder, aDataDirectory, aannotation[0], sannotation,configuration);
            

            TextWriter tw = new StreamWriter(aDataDirectory + "\\output-"+sourceFile+".arff");
            tw.WriteLine("@RELATION wockets");
            tw.WriteLine(Extractor.GetArffHeader());


            tw.WriteLine("@ATTRIBUTE INDEX NUMERIC");
            tw.WriteLine("@ATTRIBUTE ANNOTATORS_AGREE NUMERIC");
            
            Hashtable recorded_activities = new Hashtable();
            for (int k = 0; (k < annotators); k++)
            {
                //tw.Write("@ATTRIBUTE annotator"+k+" {unknown");
                //tw.Write("@ATTRIBUTE annotator" + k + " {");
                
                for (int i = 0; (i < aannotation[k].Data.Count); i++)
                {
                    AXML.AnnotatedRecord record = ((AXML.AnnotatedRecord)aannotation[k].Data[i]);
                    string activity = "";
                    for (int j = 0; (j < record.Labels.Count); j++)
                    {
                        if (j == record.Labels.Count - 1)
                            activity += ((AXML.Label)record.Labels[j]).Name;
                        else
                            activity += ((AXML.Label)record.Labels[j]).Name + "_";
                    }
                    activity = activity.Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                    activity = Regex.Replace(activity, "[_]+", "_");
                    activity = Regex.Replace(activity, "^[_]+", "");
                    activity = Regex.Replace(activity, "[_]+$", "");
                    //only output activity labels that have not been seen
                    if (recorded_activities.Contains(activity) == false)
                    {
                        //tw.Write("," + activity);
                        recorded_activities[activity] = activity;
                    }
                }
                
            }


            for (int k = 0; (k < annotators); k++)
            {
                tw.Write("@ATTRIBUTE annotator" + k + " {unknown,flapping,rocking,flaprock}\n");
                //foreach ( DictionaryEntry de in recorded_activities )
                 //   tw.Write("," + (string) de.Key); 
                //tw.WriteLine("}");
            }

            tw.Write("@ATTRIBUTE realtime {unknown,flapping,rocking,flaprock}\n");
            //foreach (DictionaryEntry de in recorded_activities)
             //   tw.Write("," + (string)de.Key);
            //tw.WriteLine("}");

            tw.WriteLine("@DATA");

            bool isData = aMITesLoggerReader.GetSensorData(10);
            int channel = 0, x = 0, y = 0, z = 0;
            double unixtimestamp = 0.0;

            int[] differenceIndex = new int[annotators];
            AXML.AnnotatedRecord[] annotatedRecord = new AXML.AnnotatedRecord[annotators];
            int intersectionIndex = 0;
            string intersection_activity = "unknown";
            AXML.AnnotatedRecord intersectionRecord = ((AXML.AnnotatedRecord)intersection.Data[intersectionIndex]);
            string[] current_activity = new string[annotators];
            string realtime_activity = "unknown";
            int realtimeIndex = 0;
            AXML.AnnotatedRecord realtimeRecord = ((AXML.AnnotatedRecord)realtimeAnnotation.Data[realtimeIndex]);
            for (int i = 0; (i < annotators); i++)
            {
                differenceIndex[i] = 0;
                annotatedRecord[i] = ((AXML.AnnotatedRecord)difference[i].Data[differenceIndex[i]]);
                current_activity[i] = "unknown";
            }
                
                
            do
            {
                //decode the frame
                channel = aMITesDecoder.GetSomeMITesData()[0].channel;
                x = aMITesDecoder.GetSomeMITesData()[0].x;
                y = aMITesDecoder.GetSomeMITesData()[0].y;
                z = aMITesDecoder.GetSomeMITesData()[0].z;
                unixtimestamp = aMITesDecoder.GetSomeMITesData()[0].unixTimeStamp;
                double lastTimeStamp = Extractor.StoreMITesWindow();

                for (int i = 0; (i < annotators); i++)
                {
                    if (unixtimestamp > annotatedRecord[i].EndUnix)
                    {
                        current_activity[i] = "unknown";
                        if (differenceIndex[i] < difference[i].Data.Count - 1)
                        {
                            differenceIndex[i] = differenceIndex[i]+1;
                            annotatedRecord[i] = ((AXML.AnnotatedRecord)difference[i].Data[differenceIndex[i]]);
                        }
                    }
                }


                if (unixtimestamp > realtimeRecord.EndUnix)
                {
                    realtime_activity = "unknown";
                    realtimeIndex++;
                    if (realtimeIndex < realtimeAnnotation.Data.Count)                                            
                        realtimeRecord = ((AXML.AnnotatedRecord)realtimeAnnotation.Data[realtimeIndex]);                    
                }


                if (unixtimestamp > intersectionRecord.EndUnix)
                {
               
                    intersection_activity = "unknown";
                    if (intersectionIndex < intersection.Data.Count - 1)
                    {
                        intersectionIndex = intersectionIndex + 1;
                        intersectionRecord = ((AXML.AnnotatedRecord)intersection.Data[intersectionIndex]);
                    }
                }

                for (int i = 0; (i < annotators); i++)
                {
                    if ((lastTimeStamp >= annotatedRecord[i].StartUnix) &&
                         (lastTimeStamp <= annotatedRecord[i].EndUnix) && current_activity[i].Equals("unknown"))
                    {
                        current_activity[i] = "";
                        for (int j = 0; (j < annotatedRecord[i].Labels.Count); j++)
                        {
                            if (j == annotatedRecord[i].Labels.Count - 1)
                                current_activity[i] += ((AXML.Label)annotatedRecord[i].Labels[j]).Name;
                            else
                                current_activity[i] += ((AXML.Label)annotatedRecord[i].Labels[j]).Name + "_";
                        }
                        current_activity[i] = current_activity[i].Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                        current_activity[i] = Regex.Replace(current_activity[i], "[_]+", "_");
                        current_activity[i] = Regex.Replace(current_activity[i], "^[_]+", "");
                        current_activity[i] = Regex.Replace(current_activity[i], "[_]+$", "");
                    }
                    else if (lastTimeStamp > annotatedRecord[i].EndUnix)
                        current_activity[i] = "unknown";
                 
                }

                if ((lastTimeStamp >= realtimeRecord.StartUnix) &&
                       (lastTimeStamp <= realtimeRecord.EndUnix) && realtime_activity.Equals("unknown"))
                {
                    realtime_activity = "";
                    for (int j = 0; (j < realtimeRecord.Labels.Count); j++)
                    {
                        if (j == realtimeRecord.Labels.Count - 1)
                            realtime_activity += ((AXML.Label)realtimeRecord.Labels[j]).Name;
                        else
                            realtime_activity += ((AXML.Label)realtimeRecord.Labels[j]).Name + "_";
                    }
                    realtime_activity = realtime_activity.Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                    realtime_activity = Regex.Replace(realtime_activity, "[_]+", "_");
                    realtime_activity = Regex.Replace(realtime_activity, "^[_]+", "");
                    realtime_activity = Regex.Replace(realtime_activity, "[_]+$", "");
                }
                else if (lastTimeStamp > realtimeRecord.EndUnix)
                    realtime_activity = "unknown";



                if ((lastTimeStamp >= intersectionRecord.StartUnix) &&
                     (lastTimeStamp <= intersectionRecord.EndUnix) && intersection_activity.Equals("unknown"))
                {
                    intersection_activity = "";
                    for (int j = 0; (j < intersectionRecord.Labels.Count); j++)
                    {
                        if (j == intersectionRecord.Labels.Count - 1)
                            intersection_activity += ((AXML.Label)intersectionRecord.Labels[j]).Name;
                        else
                            intersection_activity += ((AXML.Label)intersectionRecord.Labels[j]).Name + "_";
                    }
                    intersection_activity = intersection_activity.Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                    intersection_activity = Regex.Replace(intersection_activity, "[_]+", "_");
                    intersection_activity = Regex.Replace(intersection_activity, "^[_]+", "");
                    intersection_activity = Regex.Replace(intersection_activity, "[_]+$", "");
                }
              


                if ((Extractor.GenerateFeatureVector(lastTimeStamp)))
                {

                    string activity_suffix = "," + featureVectorIndex;
                

                    if (intersection_activity.Equals("unknown") == true) //disagreement or agreement unknown
                    {
                        

                        if ((current_activity[0] == "unknown") && (current_activity[1] == "unknown"))
                            activity_suffix += ",1";
                        else
                            activity_suffix += ",0";
                        for (int i = 0; (i < annotators); i++)
                            activity_suffix += "," + current_activity[i];
                    }
                    else
                    {
                        activity_suffix += ",1";
                        for (int i = 0; (i < annotators); i++)
                            activity_suffix += "," + intersection_activity;
                    }
                    
                    string arffSample = Extractor.toString() + activity_suffix;
                    //if (activity_suffix.Contains("unknown") == false)
                    //{
                        tw.WriteLine(arffSample+","+realtime_activity);
                        featureVectorIndex++;
                    //}
                  

                }
               

            } while (isData = aMITesLoggerReader.GetSensorData(10));

            tw.Close();
        }
Exemplo n.º 2
0
        private void MITesSenderThread()
        {
            MITesDecoder aMITesDecoder = new MITesDecoder();
            MITesLoggerReader aMITesLoggerReader = new MITesLoggerReader(aMITesDecoder, MITES_SAMPLE_DIRECTORY);
            MITesData data = new MITesData();
            double UnixTime = ((TimeSpan)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)))).TotalMilliseconds;
            //double difference=0;
            double previousTime=0;
            Random random = new Random();
            int bytePerSecond = 0;
            int samplesPerSecond=0;
            DateTime previousDateTime=DateTime.Now;
            bool workingBT=false;


            while (true)
            {
                //Thread.Sleep(1000);
                if (BluetoothConnection.IsOpen)
                {
                    try
                    {
       

                        if (startTransmission)
                        {
                            bool isData = aMITesLoggerReader.GetSensorData(10);
                            int channel = 0, x = 0, y = 0, z = 0;
                            double unixtimestamp = 0.0;
                            double lasttime = 0.0;
                            byte[] rawSample = aMITesDecoder.GetSomeMITesData()[0].rawBytes;

                            do
                            {
                                //decode the frame

                                if (realistic == false)
                                {
                                    //Thread.Sleep(gapmillseconds);
                                    if (rawSample[0] == 4)
                                        rawSample[0] = 8;
                                    else
                                        rawSample[0] = 4;

                                    rawSample[1] = (byte)random.Next(256);
                                    rawSample[2] = (byte)random.Next(256);
                                    rawSample[3] = (byte)random.Next(256);
                                    
                                    //BluetoothConnection.Write(rawSample, 0, 5);
                                    samplesPerSecond++;
                                    if ((samplesPerSecond % 5)==0)                 
                                        BluetoothConnection.Write(mitesData, 0, 2);
                                    else
                                        BluetoothConnection.Write(rawSample, 0, 5);
                                    workingBT = true;
                                }
                                else if ((int)previousTime != 0)
                                {
                                    channel = aMITesDecoder.GetSomeMITesData()[0].channel;
                                    x = aMITesDecoder.GetSomeMITesData()[0].x;
                                    y = aMITesDecoder.GetSomeMITesData()[0].y;
                                    z = aMITesDecoder.GetSomeMITesData()[0].z;
                                    unixtimestamp = aMITesDecoder.GetSomeMITesData()[0].unixTimeStamp;
                                    Thread.Sleep((int)previousTime);
                                    previousTime = unixtimestamp;

                                    if (channel != 83)
                                        BluetoothConnection.Write(aMITesDecoder.GetSomeMITesData()[0].rawBytes, 0, 5);
                                }

                                double seconds = ((TimeSpan)(DateTime.Now - previousDateTime)).TotalSeconds;
                                if (seconds > 5)
                                {
                                    sps = ((int)(samplesPerSecond / 5)).ToString();
                                    bps = ((int)(samplesPerSecond * 5)).ToString();
                                    samplesPerSecond = 0;
                                    previousDateTime = DateTime.Now;
                                }

                            } while ((realistic == false));//|| (isData = aMITesLoggerReader.GetSensorData(10)));
                            BluetoothConnection.Close();
                            Application.Exit();
                        }
                        else
                        {
                            //2 sync bytes
                            BluetoothConnection.Write(mitesData, 0, 2);
                            //Thread.Sleep(5);
                        }
                            
                      

                        /*else
                        {
                            int startTime = (int)((TimeSpan)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)))).TotalSeconds;                             
                            do
                            {
                                Thread.Sleep(gapmillseconds);
                                
                                //decode the frame
                                if (data.channel == 4)
                                    data.channel = 8;
                                else
                                    data.channel = 4;
                                data.x = (short)random.Next(1000);
                                data.y = (short)random.Next(1000);
                                data.z = (short)random.Next(1000);
                                data.unixTimeStamp = ((TimeSpan)(DateTime.UtcNow.Subtract(new DateTime(1970, 1,1)))).TotalMilliseconds;
                                data.ResetRawVals();
                                if (channel != 83)
                                    BluetoothConnection.Write(aMITesDecoder.GetSomeMITesData()[0].rawBytes, 0, 5);
                                int currentTime = (int) ((TimeSpan)(DateTime.UtcNow.Subtract(new DateTime(1970, 1,1)))).TotalSeconds;                                
                            } while (currentTime<(startTime+totalSeconds));

                        }*/

                        
                    }
                    catch (Exception e)
                    {
                        samplesPerSecond = 0;
                        if (workingBT == true) //only reset if BT was already working
                        {
                            BluetoothConnection.Close();
                            BluetoothConnection = new SerialPort();
                            this.BluetoothConnection.PortName = INCOMING_PORT;
                            BluetoothConnection.WriteTimeout = 1000;
                            BluetoothConnection.StopBits = StopBits.One;
                            BluetoothConnection.BaudRate = 57600;
                            BluetoothConnection.Parity = Parity.None;
                            //BluetoothConnection.
                            BluetoothConnection.Open();
                            workingBT = false;
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        public static void toARFF2(string aDataDirectory, string masterDirectory, int maxControllers)
        {
            MITesDecoder aMITesDecoder = new MITesDecoder();
            MITesLoggerReader aMITesLoggerReader = new MITesLoggerReader(aMITesDecoder, aDataDirectory);
            AXML.Annotation aannotation = null;
            SXML.SensorAnnotation sannotation = null;
            Hashtable calibrations = null;
            AXML.Reader reader = new AXML.Reader(masterDirectory, aDataDirectory,"AnnotationIntervals.xml");
            aannotation = reader.parse();
            aannotation.DataDirectory = aDataDirectory;
            SXML.Reader sreader = new SXML.Reader(masterDirectory, aDataDirectory);             
            sannotation = sreader.parse(maxControllers);
            SOXML.Reader calreader = new SOXML.Reader(aDataDirectory);
            calibrations = calreader.parse();
            Extractor.Initialize2(aMITesDecoder, aDataDirectory, aannotation, sannotation,calibrations);

            TextWriter tw = new StreamWriter(aDataDirectory + "\\output2.arff");
            tw.WriteLine("@RELATION wockets");
            tw.WriteLine(Extractor.GetArffHeader2());
            tw.Write("@ATTRIBUTE activity {unknown");
            Hashtable recorded_activities = new Hashtable();
            for (int i = 0; (i < aannotation.Data.Count); i++)
            {
                AXML.AnnotatedRecord record = ((AXML.AnnotatedRecord)aannotation.Data[i]);
                string activity = "";
                for (int j = 0; (j < record.Labels.Count); j++)
                {
                    if (j == record.Labels.Count - 1)
                        activity += ((AXML.Label)record.Labels[j]).Name;
                    else
                        activity += ((AXML.Label)record.Labels[j]).Name + "_";
                }
                activity = activity.Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                activity = Regex.Replace(activity, "[_]+", "_");
                activity = Regex.Replace(activity, "^[_]+", "");
                activity = Regex.Replace(activity, "[_]+$", "");
                //only output activity labels that have not been seen
                if (recorded_activities.Contains(activity) == false)
                {
                    tw.Write("," + activity);
                    recorded_activities[activity] = activity;
                }
            }
            tw.WriteLine("}");
            tw.WriteLine("@DATA");

            bool isData = aMITesLoggerReader.GetSensorData(10);
            int channel = 0, x = 0, y = 0, z = 0;
            double unixtimestamp = 0.0;
            int activityIndex = 0;
            AXML.AnnotatedRecord annotatedRecord = ((AXML.AnnotatedRecord)aannotation.Data[activityIndex]);
            string current_activity = "unknown";
            do
            {
                //decode the frame
                channel = aMITesDecoder.GetSomeMITesData()[0].channel;
                x = aMITesDecoder.GetSomeMITesData()[0].x;
                y = aMITesDecoder.GetSomeMITesData()[0].y;
                z = aMITesDecoder.GetSomeMITesData()[0].z;
                unixtimestamp = aMITesDecoder.GetSomeMITesData()[0].unixTimeStamp;
                double lastTimeStamp = Extractor.StoreMITesWindow();
                //DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0);
                //dt=dt.AddMilliseconds(unixtimestamp);
                //DateTime dt2 = new DateTime(1970, 1, 1, 0, 0, 0, 0);
                //dt2 = dt2.AddMilliseconds(annotatedRecord.EndUnix);
                if (unixtimestamp > annotatedRecord.EndUnix)
                {
                    current_activity = "unknown";
                    if (activityIndex < aannotation.Data.Count - 1)
                    {
                        activityIndex++;
                        annotatedRecord = ((AXML.AnnotatedRecord)aannotation.Data[activityIndex]);
                    }
                }

                if ((lastTimeStamp >= annotatedRecord.StartUnix) &&
                     (lastTimeStamp <= annotatedRecord.EndUnix) && current_activity.Equals("unknown"))
                {
                    current_activity = "";
                    for (int j = 0; (j < annotatedRecord.Labels.Count); j++)
                    {
                        if (j == annotatedRecord.Labels.Count - 1)
                            current_activity += ((AXML.Label)annotatedRecord.Labels[j]).Name;
                        else
                            current_activity += ((AXML.Label)annotatedRecord.Labels[j]).Name + "_";
                    }
                    current_activity = current_activity.Replace("none", "").Replace('-', '_').Replace(':', '_').Replace('%', '_').Replace('/', '_');
                    current_activity = Regex.Replace(current_activity, "[_]+", "_");
                    current_activity = Regex.Replace(current_activity, "^[_]+", "");
                    current_activity = Regex.Replace(current_activity, "[_]+$", "");
                }

                //if (lastTimeStamp>=
                if (current_activity.Equals("unknown") == false)
                {
                    if ((Extractor.GenerateFeatureVector(lastTimeStamp)))
                    {
                        string arffSample = Extractor.toString() + "," + current_activity;
                        tw.WriteLine(arffSample);
                    }
                }

            } while (isData = aMITesLoggerReader.GetSensorData(10));

            tw.Close();
        }
Exemplo n.º 4
0
        public static void toQualityHTML(string aDataDirectory, string masterDirectory, int maxControllers, string[] filter)
        {
            int ACCELEROMETER_STATISTICS_LENGTH = 16;
            //int WOCKETS_SR = 92;
            int MITES_SR = 45;

            if (CSVProgress == "")
                CSVProgress = "Generating Quality Assessment Summary in HTML";

            #region ===================  Load the MITES/Wockets DATA ==============================

            //Calculate Data Gaps
            WocketsController wc = new WocketsController("", "", "");
            CurrentWockets._Controller = wc;
            wc.FromXML(aDataDirectory + "\\" + WOCKETS_SUBDIRECTORY + "\\SensorData.xml");
            if (wc._Decoders.Count > 0)
            {
                for (int r = 0; (r < wc._Decoders.Count); r++)
                    wc._Decoders[r].Initialize();
            }

            SXML.Reader sreader = null;
            SXML.SensorAnnotation sannotation = null;

            try
            {
                //JPN!!!!!
                sreader = new SXML.Reader(masterDirectory, aDataDirectory + "\\" + MITES_SUBDIRECTORY);
                sannotation = sreader.parse(maxControllers);

                //remove the HR sensor
                for (int i = 0; (i < sannotation.Sensors.Count); i++)
                    if ((Convert.ToInt32(((SXML.Sensor)sannotation.Sensors[i]).ID) == 0))
                    {
                        sannotation.Sensors.RemoveAt(i);
                        break;
                    }
            }
            catch
            {
                //if there is not mites data, catch the error and continue
            }

            #endregion

            #region ============== Load Annotation Intervals =======================================

            Session session = new Session();
            session.FromXML(aDataDirectory + "\\" + ANNOTATION_SUBDIRECTORY + "\\" + ANNOTATION_INTERVALS_FILE);
            int numPostures = 0;
            Hashtable postures = new Hashtable();
            int k = 0;

            //Think how to handle this when there are more than one activity type
            Hashtable means_per_class = new Hashtable();
            Hashtable std_per_class = new Hashtable();
            Hashtable freq_per_class = new Hashtable();
            Hashtable min_per_class = new Hashtable();
            Hashtable max_per_class = new Hashtable();

            //Check if the "unknown" class is specified
            bool is_unknown_specified = false;

            //If two categories are available
            if (session.OverlappingActivityLists.Count == 2)
            {
                numPostures = session.OverlappingActivityLists[0].Count * session.OverlappingActivityLists[1].Count + 1;

                //Go through the activity list for the two categories
                //This list will generate all combinations of postures-activities
                for (int i = 0; (i < session.OverlappingActivityLists[1].Count); i++)
                    for (int j = 0; (j < session.OverlappingActivityLists[0].Count); j++)
                    {
                        postures.Add(session.OverlappingActivityLists[1][i]._Name + "_" + session.OverlappingActivityLists[0][j]._Name, k);
                        k++;
                    }
            }
            else if (session.OverlappingActivityLists.Count == 1)
            {

                numPostures = session.OverlappingActivityLists[0].Count + 1;

                //Go through the activity list for the available category
                //This list will simply pass the elements in the category list to the postures data structure
                for (int i = 0; (i < session.OverlappingActivityLists[0].Count); i++)
                {
                    if (session.OverlappingActivityLists[0][i]._Name.CompareTo("unknown") == 0)
                        is_unknown_specified = true;

                    postures.Add(session.OverlappingActivityLists[0][i]._Name, k);
                    k++;

                    //initialize the class stats structure
                    means_per_class.Add(session.OverlappingActivityLists[0][i]._Name, (double)0.0);
                    std_per_class.Add(session.OverlappingActivityLists[0][i]._Name, (double)0.0);
                    freq_per_class.Add(session.OverlappingActivityLists[0][i]._Name, (int)0);
                    min_per_class.Add(session.OverlappingActivityLists[0][i]._Name, (double)10000.0);
                    max_per_class.Add(session.OverlappingActivityLists[0][i]._Name, (double)0.0);
                }

            }
            // TODO if four categories present

            else if (session.OverlappingActivityLists.Count == 4)
            {
                numPostures = session.OverlappingActivityLists[0].Count * session.OverlappingActivityLists[1].Count + 1;

                //Go through the activity list for the two categories
                //This list will generate all combinations of postures-activities
                for (int i = 0; (i < session.OverlappingActivityLists[1].Count); i++)
                    for (int j = 0; (j < session.OverlappingActivityLists[0].Count); j++)
                    {
                        postures.Add(session.OverlappingActivityLists[1][i]._Name + "_" + session.OverlappingActivityLists[0][j]._Name, k);
                        k++;
                    }
            }

            //Check if postures contain the "unknown" label, otherwise add it
            if (!is_unknown_specified)
            {
                postures.Add("unknown", k);

                //initialize the class stats structure
                means_per_class.Add("unknown", (double)0.0);
                std_per_class.Add("unknown", (double)0.0);
                freq_per_class.Add("unknown", (int)0);
                min_per_class.Add("unknown", (double)10000.0);
                max_per_class.Add("unknown", (double)0.0);
            }

            #endregion

            #region  ================= Compute Statistics based on Postures  ===========================

            #region Create Data Structures & Variables

            int[] timeLostPostureSensorCounter = new int[numPostures];
            double[] wocketsSR = new double[wc._Sensors.Count];
            double[] trueWocketsSR = new double[wc._Sensors.Count];
            double[][] modeWocketsSR = new double[wc._Sensors.Count][];

            bool[] disconnected = new bool[wc._Sensors.Count];
            double[] zeroWocketsSR = new double[wc._Sensors.Count];
            int[] numDisconnected = new int[wc._Sensors.Count];
            ArrayList[] disconnectionDistribution = new ArrayList[wc._Sensors.Count];
            int[] disconnectionTimer = new int[wc._Sensors.Count];
            int[] numDisconnections = new int[wc._Sensors.Count];
            int[] meanDisconnection = new int[wc._Sensors.Count];
            int[] sdDisconnection = new int[wc._Sensors.Count];

            int[][] timeLostPostureSensorDistribution = new int[wc._Sensors.Count][];
            int[][] percentLostPostureSensorDistribution = new int[wc._Sensors.Count][];
            int[][] percentLostPostureSensorCounter = new int[wc._Sensors.Count][];

            int mitesCount = 0;
            if (sannotation != null)
                mitesCount = sannotation.Sensors.Count;
            int[] mitesSR = new int[mitesCount];
            int[] trueMitesSR = new int[mitesCount];
            int[][] modeMITesSR = new int[mitesCount][];
            Hashtable annotatedPostures = new Hashtable();

            #endregion

            #region Initialize Variables

            // int[] wocketsCounter = new int[wc._Sensors.Count];
            // int[] mitesCounter = new int[sannotation.Sensors.Count];
            int numSeconds = 0;
            for (int i = 0; (i < mitesCount); i++)
            {
                mitesSR[i] = 0;
                trueMitesSR[i] = 0;
                modeMITesSR[i] = new int[1000];
            }

            int mitesStartIndex = 3 + session.OverlappingActivityLists.Count;
            for (int i = 0; (i < wc._Sensors.Count); i++)
            {
                wocketsSR[i] = 0;
                trueWocketsSR[i] = 0;
                modeWocketsSR[i] = new double[1000];
                disconnected[i] = false;
                disconnectionDistribution[i] = new ArrayList();
                disconnectionTimer[i] = 0;
                timeLostPostureSensorDistribution[i] = new int[numPostures];
                percentLostPostureSensorDistribution[i] = new int[numPostures];
                //timeLostPostureSensorCounter[i] = new int[numPostures];
            }

            int wocketsStartIndex = mitesStartIndex + (ACCELEROMETER_STATISTICS_LENGTH * mitesCount);

            //no heart mites rate
            if (mitesCount == 0)
                wocketsStartIndex = wocketsStartIndex - 1;

            #endregion

            #region Initialize Annotations & Compute Descripte Statistics

            int numCategories = session.OverlappingActivityLists.Count;
            int currentAnnotation = 0;

            //Get the number of annotations
            int annotationsLength = session.Annotations.Count;

            //Get the overall session time
            double startTime = session.Annotations[0]._StartUnix;
            double endTime = session.Annotations[annotationsLength - 1]._EndUnix;

            string name = "";
            double duration_secs = 0.0;

            //Scan annotations and compute the duration min/max stats
            try
            {
                for (int c1 = 0; c1 < annotationsLength; c1++)
                {
                    name = session.Annotations[c1].Activities[0]._Name;
                    freq_per_class[name] = ((int)freq_per_class[name]) + 1;

                    //compute the duration of the label
                    duration_secs = (session.Annotations[c1]._EndUnix - session.Annotations[c1]._StartUnix) / 1000;

                    means_per_class[name] = ((double)means_per_class[name]) + duration_secs;

                    if (duration_secs < ((double)min_per_class[name]))
                        min_per_class[name] = duration_secs;

                    if (duration_secs > ((double)max_per_class[name]))
                        max_per_class[name] = duration_secs;
                }

                //compute the mean for each class
                for (int c2 = 0; c2 < means_per_class.Count; c2++)
                {
                    if (c2 < session.OverlappingActivityLists[0].Count)
                    {
                        name = session.OverlappingActivityLists[0][c2]._Name;
                        means_per_class[name] = ((double)means_per_class[name]) / ((int)freq_per_class[name]);
                    }
                }

                //Compute the standard deviation of durations for each class
                for (int c3 = 0; c3 < annotationsLength; c3++)
                {
                    name = session.Annotations[c3].Activities[0]._Name;

                    //compute the duration of the label
                    duration_secs = (session.Annotations[c3]._EndUnix - session.Annotations[c3]._StartUnix) / 1000;

                    std_per_class[name] = ((double)std_per_class[name]) + Math.Pow((duration_secs - ((double)means_per_class[name])), 2.0);
                }

                for (int c4 = 0; c4 < means_per_class.Count; c4++)
                {
                    if (c4 < session.OverlappingActivityLists[0].Count)
                    {
                        name = session.OverlappingActivityLists[0][c4]._Name;
                        std_per_class[name] = Math.Sqrt(((double)std_per_class[name]) / ((int)freq_per_class[name]));
                    }
                }

            }
            catch
            {  //The computation of the descriptive stats of annotations has failed
            }

            #endregion

            #region Open the Summary CSV File

            TextReader tr = new StreamReader(aDataDirectory + "\\" + MERGED_SUBDIRECTORY + "\\MITesSummaryData.csv");
            string line = "";
            tr.ReadLine();

            #endregion

            //Scan the Annotation Intervals and Summary File to Access the Sensors Statistics
            while ((line = tr.ReadLine()) != null)
            {

                //Read Line of Summary File (Sensor Reading)
                string[] tokens = line.Split(',');
                double currentTime = Convert.ToDouble(tokens[0]);
                string posture = tokens[2];
                string current_posture = "unknown";

                #region Determine if the sensor reading is within the annotation interval & compute its metrics

                try
                {

                    // If the sensor reading happens after the end of the annotation interval,
                    // advance to the next annotation
                    if ((currentAnnotation < session.Annotations.Count - 1) &&
                          (session.Annotations[currentAnnotation]._EndUnix < currentTime))
                        currentAnnotation++;

                    // If the sensor reading happens within the annotation interval,
                    // proceed to compute the metrics
                    if ((currentTime >= session.Annotations[currentAnnotation]._StartUnix) &&
                        (currentTime <= session.Annotations[currentAnnotation]._EndUnix))
                    {

                        #region Get the Label Name, Add it to the Hash Table, and Add the Annotated Seconds

                        // If we have more than one category,
                        // make the check for the second category (activities)
                        if (session.Annotations[currentAnnotation].Activities.Count > 1)
                        {
                            //If it is NOT a valid label, replace it for "unknown"
                            if ((session.Annotations[currentAnnotation].Activities[1]._Name == "none") ||
                                (session.Annotations[currentAnnotation].Activities[1]._Name == "") ||
                                (session.Annotations[currentAnnotation].Activities[1]._Name == "-"))
                                session.Annotations[currentAnnotation].Activities[1]._Name = "unknown";
                        }

                        //Make the check for all the first category (postures)
                        if ((session.Annotations[currentAnnotation].Activities[0]._Name == "none") ||
                            (session.Annotations[currentAnnotation].Activities[0]._Name == "") ||
                            (session.Annotations[currentAnnotation].Activities[0]._Name == "-"))
                            session.Annotations[currentAnnotation].Activities[0]._Name = "unknown";

                        //Get the name of the annotation label
                        if (session.Annotations[currentAnnotation].Activities.Count > 1)
                            current_posture = session.Annotations[currentAnnotation].Activities[1]._Name + "_" + session.Annotations[currentAnnotation].Activities[0]._Name;
                        else
                            current_posture = session.Annotations[currentAnnotation].Activities[0]._Name;

                        // Search in the hash table the name of the current label,
                        // If it doesn't exists, add it to the list of annotated postures
                        // If it exists, add the number of seconds in the annotation
                        if (!annotatedPostures.ContainsKey(current_posture))
                            annotatedPostures.Add(current_posture, 1);
                        else
                        {
                            int annotatedSeconds = (int)annotatedPostures[current_posture] + 1;
                            annotatedPostures[current_posture] = annotatedSeconds;
                        }

                        #endregion

                    }

                    #region  Calculate quality metrics on data that has been annotated only

                    //If the sensor reading falls within the start-end of the session
                    if ((currentTime >= startTime) && (currentTime <= endTime))
                    {
                        #region Calculate Metrics

                        #region  mites SR

                        for (int i = 0; (i < mitesCount); i++)
                        {
                            int sr = Convert.ToInt32(tokens[mitesStartIndex + (ACCELEROMETER_STATISTICS_LENGTH * i)]);
                            mitesSR[i] += sr;
                            modeMITesSR[i][sr] = modeMITesSR[i][sr] + 1;
                        }

                        #endregion

                        #region  The number of seconds in a particular posture (adds to the global counter)

                        int currentPostureIndex = 0;
                        currentPostureIndex = (int)postures[current_posture];
                        timeLostPostureSensorCounter[currentPostureIndex] = timeLostPostureSensorCounter[currentPostureIndex] + 1;

                        #endregion

                        #region  wockets SR

                        for (int i = 0; (i < wc._Sensors.Count); i++)
                        {

                            //Compute Wockets Sampling Rate
                            int sr = 0;
                            try
                            {
                                sr = Convert.ToInt32(tokens[wocketsStartIndex + (ACCELEROMETER_STATISTICS_LENGTH * i)]);
                                wocketsSR[i] += sr;
                                modeWocketsSR[i][sr] = modeWocketsSR[i][sr] + 1;
                            }
                            catch (Exception e)
                            {
                            }

                            //Add the samples collected per activity
                            timeLostPostureSensorDistribution[i][currentPostureIndex] = timeLostPostureSensorDistribution[i][currentPostureIndex] + sr;

                            //Compute the number of disconnections
                            if (sr == 0)
                            {
                                zeroWocketsSR[i] = zeroWocketsSR[i] + 1;
                                if (zeroWocketsSR[i] == 5)
                                {
                                    disconnected[i] = true;
                                    numDisconnected[i] = numDisconnected[i] + 1;
                                }
                                disconnectionTimer[i]++;
                            }
                            else
                            {
                                if (disconnectionTimer[i] >= 5)
                                    disconnectionDistribution[i].Add(disconnectionTimer[i]);
                                zeroWocketsSR[i] = 0;
                                disconnected[i] = false;
                                disconnectionTimer[i] = 0;
                            }
                        }

                        #endregion

                        numSeconds++;

                        #endregion

                    } //end of the if

                    #endregion

                }//end of try
                catch (Exception e)
                {
                    //Launch exception when there is a index mistmatch in the ActivityIntervals.xml file
                }

                #endregion

            }//end of while

            #region  Calculate time lost, % data lost, burstiness

            #region Wockets Loss Calculation

            //The total session duration
            int totalSeconds = (int)((endTime - startTime) / 1000.0);

            //initialize variables
            int expectedMITesSamples = MITES_SR * totalSeconds;
            int[] wocketsSecondsLost = new int[wc._Sensors.Count];
            int[] mitesSecondsLost = new int[mitesCount];
            int[] wocketsPercentLost = new int[wc._Sensors.Count];
            int[] mitesPercentLost = new int[mitesCount];

            //Compute Loss Based on Sampling Rate and Number of Samples
            for (int i = 0; (i < wc._Sensors.Count); i++)
            {
                int expectedWocketsSamples = wc._Sensors[i]._SamplingRate * totalSeconds;
                if (wocketsSR[i] < expectedWocketsSamples)
                {
                    wocketsSecondsLost[i] = (int)Math.Ceiling((double)(expectedWocketsSamples - wocketsSR[i]) / wc._Sensors[i]._SamplingRate);
                    wocketsPercentLost[i] = (int)(((double)wocketsSecondsLost[i] / (double)totalSeconds) * 100.0);
                }

                if (disconnectionTimer[i] >= 5)
                    disconnectionDistribution[i].Add(disconnectionTimer[i]);

            }

            #endregion Wockets Loss Calculation

            #region Wockets per Activity Loss Calculation

            //Scan through the list of annotated postures
            for (int i = 0; (i < timeLostPostureSensorCounter.Length); i++)
            {

                //Scan through the list of sensors
                for (int j = 0; (j < wc._Sensors.Count); j++)
                {

                    //expected samples
                    int expectedWocketsSamples = wc._Sensors[j]._SamplingRate * timeLostPostureSensorCounter[i];

                    //compute loss
                    if (timeLostPostureSensorDistribution[j][i] < expectedWocketsSamples)
                    {
                        timeLostPostureSensorDistribution[j][i] = (int)Math.Floor((expectedWocketsSamples - timeLostPostureSensorDistribution[j][i]) / (double)wc._Sensors[j]._SamplingRate);
                        percentLostPostureSensorDistribution[j][i] = (int)Math.Floor((((double)timeLostPostureSensorDistribution[j][i] / (double)timeLostPostureSensorCounter[i]) * 100.0));
                    }
                    else
                    {
                        timeLostPostureSensorDistribution[j][i] = 0;
                        percentLostPostureSensorDistribution[j][i] = 0;
                    }

                }

            }

            #endregion Wockets per Activity Loss Calculation

            #region MEAN and SD Calculation

            //Iterate through sensors
            for (int i = 0; (i < wc._Sensors.Count); i++)
            {
                numDisconnections[i] = disconnectionDistribution[i].Count;
                meanDisconnection[i] = 0;

                for (int j = 0; (j < disconnectionDistribution[i].Count); j++)
                    meanDisconnection[i] = meanDisconnection[i] + (int)disconnectionDistribution[i][j];

                if (numDisconnections[i] > 0)
                    meanDisconnection[i] = (meanDisconnection[i] - 1) / numDisconnections[i];

                for (int j = 0; (j < disconnectionDistribution[i].Count); j++)
                    sdDisconnection[i] = sdDisconnection[i] + (int)Math.Pow(((double)(int)disconnectionDistribution[i][j] - meanDisconnection[i]), 2.0);

                if (disconnectionDistribution[i].Count > 1)
                    sdDisconnection[i] = (int)Math.Sqrt(sdDisconnection[i] / (disconnectionDistribution[i].Count - 1));
                else
                    sdDisconnection[i] = -1;

            }

            #endregion MEAN and SD Calculation

            #region MITes Loss Calculation

            for (int i = 0; (i < mitesCount); i++)
            {
                if (mitesSR[i] < expectedMITesSamples)
                    mitesSecondsLost[i] = (expectedMITesSamples - mitesSR[i]) / MITES_SR;

                mitesPercentLost[i] = (int)(((double)mitesSecondsLost[i] / (double)totalSeconds) * 100.0);
            }

            #endregion MITes Loss Calculation

            tr.Close();

            #region Percent Maxedout MITES

            int[] mitesMaxedOut = null;

            if (sannotation != null)
                mitesMaxedOut = new int[sannotation.MaximumSensorID + 1];

            int[] mitesSamplesCount = null;

            if (sannotation != null)
                mitesSamplesCount = new int[sannotation.MaximumSensorID + 1];

            try
            {
                MITesDecoder aMITesDecoder = new MITesDecoder();
                MITesLoggerReader aMITesLoggerReader = new MITesLoggerReader(aMITesDecoder, aDataDirectory + "\\" + MITES_SUBDIRECTORY);
                bool isData = true;
                do
                {
                    //decode the frame
                    int i = aMITesDecoder.GetSomeMITesData()[0].channel;
                    int x = aMITesDecoder.GetSomeMITesData()[0].x;
                    int y = aMITesDecoder.GetSomeMITesData()[0].y;
                    int z = aMITesDecoder.GetSomeMITesData()[0].z;
                    mitesSamplesCount[i] = mitesSamplesCount[i] + 1;
                    if ((x >= 1023) || (y >= 1023) || (z >= 1023))
                        mitesMaxedOut[i] = mitesMaxedOut[i] + 1;

                } while (isData = aMITesLoggerReader.GetSensorData(10));
            }
            catch
            {
            }

            #endregion

            #region Percent Maxed Out Wockets

            int[] maxedOut = new int[wc._Sensors.Count];
            int[] samplesCount = new int[wc._Sensors.Count];

            for (int i = 0; (i < wc._Sensors.Count); i++)
            {

                wc._Sensors[i]._RootStorageDirectory = aDataDirectory + "\\" + WOCKETS_SUBDIRECTORY + "\\data\\raw\\PLFormat\\";
                try
                {

                    int lastDecodedIndex = 0;

                    while (wc._Sensors[i].Load())
                    {

                        samplesCount[i] = samplesCount[i] + 1;

                        if (wc._Sensors[i]._Decoder._Head == 0)
                            lastDecodedIndex = wc._Sensors[i]._Decoder._Data.Length - 1;
                        else
                            lastDecodedIndex = wc._Sensors[i]._Decoder._Head - 1;

                        Wockets.Data.Accelerometers.AccelerationData data = (Wockets.Data.Accelerometers.AccelerationData)wc._Sensors[i]._Decoder._Data[lastDecodedIndex];

                        if ((data._X >= 1023) || (data._Y >= 1023) || (data._Z >= 1023))
                            maxedOut[i] = maxedOut[i] + 1;

                    }
                }
                catch (Exception e)
                {
                }

            }

            #endregion Percent Maxed Out Wockets

            #region Write Results to HTML

            string summary = "<h3><Font Color=#585858>MITes and Wockets Data Loss, Disconnections and Maxing out Statistics </Font></h3><TABLE border=\"1\">\n";
            int numRows = wc._Sensors.Count - 1 + mitesCount;
            string[] rows = new string[numRows];
            string header = "<TR>\n";

            string[] hlabels = new string[] { "Placement\\Metric", "Data Loss (seconds)", "% Data Loss", "Num Disconnections", "Mean Disconnection (seconds)", "SD Disconnection (seconds)", "Num Maxed Out", "% Maxed Out" };

            for (int i = 0; (i < hlabels.Length); i++)
                header += "<TD><div align=\"center\"><strong>" + hlabels[i] + "</strong></div></TD>\n";

            header += "</TR>\n";
            summary += header;

            #region Statistics Table for MITES

            for (int i = 0; (i < mitesCount); i++)
            {

                string row = "<TR>\n";
                row += "<TD><div align=\"center\"><strong>MITes " + ((SXML.Sensor)sannotation.Sensors[i]).Location + "</strong></div></TD>\n";

                if (mitesPercentLost[i] >= 20)
                {
                    row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + mitesSecondsLost[i].ToString() + "</div></TD>\n"; ;
                    row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + mitesPercentLost[i].ToString() + "%" + "</div></TD>\n";
                }
                else
                {
                    row += "<TD><div align=\"center\">" + mitesSecondsLost[i].ToString() + "</div></TD>\n"; ;
                    row += "<TD><div align=\"center\">" + mitesPercentLost[i].ToString() + "%" + "</div></TD>\n";
                }

                int percent = 0;

                if (mitesSamplesCount[Convert.ToInt32(((SXML.Sensor)sannotation.Sensors[i]).ID)] > 0)
                    percent = (int)(((double)mitesMaxedOut[Convert.ToInt32(((SXML.Sensor)sannotation.Sensors[i]).ID)] / (double)mitesSamplesCount[Convert.ToInt32(((SXML.Sensor)sannotation.Sensors[i]).ID)]) * 100.0);
                row += "<TD><div align=\"center\">" + "N/A" + "</div></TD>\n";
                row += "<TD><div align=\"center\">" + "N/A" + "</div></TD>\n";
                row += "<TD><div align=\"center\">" + "N/A" + "</div></TD>\n";
                row += "<TD><div align=\"center\">" + mitesMaxedOut[Convert.ToInt32(((SXML.Sensor)sannotation.Sensors[i]).ID)] + "</div></TD>\n";
                row += "<TD><div align=\"center\">" + percent + "% </div></TD>\n";
                row += "</TR>\n";
                summary += row;

            }

            summary += "<TR><TD colspan=\"8\"></TD></TR><TR>\n";

            #endregion

            #region Statistics Table for Wockets

            for (int i = 0; (i < wc._Sensors.Count); i++)
            {

                if (wc._Receivers[i] is Wockets.Receivers.RFCOMMReceiver)
                {
                    string row = "<TR>\n";
                    row += "<TD><div align=\"center\"><strong>Wocket " + wc._Sensors[i]._Location + "</strong></div></TD>\n";

                    if (wocketsPercentLost[i] >= 20)
                    {
                        row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + wocketsSecondsLost[i].ToString() + "</div></TD>\n";
                        row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + wocketsPercentLost[i].ToString() + "%" + "</div></TD>\n";
                    }
                    else
                    {
                        row += "<TD><div align=\"center\">" + wocketsSecondsLost[i].ToString() + "</div></TD>\n";
                        row += "<TD><div align=\"center\">" + wocketsPercentLost[i].ToString() + "%" + "</div></TD>\n";
                    }
                    row += "<TD><div align=\"center\">" + numDisconnections[i].ToString() + "</div></TD>\n";
                    row += "<TD><div align=\"center\">" + meanDisconnection[i].ToString() + "</div></TD>\n";
                    if (sdDisconnection[i] >= 0)
                        row += "<TD><div align=\"center\">" + sdDisconnection[i].ToString() + "</div></TD>\n";
                    else
                        row += "<TD><div align=\"center\">N/A</div></TD>\n";
                    row += "<TD><div align=\"center\">" + maxedOut[i].ToString() + "</div></TD>\n";
                    if (samplesCount[i] > 0)
                        row += "<TD><div align=\"center\">" + ((int)(((double)maxedOut[i] / (double)samplesCount[i]) * 100.0)).ToString() + "% </div></TD>\n";
                    else
                        row += "<TD><div align=\"center\">0% </div></TD>\n";
                    row += "</TR>\n";
                    summary += row;
                }

            }

            summary += "</TABLE>\n";

            summary = "<HTML><HEAD></HEAD><BODY>" + summary + "</BODY></HTML>";
            TextWriter tw = new StreamWriter(aDataDirectory + "\\result.html", true);
            tw.WriteLine(summary);
            tw.WriteLine("\n<p>&nbsp;</p>\n");

            #endregion

            #region Statistics per Activity Table

            summary = "<h3><Font Color=#585858>Wockets Data Loss by Posture and Activity Statistics</Font></h3><TABLE border=\"1\">\n";
            numRows = numPostures;
            rows = new string[numRows];
            header = "<TR>\n<td><div align=\"center\"><strong>Activity</strong></div></td><td><div align=\"center\"><strong>Posture</strong></div></td><td><strong>Total Seconds Annotated</strong></td>\n";
            for (int j = 0; (j < wc._Sensors.Count); j++)
                header += "<TD><div align=\"center\"><strong>" + wc._Sensors[j]._Location + "</br>(Seconds Lost|% Lost)</strong></div></TD>\n";
            header += "</TR>\n";
            summary += header;

            int m = 0;
            if (session.OverlappingActivityLists.Count > 1)
            {
                for (int i = 0; (i < session.OverlappingActivityLists[1].Count); i++)
                    for (int j = 0; (j < session.OverlappingActivityLists[0].Count); j++)
                    {
                        if (annotatedPostures.ContainsKey(session.OverlappingActivityLists[1][i]._Name + "_" + session.OverlappingActivityLists[0][j]._Name))
                        {
                            string row = "<TR>\n";
                            row += "<TD><div align=\"center\"><strong>" + session.OverlappingActivityLists[1][i]._Name + "</strong></div></TD><TD><div align=\"center\"><strong>" + session.OverlappingActivityLists[0][j]._Name + "</strong></div></TD>\n";
                            row += "<TD><div>" + (int)annotatedPostures[session.OverlappingActivityLists[1][i]._Name + "_" + session.OverlappingActivityLists[0][j]._Name] + "</TD>\n";
                            for (int r = 0; (r < wc._Sensors.Count - 1); r++)
                                if (percentLostPostureSensorDistribution[r][m] > 20)
                                    row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + timeLostPostureSensorDistribution[r][m].ToString() + " | " + percentLostPostureSensorDistribution[r][m].ToString() + "%" + "</div></TD>\n";
                                else
                                    row += "<TD ><div align=\"center\">" + timeLostPostureSensorDistribution[r][m].ToString() + " | " + percentLostPostureSensorDistribution[r][m].ToString() + "%" + "</div></TD>\n";

                            row += "</TR>\n";
                            summary += row;
                        }
                        m++;
                    }
            }
            else
            {

                for (int j = 0; (j < session.OverlappingActivityLists[0].Count); j++)
                {
                    if (annotatedPostures.ContainsKey(session.OverlappingActivityLists[0][j]._Name))
                    {
                        string row = "<TR>\n";
                        row += "<TD><div align=\"center\"><strong>" + session.OverlappingActivityLists[0][j]._Name + "</strong></div></TD><TD><div align=\"center\"><strong>" + session.OverlappingActivityLists[0][j]._Name + "</strong></div></TD>\n";
                        row += "<TD><div>" + (int)annotatedPostures[session.OverlappingActivityLists[0][j]._Name] + "</TD>\n";
                        for (int r = 0; (r < wc._Sensors.Count); r++)
                            if (percentLostPostureSensorDistribution[r][m] > 20)
                                row += "<TD bgcolor=\"#FF0000\"><div align=\"center\">" + timeLostPostureSensorDistribution[r][m].ToString() + " | " + percentLostPostureSensorDistribution[r][m].ToString() + "%" + "</div></TD>\n";
                            else
                                row += "<TD ><div align=\"center\">" + timeLostPostureSensorDistribution[r][m].ToString() + " | " + percentLostPostureSensorDistribution[r][m].ToString() + "%" + "</div></TD>\n";

                        row += "</TR>\n";
                        summary += row;
                    }
                    m++;
                }
            }

            tw.WriteLine(summary + "</TABLE>\n");

            #endregion

            #region Other Sensors Statistics Table

            string[] ofiles = Directory.GetFileSystemEntries(aDataDirectory + "\\" + OTHER_SUBDIRECTORY + "\\");

            if (ofiles.Length > 1)
            {

                summary = "<h3><Font Color=#585858>Other Sensors Statistics</Font></h3><TABLE border=\"1\">\n";
                header = "<TR>\n<td><div align=\"center\"><strong>Sensor Type</strong></div></td><td><div align=\"center\"><strong>Start Time</strong></div></td><td><strong>Data Present</strong></td><td><strong>Num Samples</strong></td><td><strong>Percent Loss</strong></td></TR>\n";
                header += "</TR>\n";
                summary += header;

                int expectedOxyconRecords = totalSeconds / 5;
                double oxyconLoss = 0;
                if (oxyconRecords < expectedOxyconRecords)
                    oxyconLoss = 100 - (((double)oxyconRecords / expectedOxyconRecords) * 100.0);

                summary += "<TR>\n<td><div align=\"center\"><strong>Oxycon</strong></div></td><td>" + (oxyconStart == null ? "&nbsp;" : oxyconStart) + "</td><td>" + (hasOxycon ? "Yes" : "No") + "</td><td>" + oxyconRecords + "</td><td>" + oxyconLoss.ToString("0") + "%</td></TR>\n";

                double sensewearLoss = 0;
                if (sensewearRecords < totalSeconds)
                    sensewearLoss = 100 - (((double)sensewearRecords / totalSeconds) * 100.0);

                summary += "<TR>\n<td><div align=\"center\"><strong>Sensewear</strong></div></td><td>" + (sensewearStart == null ? "&nbsp;" : sensewearStart) + "</td><td>" + (hasSensewear ? "Yes" : "No") + "</td><td>" + sensewearRecords + "</td><td>" + sensewearLoss.ToString("0") + "%</td></TR>\n";

                summary += "<TR>\n<td><div align=\"center\"><strong>Actigraph</strong></div></td><td>" + (actigraphStart == null ? "&nbsp;" : actigraphStart) + "</td><td>" + (hasActigraph ? "Yes" : "No") + "</td><td>";

                for (int r = 0; (r < actigraphData.Length); r++)
                {
                    summary += actigraphData[r].Count;
                    if (r != (actigraphData.Length - 1))
                        summary += " | ";
                }
                summary += "</td><td>";

                for (int r = 0; (r < actigraphData.Length); r++)
                {
                    double actigraphLoss = 0;
                    if (actigraphData[r].Count < totalSeconds)
                        actigraphLoss = 100 - (((double)actigraphData[r].Count / totalSeconds) * 100.0);
                    summary += actigraphLoss.ToString("0") + " %";
                    if (r != (actigraphData.Length - 1))
                        summary += " | ";
                }
                summary += "</td></TR>\n";

                double zephyrLoss = 0;
                if (zephyrRecords < totalSeconds)
                    zephyrLoss = 100 - (((double)zephyrRecords / totalSeconds) * 100.0);
                summary += "<TR>\n<td><div align=\"center\"><strong>Zephyr</strong></div></td><td>" + (zephyrStart == null ? "&nbsp;" : zephyrStart) + "</td><td>" + (hasZephyr ? "Yes" : "No") + "</td><td>" + zephyrRecords + "</td><td>" + zephyrLoss.ToString("0") + "%</td></TR>\n";

                double rtiLoss = 0;
                if (rtiRecords < totalSeconds)
                    rtiLoss = 100 - (((double)rtiRecords / totalSeconds) * 100.0);
                summary += "<TR>\n<td><div align=\"center\"><strong>RTI</strong></div></td><td>" + (rtiStart == null ? "&nbsp;" : rtiStart) + "</td><td>" + (hasRTI ? "Yes" : "No") + "</td><td>" + rtiRecords + "</td><td>" + rtiLoss.ToString("0") + "%</td></TR>\n";

                double columbiaLoss = 0;
                if (columbiaRecords < totalSeconds)
                    columbiaLoss = 100 - (((double)columbiaRecords / totalSeconds) * 100.0);
                summary += "<TR>\n<td><div align=\"center\"><strong>Columbia</strong></div></td><td>" + (columbiaStart == null ? "&nbsp;" : columbiaStart) + "</td><td>" + (hasColumbia ? "Yes" : "No") + "</td><td>" + columbiaRecords + "</td><td>" + columbiaLoss.ToString("0") + "%</td></TR>\n";

                double gpsLoss = 0;
                if (gpsRecords < totalSeconds)
                    gpsLoss = 100 - (((double)gpsRecords / totalSeconds) * 100.0);
                summary += "<TR>\n<td><div align=\"center\"><strong>GPS</strong></div></td><td>" + (gpsStart == null ? "&nbsp;" : gpsStart) + "</td><td>" + (hasGPS ? "Yes" : "No") + "</td><td>" + gpsRecords + "</td><td>" + gpsLoss.ToString("0") + "%</td></TR>\n";

                tw.WriteLine(summary + "</TABLE>\n");
            }

            #endregion

            tw.WriteLine("</HTML>");
            tw.Flush();
            tw.Close();

            #endregion

            #region Add the Annotations Summary

            tw = new StreamWriter(aDataDirectory + "\\result.html", true);

            summary = "";
            summary += "<h3><Font Color=#585858>Annotation Summary</Font></h3>\n";

            //If the annotation summary file exists, add it to current summary
            //If it doesn't exist, add the HTML to summary
            if (File.Exists(aDataDirectory + "\\" + ANNOTATION_SUBDIRECTORY + "\\AnnotationSummary.html"))
            {
                try
                {
                    TextReader ttr = new StreamReader(aDataDirectory + "\\" + ANNOTATION_SUBDIRECTORY + "\\AnnotationSummary.html");
                    summary += ttr.ReadToEnd();
                    ttr.Close();
                }
                catch (Exception ee)
                {
                }
            }
            else
            {

                #region Create HTML content with stats for Autism Data

                try
                {
                    //Create Table & Headers
                    summary += "<table border=\"1\">\n";

                    TimeSpan ttime = new TimeSpan(0, 0, totalSeconds);
                    //Session total time
                    summary += "<tr> <td><div align=\"center\"><strong>Session Total Time (hh:mm:ss.ms)</strong></div></td>" +
                                    "<td>" + String.Format("{0:HH mm ss ff}", ttime) + "</td>" +
                               "</tr>";

                    //Headers for annotation metrics
                    summary += "<tr>" + "<td><div align=\"center\"><strong> Label </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> Duration in Seconds </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> %Occurrence </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> Frequency </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> Mean (sec) </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> STD (sec) </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> Min (sec) </strong></div></td>" +
                                        "<td><div align=\"center\"><strong> Max (sec) </strong></div></td>" +
                               "</tr>";

                    //Scan through labels
                    int total_secs_activity = 0;
                    double percent_duration = 0.0;

                    for (int j = 0; j < session.OverlappingActivityLists[0].Count; j++)
                    {

                        name = session.OverlappingActivityLists[0][j]._Name;

                        if (annotatedPostures.ContainsKey(name))
                        {
                            total_secs_activity = (int)annotatedPostures[name];
                            percent_duration = ((double)total_secs_activity / totalSeconds) * 100.0;

                            summary += "<tr>\n" +
                                   "<td><div align=\"center\"><strong>" + name + "</strong></div></td>" +
                                   "<td>" + total_secs_activity.ToString() + "</td>" +
                                   "<td>" + String.Format("{0:0.0}%", percent_duration) + "</td>" +
                                   "<td>" + String.Format("{0:0}", freq_per_class[name]) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", means_per_class[name]) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", std_per_class[name]) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", min_per_class[name]) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", max_per_class[name]) + "</td>" +
                                   "</tr>";
                        }
                        else
                        {

                            summary += "<tr>\n" +
                                   "<td><div align=\"center\"><strong>" + name + "</strong></div></td>" +
                                   "<td>" + String.Format("{0:0}", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0.0}%", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0}", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", 0) + "</td>" +
                                   "<td>" + String.Format("{0:0.00}", 0) + "</td>" +
                                   "</tr>";

                        }

                    }

                    //Close table
                    summary += "</table>";

                    //Generate the colors code for Autistic Labels
                    SaveLabelsColorsToFile(aDataDirectory, session.OverlappingActivityLists.Count, session.OverlappingActivityLists);

                }
                catch (Exception ee)
                {
                    summary += "</HTML>";

                    try
                    {
                        if (tw != null)
                        {
                            tw.WriteLine(summary);
                            tw.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        //cannot write to file
                    }

                }

                #endregion

            }

            summary += "</HTML>";

            #endregion

            tw.WriteLine(summary);
            tw.Close();

            #endregion

            #endregion
        }