Beispiel #1
0
        private void BuildHeader(Header header, Exposure exposure, Dictionary<string, object> metadata, long maxValue)
        {
            // Set BZERO to half of bitness (32768 for 16-bit)
            header.AddValue("BZERO", 0.5 * maxValue, "");
            header.AddValue("BSCALE", (double)1, "");
            header.AddValue("DATAMIN", 0.0, "");
            header.AddValue("DATAMAX", (double)exposure.MaxDepth, "");
            header.AddValue("CBLACK", (double)exposure.PixelMinValue, "");
            header.AddValue("CWHITE", (double)exposure.PixelMaxValue, "");
            header.AddValue("SWCREATE", "DSImager", "");

            if (metadata != null)
            {
                foreach (var entry in metadata)
                {
                    if (entry.Value is int)
                        header.AddValue(entry.Key, (int)entry.Value, "");
                    if (entry.Value is bool)
                        header.AddValue(entry.Key, (bool)entry.Value, "");
                    if (entry.Value is double)
                        header.AddValue(entry.Key, (double)entry.Value, "");
                    if (entry.Value is string)
                        header.AddValue(entry.Key, (string)entry.Value, "");
                    if (entry.Value is long)
                        header.AddValue(entry.Key, (long)entry.Value, "");
                }
            }
        }
Beispiel #2
0
        public void Save(Exposure exposure, string filename, Dictionary<string, object> metadata)
        {
            Fits fits = new Fits();
            int[] dimensions = new[] { exposure.Height, exposure.Width };

            // choose the type from calculating the bitness from the exposure maxdepth
            long a = 0, bits = -1;
            while (a < exposure.MaxDepth)
                a = (int)Math.Pow(2.0, ++bits);

            Array pixels;
            if (bits <= 16)
            {
                pixels = ConvertToShort(exposure.Pixels);
            }
            else
            {
                pixels = exposure.Pixels;
            }

            var data = ArrayFuncs.Curl(pixels, dimensions);
            var hdu = FitsFactory.HDUFactory(data);

            // Write the headers.

            BuildHeader(hdu.Header, exposure, metadata, a);

            fits.AddHDU(hdu);

            if (!filename.EndsWith(".fits"))
                filename += ".fits";

            BufferedFile bf = new BufferedFile(filename, FileAccess.ReadWrite, FileShare.None);
            fits.Write(bf);
            bf.Close();
        }
Beispiel #3
0
 public void Save(Exposure exposure, string filename)
 {
     Save(exposure, filename, null);
 }
Beispiel #4
0
        private void OnExposureCompleted(bool successful, Exposure exposure)
        {
            if (!ExposureVisualProcessingSettings.AutoStretch)
            {
                var min = ExposureVisualProcessingSettings.StretchMin;
                var max = ExposureVisualProcessingSettings.StretchMax;
                // No auto stretch, make sure we don't have initial conditions 
                // (default min/max), if values are non-default then apply stretch.
                if (!(min == 0 && (max == -1 || max == exposure.MaxDepth)))
                {
                    if (max == -1)
                        max = exposure.MaxDepth;
                    exposure.SetStretch(min, max);
                }
            }
            else
            {
                exposure.SetStretch();
            }

            if (CurrentImagingSession != null && CurrentImagingSession.SaveOutput)
            {
                try
                {
                    SaveExposureToDisk(exposure, CurrentImageSequence.FileFormat);                    
                }
                catch (Exception e)
                {
                    _logService.LogMessage(new LogMessage(this, LogEventCategory.Error, "Unable to save exposure to disk! Exception raised: " + e.Message));
                }
            }

            if (OnImagingComplete != null)
                OnImagingComplete(successful, exposure);
        }
Beispiel #5
0
        private void SaveExposureToDisk(Exposure exposure, string format)
        {

            var ff = _imageIoService.WritableFileFormats.Where(wff => wff.Id == format).FirstOrDefault();
            if(ff == null)
                throw new ArgumentException("File format '" + format + "' was invalid, no writer for that file format found.", "format");

            var writer = _imageIoService.GetImageWriter(ff);
            
            var fname = CurrentImagingSession.GenerateFilename(CurrentImageSequence);
            
            var path = CurrentImagingSession.OutputDirectory;
            if (string.IsNullOrEmpty(path))
            {
                if (!string.IsNullOrEmpty(_systemEnvironment.UserPicturesDirectory))
                {
                    path = Path.Combine(_systemEnvironment.UserPicturesDirectory,
                        "DSImager-session-" + CurrentImagingSession.Name.ToFilenameString());
                }
                else
                {
                    path = Path.Combine(_systemEnvironment.UserHomeDirectory,
                        "DSImager-session-" + CurrentImagingSession.Name.ToFilenameString());
                }
            }

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            
            var filename = Path.Combine(path, fname);
            writer.Save(exposure, filename);
            _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational, "Exposure saved to disk: " + filename));

        }
