public ImagingSession Clone() { var clone = new ImagingSession { Name = Name, AreaRect = AreaRect, PauseAfterEachRepeat = PauseAfterEachRepeat, RepeatTimes = RepeatTimes, PauseAfterEachSequence = PauseAfterEachSequence, CurrentRepeatIndex = 0, CurrentImageSequenceIndex = 0 }; clone.ImageSequences = new ObservableCollection<ImageSequence>(); foreach (var imageSequence in ImageSequences) { clone.ImageSequences.Add(imageSequence.Clone()); } return clone; }
public void CancelStoredImagingOperation() { var session = IsSessionPaused ? _storedSession : CurrentImagingSession; _storedSession = null; IsSessionPaused = false; CancelCurrentImagingOperation(); CurrentImagingSession = null; if (OnImagingSessionCompleted != null) OnImagingSessionCompleted(session, false, true); }
public async Task RunImagingSession(ImagingSession session) { int rightBound = _cameraService.Camera.CameraXSize; int bottomBound = _cameraService.Camera.CameraYSize; if (session.AreaRect.X + session.AreaRect.Width > rightBound || session.AreaRect.X < 0) throw new ArgumentOutOfRangeException("areaRect", "Pixel X area out of camera pixel bounds"); if (session.AreaRect.Y + session.AreaRect.Height > bottomBound || session.AreaRect.Y < 0) throw new ArgumentOutOfRangeException("areaRect", "Pixel Y area out of camera pixel bounds"); _cameraService.OnExposureCompleted += OnExposureCompleted; CurrentImagingSession = session; SessionHistory.Add(session); if (OnImagingSessionStarted != null) OnImagingSessionStarted(session); for (; session.CurrentRepeatIndex < session.RepeatTimes; session.CurrentRepeatIndex++) { for (; session.CurrentImageSequenceIndex < session.ImageSequences.Count; session.CurrentImageSequenceIndex++) { var sequence = session.ImageSequences[session.CurrentImageSequenceIndex]; CurrentImageSequence = sequence; if(!sequence.Enabled) continue; if (OnImageSequenceStarted != null) OnImageSequenceStarted(session, sequence); // Set binning for the camera accordingly. _cameraService.Camera.BinX = (short)sequence.BinXY; _cameraService.Camera.BinY = (short)sequence.BinXY; // If Width or Height is 0, assume full area. var rect = session.AreaRect; if (rect.Width == 0 || rect.Height == 0) { rect.Width = _cameraService.Camera.CameraXSize; rect.Height = _cameraService.Camera.CameraYSize; } _cameraService.Camera.StartX = rect.X; _cameraService.Camera.StartY = rect.Y; _cameraService.Camera.NumX = rect.Width / sequence.BinXY; _cameraService.Camera.NumY = rect.Height / sequence.BinXY; for (; sequence.CurrentExposureIndex < sequence.NumExposures; sequence.CurrentExposureIndex++) { bool result = false; try { result = await _cameraService.TakeExposure(sequence.ExposureDuration, sequence.ExposureDuration == 0); if (!result) { _logService.LogMessage(new LogMessage(this, LogEventCategory.Error, "TakeExposure returned false; last exposure could not be taken/saved.")); } // Note: saving happens in OnExposureCompleted and only when the session has SaveOutput set to true. // Note: we do not increment CurrentExposureIndex because most likely the exposure was incomplete. if (IsSessionPaused) break; } catch (Exception e) { _logService.LogMessage(new LogMessage(this, LogEventCategory.Error, "Exception occured on RunImagingSession: " + e.Message)); _cameraService.OnExposureCompleted -= OnExposureCompleted; // Pause, do not abort. Something happened that might be fixable. PauseCurrentImagingOperation("Error occured. Check log entry for details. Imaging paused, session may still be continuable.", true); break; } } if (session.PauseAfterEachSequence && sequence.CurrentExposureIndex == sequence.NumExposures && session.CurrentImageSequenceIndex < session.ImageSequences.Count - 1) { PauseCurrentImagingOperation("Sequence completed.", false); session.CurrentImageSequenceIndex++; if (OnImageSequenceCompleted != null) OnImageSequenceCompleted(session, sequence); break; } if (IsSessionPaused) break; if (OnImageSequenceCompleted != null) OnImageSequenceCompleted(session, sequence); } if (session.PauseAfterEachRepeat && session.CurrentImageSequenceIndex == session.ImageSequences.Count && session.CurrentRepeatIndex < session.RepeatTimes - 1) { PauseCurrentImagingOperation("Session run completed.", false); session.CurrentRepeatIndex++; break; } if (IsSessionPaused) break; // Repeat completed, reset the current indices for the next round. session.CurrentImageSequenceIndex = 0; foreach (var imageSequence in session.ImageSequences) imageSequence.CurrentExposureIndex = 0; } _cameraService.OnExposureCompleted -= OnExposureCompleted; if (!IsSessionPaused) { CurrentImagingSession = null; if (OnImagingSessionCompleted != null) OnImagingSessionCompleted(session, true, false); } }
/// <summary> /// todo reason Sequence completed /// </summary> public void PauseCurrentImagingOperation(string reason, bool error) { if (IsSessionPaused) return; // Store the session and set paused true. _storedSession = CurrentImagingSession; CurrentImagingSession = null; IsSessionPaused = true; // Stop any exposure in progress. CancelCurrentImagingOperation(); if (OnImagingSessionPaused != null) OnImagingSessionPaused(_storedSession, reason, error); }
public async Task TestImagingServiceSequence() { var imageIoService = MockImageIoService(); var cameraService = MockCameraService(); var logService = MockLogService(); var systemEnv = new Mock<ISystemEnvironment>(); systemEnv.SetupGet(x => x.UserPicturesDirectory).Returns(Path.GetTempPath()); systemEnv.SetupGet(x => x.UserHomeDirectory).Returns(Path.GetTempPath()); systemEnv.SetupGet(x => x.TemporaryFilesDirectory).Returns(Path.GetTempPath()); cameraService.Setup(x => x.TakeExposure(It.IsAny<double>(), It.IsAny<bool>(), It.IsAny<bool>())) .ReturnsAsync(true) .Raises(x => x.OnExposureCompleted += null, true, new Exposure(800, 600, new int[0], 1, false)); var writerMoq = new Mock<IImageWriter>(); writerMoq.Setup(x => x.Save(It.IsAny<Exposure>(), It.IsAny<string>())); writerMoq.Setup(x => x.Save(It.IsAny<Exposure>(), It.IsAny<string>(), It.IsAny<Dictionary<string, object>>())); imageIoService.Setup(x => x.GetImageWriter(It.IsAny<ImageFileFormat>())).Returns(writerMoq.Object); var imagingService = new ImagingService(cameraService.Object, logService.Object, imageIoService.Object, systemEnv.Object); var session = new ImagingSession() { Name = "Test Session", SaveOutput = true, RepeatTimes = 2, PauseAfterEachRepeat = false, PauseAfterEachSequence = false }; var sequence1 = new ImageSequence() { BinXY = 4, ExposureDuration = 90, Extension = "test", FileFormat = imageIoService.Object.WritableFileFormats.First().Id, Name = "Sequence 1", NumExposures = 2 }; var sequence2 = new ImageSequence() { BinXY = 1, ExposureDuration = 10, Extension = "test", FileFormat = imageIoService.Object.WritableFileFormats.First().Id, Name = "Sequence 2", NumExposures = 2 }; session.ImageSequences.Add(sequence1); session.ImageSequences.Add(sequence2); imagingService.OnImagingSessionStarted += imagingSession => { Console.WriteLine(@"Imaging session started"); }; imagingService.OnImagingComplete += (successful, exposure) => { Console.WriteLine(@"Single exposure imaging complete, success: " + successful); Console.WriteLine(@"Exposure filename: " + session.GenerateFilename(imagingService.CurrentImageSequence)); }; imagingService.OnImagingSessionCompleted += (imagingSession, successfully, userCanceled) => { Console.WriteLine(@"Imaging session completed, success: " + successfully + @", was user canceled: " + userCanceled); }; await imagingService.RunImagingSession(session); // 2 x 2 x 2 images, verify. writerMoq.Verify(x => x.Save(It.IsAny<Exposure>(), It.IsAny<string>()), Times.Exactly(8)); // Asserts? }