/// <summary> /// Loads the shapes that are listed in the given database table /// and creates corresponding graphic elements. /// </summary> /// <param name="areaOfInterestTableRows"> /// Areas of interest table as /// a <see cref="DataGridViewRowCollection"/> /// </param> public void LoadShapesFromDataGridView(DataGridViewRowCollection areaOfInterestTableRows) { try { // Create aoi elements from data view this.AoiCollection = new VGElementCollection(); foreach (DataGridViewRow row in areaOfInterestTableRows) { if (!row.IsNewRow) { // retrieve shape parameters from cell values. var shapeName = row.Cells["colShapeName"].Value.ToString(); var strPtList = row.Cells["colShapePts"].Value.ToString(); Pen usedPen; Font usedFont; Color usedFontColor; VGAlignment usedAlignment; VGStyleGroup usedStyleGroup; var pointList = ObjectStringConverter.StringToPointFList(strPtList); var usedElementGroup = row.Cells["colShapeGroup"].Value.ToString(); switch (usedElementGroup) { case "Target": usedPen = this.TargetPen; usedFont = this.TargetFont; usedFontColor = this.TargetFontColor; usedStyleGroup = VGStyleGroup.AOI_TARGET; usedAlignment = this.TargetTextAlignment; break; case "SearchRect": usedPen = this.SearchRectPen; usedFont = this.SearchRectFont; usedFontColor = this.SearchRectFontColor; usedStyleGroup = VGStyleGroup.AOI_SEARCHRECT; usedAlignment = this.SearchRectTextAlignment; break; default: usedPen = this.DefaultPen; usedFont = this.DefaultFonts; usedFontColor = this.DefaultFontColor; usedStyleGroup = VGStyleGroup.AOI_NORMAL; usedAlignment = this.DefaultTextAlignment; break; } // Create the shape depending on ShapeType var boundingRect = new RectangleF(); switch (row.Cells["colShapeType"].Value.ToString()) { case "Rectangle": boundingRect.Location = pointList[0]; boundingRect.Width = pointList[2].X - pointList[0].X; boundingRect.Height = pointList[2].Y - pointList[0].Y; // Create Rect with defined stroke var newRect = new VGRectangle( this.hideAOIDescription ? ShapeDrawAction.Edge : ShapeDrawAction.NameAndEdge, usedPen, usedFont, usedFontColor, boundingRect, usedStyleGroup, shapeName, usedElementGroup); newRect.TextAlignment = usedAlignment; this.AoiCollection.Add(newRect); break; case "Ellipse": boundingRect.Location = pointList[0]; boundingRect.Width = pointList[2].X - pointList[0].X; boundingRect.Height = pointList[2].Y - pointList[0].Y; // Create Rect with defined stroke var newEllipse = new VGEllipse( this.hideAOIDescription ? ShapeDrawAction.Edge : ShapeDrawAction.NameAndEdge, usedPen, usedFont, usedFontColor, boundingRect, usedStyleGroup, shapeName, usedElementGroup); newEllipse.TextAlignment = usedAlignment; this.AoiCollection.Add(newEllipse); break; case "Polyline": // Create Polyline with defined stroke var newPolyline = new VGPolyline( this.hideAOIDescription ? ShapeDrawAction.Edge : ShapeDrawAction.NameAndEdge, usedPen, usedFont, usedFontColor, usedStyleGroup, shapeName, usedElementGroup); newPolyline.TextAlignment = usedAlignment; foreach (var point in pointList) { newPolyline.AddPt(point); } newPolyline.ClosePolyline(); this.AoiCollection.Add(newPolyline); break; } } } // Reset Elements (deselect and clear all) this.ResetPicture(); this.Elements.AddRange(this.AoiCollection); // If there were a selected element before updating, try // to select it again. if (this.SelectedElement != null) { foreach (VGElement element in this.Elements) { if (VGPolyline.Distance(element.Location, this.SelectedElement.Location) < 1) { this.SelectedElement = element; element.IsInEditMode = true; } } } this.DrawForeground(true); } catch (Exception ex) { ExceptionMethods.HandleException(ex); } }
/// <summary> /// Calculates fixations from raw data and writes them into /// the database in the fixations tables. /// </summary> /// <param name="sampleType">The <see cref="SampleType"/> of the data, gaze or mouse</param> /// <param name="subject">A <see cref="String"/> with the subject name</param> /// <param name="trialsTable">The database trials <see cref="DataTable"/></param> /// <param name="worker">The <see cref="BackgroundWorker"/> of the calculation</param> /// <param name="e">The <see cref="DoWorkEventArgs"/> of the <see cref="BackgroundWorker"/></param> public void CalcFixations( SampleType sampleType, string subject, System.Data.DataTable trialsTable, BackgroundWorker worker, DoWorkEventArgs e) { // Fixation Calculating Objects ////////////////////////////////////////// FixationDetection objFixationDetection = new FixationDetection(); // Instantiate the delegate using the method as a parameter GetDataDelegate getDataMethod = null; int minSamples = 0; int maxDistance = 0; if (sampleType == (sampleType | SampleType.Gaze)) { getDataMethod = Queries.GetGazeData; minSamples = this.gazeMinSamples; maxDistance = this.gazeMaxDistance; } else if (sampleType == (sampleType | SampleType.Mouse)) { getDataMethod = Queries.GetMouseData; minSamples = this.mouseMinSamples; maxDistance = this.mouseMaxDistance; } bool point_found_delayed; /* sample gazepoint-found flag, */ /* min_fix_samples ago */ float x_delayed; /* sample gazepoint coordinates, */ float y_delayed; /* min_fix_samples ago */ float deviation_delayed; /* deviation of the gaze from the */ /* present fixation, */ /* min_fix_samples ago */ /* Fixation data - delayed: */ float x_fix_delayed = new float(); /* fixation point as estimated */ float y_fix_delayed = new float(); /* min_fix_samples ago */ int saccade_duration_delayed; /* duration of the saccade */ /* preceeding the preset fixation */ /* (samples) */ long fix_start_time = new long(); int fix_duration_delayed_samples = new int(); /* duration of the present fixation */ long fix_duration_delayed_milliseconds = new long(); /* duration of the present fixation */ EyeMotionState currentState = new EyeMotionState(); // OtherVars int counterTrial = 0; PointF trialLastFixCenter = new PointF(0, 0); // Loop Rows=Trials foreach (DataRow trialRow in trialsTable.Rows) { List <Fixation> fixations = new List <Fixation>(); // Reinitialize Fixation detection object // to ensure no overlay between fixations of // trials that follow each other. objFixationDetection.InitFixation(minSamples); int trialID = (int)trialRow["TrialID"]; int trialSequence = (int)trialRow["TrialSequence"]; // Holds RawData corresponding to selected trial and subject DataTable rawDataTable = Queries.GetRawDataBySubjectAndTrialSequence(subject, trialSequence); long trialStartTime = rawDataTable.Rows.Count > 0 ? (long)rawDataTable.Rows[0]["Time"] : 0; int counterRows = 0; int counterFix = 0; bool isFixation = false; // Loop RawData foreach (DataRow rowRaw in rawDataTable.Rows) { PointF? newPt; SampleValidity isValidData = getDataMethod( rowRaw, Document.ActiveDocument.PresentationSize, out newPt); bool useSample = false; switch (isValidData) { case SampleValidity.Valid: useSample = true; break; case SampleValidity.Empty: useSample = true; break; case SampleValidity.Null: break; case SampleValidity.OutOfStimulus: useSample = true; break; } if (useSample) { PointF dataPoint = newPt.Value; currentState = objFixationDetection.DetectFixation( dataPoint.IsEmpty ? false : true, Convert.ToInt64(rowRaw[3]), dataPoint.X, dataPoint.Y, maxDistance, minSamples, out point_found_delayed, out x_delayed, out y_delayed, out deviation_delayed, out x_fix_delayed, out y_fix_delayed, out saccade_duration_delayed, out fix_start_time, out fix_duration_delayed_milliseconds, out fix_duration_delayed_samples); switch (currentState) { case EyeMotionState.FIXATING: if (!isFixation) { isFixation = true; } break; case EyeMotionState.FIXATION_COMPLETED: PointF fixationCenter = new PointF(x_fix_delayed, y_fix_delayed); // if (!Queries.OutOfScreen(fixationCenter)) TODO { Fixation completedFixation = new Fixation(); completedFixation.CountInTrial = counterFix + 1; completedFixation.Length = fix_duration_delayed_milliseconds; completedFixation.PosX = x_fix_delayed; completedFixation.PosY = y_fix_delayed; completedFixation.SampleType = sampleType; completedFixation.StartTime = fix_start_time - trialStartTime; completedFixation.SubjectName = (string)trialRow["SubjectName"]; completedFixation.TrialID = (int)trialRow["TrialID"]; completedFixation.TrialSequence = (int)trialRow["TrialSequence"]; if (this.eliminateFirstFixation && this.eliminateFirstFixationSimple == false && counterFix == 0 && VGPolyline.Distance(fixationCenter, trialLastFixCenter) < maxDistance && fix_duration_delayed_milliseconds < this.limitForFirstFixation) { // Eliminate if applicable } else if (this.eliminateFirstFixationSimple && counterFix == 0) { // do nothing, just go on with the next fixation eliminating this one counterFix++; } else { fixations.Add(completedFixation); counterFix++; } } isFixation = false; break; case EyeMotionState.ERROR: break; default: break; } } counterRows++; // End RawData Loop } // Save last Fix if it has not been saved by a following saccade if (isFixation && fix_duration_delayed_milliseconds > 0) { Fixation lastFixation = new Fixation(); lastFixation.CountInTrial = counterFix + 1; lastFixation.Length = fix_duration_delayed_milliseconds; lastFixation.PosX = x_fix_delayed; lastFixation.PosY = y_fix_delayed; lastFixation.SampleType = sampleType; lastFixation.StartTime = fix_start_time - trialStartTime; lastFixation.SubjectName = (string)trialRow["SubjectName"]; lastFixation.TrialID = (int)trialRow["TrialID"]; lastFixation.TrialSequence = (int)trialRow["TrialSequence"]; fixations.Add(lastFixation); } // Save last FixCenter for Eliminating first Fix of new trial if choosen in UI trialLastFixCenter.X = x_fix_delayed; trialLastFixCenter.Y = y_fix_delayed; if (this.mergeConsecutiveFixations) { // Look for consecutive fixations that are beneath each other // (within GazeMaxDistance) because of // miscalculation due to blinks or missing data. List <Fixation> mergedFixations = new List <Fixation>(); if (fixations.Count > 1) { Fixation foregoingFixation = fixations[0]; bool merged = false; int mergedCounter = 0; int consecutiveMerges = 0; int trialFixCounter = 1; PointF foregoingFixationCenter = new PointF(foregoingFixation.PosX, foregoingFixation.PosY); for (int i = 1; i < fixations.Count; i++) { // Test if consecutive calculated fixations lie in GazeMaxDistanceRange PointF fixationCenter = new PointF(fixations[i].PosX, fixations[i].PosY); int distance = (int)VGPolyline.Distance(foregoingFixationCenter, fixationCenter); if (distance < maxDistance) { long sumOfDuration = foregoingFixation.Length + fixations[i].Length; foregoingFixation.PosX = (foregoingFixation.PosX * foregoingFixation.Length + fixations[i].PosX * fixations[i].Length) / sumOfDuration; foregoingFixation.PosY = (foregoingFixation.PosY * foregoingFixation.Length + fixations[i].PosY * fixations[i].Length) / sumOfDuration; foregoingFixation.Length = fixations[i].StartTime - foregoingFixation.StartTime + fixations[i].Length; merged = true; mergedCounter++; consecutiveMerges++; } else { if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } else { merged = false; foregoingFixation.CountInTrial -= mergedCounter - 1; foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); consecutiveMerges = 0; trialFixCounter++; } foregoingFixation = fixations[i]; foregoingFixationCenter = fixationCenter; } } if (!merged) { foregoingFixation.CountInTrial = trialFixCounter; mergedFixations.Add(foregoingFixation); trialFixCounter++; } } else { mergedFixations = fixations; } foreach (Fixation fixationToSave in mergedFixations) { this.SaveFixationToTable(fixationToSave); } } else { // Don not merge fixations, use the originals. foreach (Fixation fixationToSave in fixations) { this.SaveFixationToTable(fixationToSave); } } // increase TrialCounter counterTrial++; if (worker != null) { if (worker.CancellationPending) { e.Cancel = true; break; } else { // Report progress as a percentage of the total task. int percentComplete = Convert.ToInt32(Convert.ToSingle(counterTrial) / trialsTable.Rows.Count * 100); worker.ReportProgress(percentComplete); } } // End Trial Loop } // Save Data to MDF File this.WriteToMDF(sampleType); }