Beispiel #6
0
        private void HandleCanceledImagingOperation(bool successful, Exposure exposure)
        {
            // Canceling seems to leave the buffer in a questionable state: the next
            // frame is usually broken (tested on Atik 414EX). Therefore take one "garbage frame"
            // so that the next frame taken won't be a disappointment.

            _cameraService.OnExposureCompleted -= HandleCanceledImagingOperation;
            _cameraService.TakeExposure(0, true, true);
        }
Beispiel #7
0
        /// <summary>
        /// Starts exposuring.
        /// No camera parameters given, ie. the Camera parameters must have already been set.
        /// ImagingService should do that part - this method just starts the exposure and 
        /// runs an exposure cycle and handles the different states and such.
        /// </summary>
        /// <param name="duration">The exposure duration, in seconds</param>
        /// <param name="isCalibrationFrame">If the frame is a calibration frame, set to true</param>
        /// <param name="garbageFrame">If we consider this a "garbage frame", ie. this frame is taken for cleanup purposes.
        /// No events will be triggered by this frame.</param>
        /// <returns>
        /// Did exposuring succeed or fail. Note: upon stopping exposure, 
        /// the return value is true (exposure data is still saved). Upon aborting, the value is false.
        /// </returns>
        public async Task<bool> TakeExposure(double duration, bool isCalibrationFrame = false, bool garbageFrame = false)
        {
            _isExposuring = true;

            if (garbageFrame)
            {
                _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational, 
                    "Taking a cleanup frame"));
            }
            else
                _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational,
                    string.Format("Starting new exposure: {0:F}s", duration)));

            if (Camera.CameraState != CameraStates.cameraIdle)
            {
                _logService.LogMessage(new LogMessage(this, LogEventCategory.Warning, 
                    "Camera is not in idle state, unable to start a new exposure."));
                return false;
            }


            var metadata = new ExposureMetaData()
            {
                BinX = Camera.BinX,
                BinY = Camera.BinY,
                ExposureTime = duration
            };

            if (OnExposureStarted != null && !garbageFrame)
                OnExposureStarted(duration);

            Camera.StartExposure(duration, !isCalibrationFrame);
            
            if (OnExposureProgressChanged != null && !garbageFrame)
                OnExposureProgressChanged(0, duration, ExposurePhase.Exposuring);

            var startTime = DateTime.Now;
            TimeSpan currentDuration = TimeSpan.Zero;
            while (!Camera.ImageReady && (Camera.CameraState != CameraStates.cameraExposing ||
                    Camera.CameraState != CameraStates.cameraReading))
            {
                await Task.Delay(200);
                currentDuration = DateTime.Now - startTime;
                if (OnExposureProgressChanged != null && !garbageFrame)
                    OnExposureProgressChanged(currentDuration.TotalSeconds, duration, ExposurePhase.Exposuring);
            }

            // Done, download the image.
            if (Camera.ImageReady)
            {

                if (garbageFrame)
                {
                    _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational,
                        "Cleanup frame taken"));
                    _isExposuring = false;
                    return true;
                }

                if (OnExposureProgressChanged != null)
                    OnExposureProgressChanged(currentDuration.TotalSeconds, duration, ExposurePhase.Downloading);

                _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational,
                    "Exposure ready, downloading..."));

                int[,] imgArr = (int[,])Camera.ImageArray;
                int imageW = imgArr.GetLength(0);
                int imageH = imgArr.GetLength(1);

                // BlockCopy doesn't work here because the output row/column order is wrong.
                // We really want the data as a single dimensional array and this is not
                // the most efficient way to do it but will have to suffice until
                // I find a more efficient way.
                int[] pixelArr = new int[imgArr.GetLength(0) * imgArr.GetLength(1)];
                for (int y = 0; y < imageH; y++)
                {
                    for (int x = 0; x < imageW; x++)
                    {
                        pixelArr[y * imageW + x] = imgArr[x, y];
                    }
                }
                

                Exposure exposure = new Exposure(imageW, imageH, pixelArr, Camera.MaxADU, false);
                metadata.ExposureTime = Camera.LastExposureDuration;
                metadata.ExposureEndTime = DateTime.Now;
                exposure.MetaData = metadata;
                _exposure = exposure;

                _isExposuring = false;

                _logService.LogMessage(new LogMessage(this, LogEventCategory.Informational,
                    "Exposure done."));

                if (OnExposureCompleted != null)
                    OnExposureCompleted(true, exposure);

                return true;
            }
            // The exposure was aborted and image could not be retrieved.
            else
            {
                _logService.LogMessage(new LogMessage(this, LogEventCategory.Warning,
                    "Exposure done but image not ready, exposure must have been aborted."));

                _isExposuring = false;

                if (OnExposureCompleted != null && !garbageFrame)
                    OnExposureCompleted(false, null);

                return false;
            }
            

        }