Пример #1
0
        private int pixeldepth = 16;  //Fixed pixel depth -- May be changed latger

        public ImageArray(string filepath)
        //Open a new integer array representing the contents of a TSX image
        //  get and store the width and height in pixels for changes
        //  close the TSX window
        {
            ccdsoftImage tsx_im = new ccdsoftImage();

            imageFilePath = filepath;
            tsx_im.Path   = imageFilePath;
            tsx_im.Open();
            //tsx_im.AttachToActive();
            var img = tsx_im.DataArray;
            var pix = new int[img.Length];

            for (int i = 0; i < img.Length; i++)
            {
                pix[i] = Convert.ToInt32(img[i]);
            }
            imagePixels          = pix;
            pixelSizeX           = tsx_im.WidthInPixels;
            pixelSizeY           = tsx_im.HeightInPixels;
            tsx_im.DetachOnClose = 0;
            tsx_im.Close();
            tsx_im = null;
            pix    = null;
            GC.Collect();
            return;
        }
Пример #2
0
        private int FindClosestLightSource(ccdsoftImage tsxim, double sRA, double sDec, int pDistance)
        {
            //Searches for a "near" light source to the location SRA, SDec and returns it//s index
            //if not, then -1 is returned

            tsxim.RADecToXY(sRA, sDec);
            double tLocX = tsxim.RADecToXYResultX();
            double tLocY = tsxim.RADecToXYResultY();

            double tLhighX = tLocX + pDistance;
            double tLlowX  = tLocX - pDistance;
            double tLhighY = tLocY + pDistance;
            double tLlowY  = tLocY - pDistance;

            var rXArr = tsxim.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryX);
            var rYArr = tsxim.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryY);

            for (int iR = 0; iR < rXArr.Length; iR++)
            {
                if ((rXArr[iR] < tLhighX) &&
                    (rXArr[iR] > tLlowX) &&
                    (rYArr[iR] < tLhighY) &&
                    (rYArr[iR] > tLlowY))
                {
                    return(iR);
                }
            }
            return(-1);   //Error return
        }
Пример #3
0
        private TargetData SearchForLightSourceInventory(ccdsoftImage tsximg, TargetData lightSource)
        {
            sky6Utils tsxu   = new sky6Utils();
            double    ra     = lightSource.TargetRA;
            double    dec    = lightSource.TargetDec;
            double    rDelta = 1000;
            double    rmsDelta;
            int       sIndex = -1;

            for (int iSource = 0; iSource < XPosArr.Length; iSource++)
            {
                tsximg.XYToRADec((double)XPosArr[iSource], (double)YPosArr[iSource]);
                double raSrc  = tsximg.XYToRADecResultRA();
                double decSrc = tsximg.XYToRADecResultDec();;
                tsxu.ComputeAngularSeparation(ra, dec, raSrc, decSrc);
                rmsDelta = tsxu.dOut0;
                if (rmsDelta <= rDelta)
                {
                    rDelta = rmsDelta;
                    sIndex = iSource;
                    lightSource.InventoryArrayIndex         = sIndex;
                    lightSource.TargetToSourcePositionError = rDelta * 3600.0;
                    lightSource.SourceRA  = raSrc;
                    lightSource.SourceDec = decSrc;
                    lightSource.SourceUncorrectedMagnitude = (double)MagArr[sIndex];
                    lightSource.SourceX = (double)XPosArr[sIndex];
                    lightSource.SourceY = (double)YPosArr[sIndex];
                }
            }
            return(lightSource);
        }
Пример #4
0
        public static void SaveFlatImage(string targetName, string filterName, string targetPA, string sidePoint)
        {
            //The NH image directory originates from the SetUp form and stored in the
            //Configuration file.
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);
            //Get Humason directory name, create image directory if it doesn't exist yet
            string nhDirName      = openSession.HumasonDirectoryPath;
            string nhImageDirName = nhDirName + "\\Images";

            if (!Directory.Exists(nhImageDirName))
            {
                Directory.CreateDirectory(nhImageDirName);
            }
            //Create date name for image sub-directory, create if it doesn't exist yet
            DateTime sequenceStartDate = tPlan.SequenceStartTime;
            string   targetImageDir    = nhImageDirName + "\\" + sequenceStartDate.ToString("yyyyMMdd");

            if (!Directory.Exists(targetImageDir))
            {
                Directory.CreateDirectory(targetImageDir);
            }
            //Create Data Files directory if it doesn't exit yet
            string targetImageDataDir = targetImageDir + "\\Calibration Files";

            if (!Directory.Exists(targetImageDataDir))
            {
                Directory.CreateDirectory(targetImageDataDir);
            }

            //Reduce target PA to integer string, i.e. scrape off the decimal
            targetPA = (Convert.ToDouble(targetPA)).ToString("0");
            string targetImageDataPath = targetImageDataDir + "\\" +
                                         filterName +
                                         targetName +
                                         "_" +
                                         targetPA +
                                         "PA" +
                                         sidePoint +
                                         "." +
                                         openSession.SequentialFileNumber.ToString() +
                                         ".fit";
            //open TSX camera and get the last image
            ccdsoftImage tsxi      = new ccdsoftImage();
            int          camStatus = tsxi.AttachToActiveImager();

            //save handling an exception here until some future date
            tsxi.setFITSKeyword("OBJECT", "Humason Flat Field");
            AstroImage tsxc = new AstroImage();

            if (tPlan.RotatorEnabled)
            {
                tsxi.setFITSKeyword("ROTATOR", Rotator.RealRotatorPA.ToString());
            }
            //Set save path and save
            tsxi.Path = targetImageDataPath;
            tsxi.Save();
            lg.LogIt("Flat saved: " + targetImageDataPath);
        }
Пример #5
0
        public FormTargetImageAnalysis()
        {
            initFlag = true;
            InitializeComponent();
            SeeingGroupBox.ForeColor           = Color.White;
            TargetPhotometryGroupBox.ForeColor = Color.White;
            FitsImageDataBox.ForeColor         = Color.White;
            InstrumentationGroupBox.ForeColor  = Color.White;
            FitsImageDataBox.ForeColor         = Color.White;
            StatisticsGroupBox.ForeColor       = Color.White;
            TargetedVariableGroupBox.ForeColor = Color.White;
            ImagePickListGroupBox.ForeColor    = Color.White;
            NearestSourceGroupBox.ForeColor    = Color.White;
            SourceGroupBox.ForeColor           = Color.White;
            Utility.ButtonGreen(BreakButton);
            Utility.ButtonGreen(DoneButton);
            // Acquire the version information and put it in the form header
            try { this.Text = ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString(); }
            catch { this.Text = " in Debug"; } //probably in debug, no version info available
            this.Text = "VariScan V" + this.Text;
            //Create a single, reusable object for connecting to multiple TSX images, otherwise garbage collection is a problem
            TSX_Image = new ccdsoftImage();
            //Populate variable list box in the form
            List <string> tdirs = VariScanFileManager.GetVaultList();

            foreach (string t in tdirs)
            {
                SelectTargetListBox.Items.Add(VariScanFileManager.StripPath(t));
            }
            Configuration cfg = new Configuration();

            OnTopCheckBox.Checked = Convert.ToBoolean(cfg.AnalysisFormOnTop);
            this.TopMost          = OnTopCheckBox.Checked;
            initFlag = false;
        }
Пример #6
0
        public ImageArray(int xSize, int ySize)
        //Open a new integer array without a file connection
        //  get and store the width and height in pixels for changes
        //  close the TSX window
        {
            //Might want to check for excessively large array here
            ccdsoftImage tsx_im = new ccdsoftImage();

            tsx_im.New(xSize, ySize, pixeldepth);
            var img = tsx_im.DataArray;
            var pix = new int[img.Length];

            for (int i = 0; i < img.Length; i++)
            {
                pix[i] = Convert.ToInt32(img[i]);
            }
            imagePixels          = pix;
            pixelSizeX           = tsx_im.WidthInPixels;
            pixelSizeY           = tsx_im.HeightInPixels;
            tsx_im.DetachOnClose = 0;
            tsx_im.Close();
            tsx_im = null;
            pix    = null;
            GC.Collect();
            return;
        }
Пример #7
0
            public XYToRADec(string wcsfilepath, double Xpos, double Ypos)
            {
                //Open reference image in TSX.  Plate solve.
                ccdsoftImage tsx_img = new ccdsoftImage();

                tsx_img.Path = wcsfilepath;
                tsx_img.Open();
                tsx_img.DetachOnClose = 0;
                try
                {
                    tsx_img.InsertWCS(true);
                }
                catch
                {
                    tsx_img.Close();
                    plateSolve = false;
                    return;
                }
                tsx_img.XYToRADec(Xpos, Ypos);
                targetRA    = tsx_img.XYToRADecResultRA();
                targetDec   = tsx_img.XYToRADecResultDec();
                northangle  = tsx_img.NorthAngle;
                imagescale  = tsx_img.ScaleInArcsecondsPerPixel;
                imagewidth  = tsx_img.WidthInPixels;
                imageheight = tsx_img.HeightInPixels;
                plateSolve  = true;
                tsx_img.Close();
                return;
            }
Пример #8
0
        public static bool DialogOpenImageFile(ccdsoftImage tsximg, string agnName)
        {
            using (OpenFileDialog imageFileDialog = new OpenFileDialog())
            {
                imageFileDialog.Filter = "*.fit|*.fit";
                Configuration cfg = new Configuration();
                string        imageFileDirectory = cfg.ImageBankFolder + "\\" + agnName;
                if (Directory.Exists(imageFileDirectory))
                {
                    imageFileDialog.InitialDirectory = imageFileDirectory;
                    if (imageFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        tsximg.Path = imageFileDialog.FileName;
                        try { tsximg.Open(); }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                            return(false);
                        }

                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                return(false);
            }
        }
Пример #9
0
        private int GetFitsInteger(ccdsoftImage tsximg, string keyWord)
        {
            int keyValue;

            try { keyValue = tsximg.FITSKeyword(keyWord); }
            catch { return(0); }
            return(keyValue);
        }
Пример #10
0
        private double?GetFits(ccdsoftImage tsximg, string keyWord)
        {
            double?keyValue;

            try { keyValue = tsximg.FITSKeyword(keyWord); }
            catch { return(null); }
            return(keyValue);
        }
Пример #11
0
        private string GetFitsString(ccdsoftImage tsximg, string keyWord)
        {
            string keyValue;

            try { keyValue = tsximg.FITSKeyword(keyWord); }
            catch { return("None"); }
            return(keyValue);
        }
Пример #12
0
 public static bool AttachFitsFile(ccdsoftImage tsximg)
 {
     try { tsximg.AttachToActive(); }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message);
         return(false);
     }
     return(true);
 }
Пример #13
0
        private bool OptimizeExposure(double maxExposure)
        {
            //Subframe size
            const int subFrameSize = 192;
            //Subframe the center in order to get rid of any brighter outliers
            const int    testExposure = 10;
            const double minExposure  = 0.1;

            ccdsoftImage tsxi = new ccdsoftImage();

            tsxi.AttachToActive();  //We should have a CLS image handy
            double xcenter = tsxi.WidthInPixels / 2;
            double ycenter = tsxi.HeightInPixels / 2;
            //Set up 64 pixel square subframe
            int subTop    = (int)ycenter - subFrameSize / 2; //Y is top down
            int subBottom = (int)ycenter + subFrameSize / 2; //Y is top down
            int subRight  = (int)xcenter + subFrameSize / 2;
            int subLeft   = (int)xcenter - subFrameSize / 2;

            Configuration cfg    = new Configuration();
            int           ADUMax = Convert.ToInt32(cfg.ADUMax);

            ccdsoftCamera tsx_cc = new ccdsoftCamera
            {
                AutoSaveOn           = 0, //Autosave Off
                FilterIndexZeroBased = freshImageFilter,
                ExposureTime         = testExposure,
                Subframe             = 1,
                SubframeTop          = subTop,
                SubframeBottom       = subBottom,
                SubframeLeft         = subLeft,
                SubframeRight        = subRight,
                Frame          = ccdsoftImageFrame.cdLight,
                ImageReduction = ccdsoftImageReduction.cdAutoDark,
                Asynchronous   = 0      //Asynchronous off for this short shot
            };

            do
            {
                tsx_cc.TakeImage();
                double maxPixel        = tsx_cc.MaximumPixel;
                double correctExposure = (ADUMax / maxPixel) * tsx_cc.ExposureTime;
                if (correctExposure > maxExposure)
                {
                    correctExposure = maxExposure;
                }
                freshImageExposure = correctExposure;
                if (maxPixel > ADUMax)
                {
                    tsx_cc.ExposureTime = freshImageExposure;
                }
            } while (tsx_cc.MaximumPixel > ADUMax && freshImageExposure > minExposure);
            return(true);
        }
Пример #14
0
 public static bool DirectOpenFitsFile(ccdsoftImage tsximg, string filePath)
 {
     tsximg.Path = filePath;
     try { tsximg.Open(); }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message);
         return(false);
     }
     return(true);
 }
Пример #15
0
        //Take an image via TSX.  Set the autosave path to the FreshImage path;
        //  Set exposureTime, Light Frame, AutoDark, No Autosave, Asynchronous
        //  then TakeImage
        //  Wait for completion status, then return
        //
        //  Removed subframe setting on request for cameras with long download times

        private void ShootGalaxy()
        {
            Configuration sscf   = new Configuration();
            ccdsoftImage  tsx_im = new ccdsoftImage
            {
                Path = sscf.FreshImagePath
            };
            ccdsoftCamera tsx_cc = new ccdsoftCamera
            {
                AutoSaveOn           = 0, //Autosave Off
                FilterIndexZeroBased = Convert.ToInt32(sscf.Filter),
                ExposureTime         = Convert.ToDouble(sscf.Exposure),
                //Subframe = 0,
                Frame = ccdsoftImageFrame.cdLight,
                //ImageReduction = ccdsoftImageReduction.cdAutoDark,
                Asynchronous = 1        //Asynchronous on
            };

            switch (sscf.CalibrationType)
            {
            case "None":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdNone;
                break;
            }

            case "Auto":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdAutoDark;
                break;
            }

            case "Full":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdBiasDarkFlat;
                break;
            }
            }
            LogEntry("Imaging target for " + sscf.Exposure + " secs");
            tsx_cc.TakeImage();
            //Wait for completion
            while (tsx_cc.State != ccdsoftCameraState.cdStateNone)
            {
                System.Threading.Thread.Sleep(1000);
                System.Windows.Forms.Application.DoEvents();
            }
            tsx_im.AttachToActiveImager();
            tsx_im.Save();
            freshImagePath = sscf.FreshImagePath;
            LogEntry("Imaging Complete");
            return;
        }
Пример #16
0
        private double PlateSolve()
        {
            //runs an image link on the current location to get PA data
            //assume camera, mount etc are connected and properly configured.
            ccdsoftCamera tsxcc = new ccdsoftCamera
            {
                Autoguider   = 0,
                Frame        = ccdsoftImageFrame.cdLight,
                ExposureTime = 10,
                Delay        = 0,
                Asynchronous = 0,
                AutoSaveOn   = 1,
                Subframe     = 0
            };

            try { tsxcc.TakeImage(); }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
                return(0);
            }

            ccdsoftImage tsxi  = new ccdsoftImage();
            ImageLink    tsxil = new ImageLink
            {
                pathToFITS = tsxcc.LastImageFileName,
                scale      = 1.70
            };

            try { tsxil.execute(); }
            catch (Exception ex)
            {
                return(0);
            }
            ImageLinkResults tsxir = new ImageLinkResults();
            double           iPA   = tsxir.imagePositionAngle;

            //Check for image link success, return 0 if not.
            if (tsxir.succeeded == 1)
            {
                return(iPA);
            }
            else
            {
                return(0);
            }
        }
Пример #17
0
        public void Shoot(string gName, double expTime)
        {
            //Take a fresh image at 600 seconds
            //That will be placed in the
            Configuration sscfg  = new Configuration();
            ccdsoftImage  tsx_im = new ccdsoftImage();
            ccdsoftCamera tsx_cc = new ccdsoftCamera();

            tsx_im.Path       = FollowUpPath + "\\" + gName + ".fit";
            tsx_cc.AutoSaveOn = 0;          //Autosave Off
            //No filter change
            tsx_cc.ExposureTime   = expTime;
            tsx_cc.Frame          = ccdsoftImageFrame.cdLight;
            tsx_cc.ImageReduction = ccdsoftImageReduction.cdAutoDark;
            switch (sscfg.CalibrationType)
            {
            case "None":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdNone;
                break;
            }

            case "Auto":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdAutoDark;
                break;
            }

            case "Full":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdBiasDarkFlat;
                break;
            }
            }
            tsx_cc.Asynchronous = 0;        //Asynchronous on

            tsx_cc.TakeImage();
            //Wait for completion
            while (tsx_cc.State != ccdsoftCameraState.cdStateNone)
            {
                System.Threading.Thread.Sleep(1000);
                System.Windows.Forms.Application.DoEvents();
            }
            tsx_im.AttachToActiveImager();
            tsx_im.Save();
        }
Пример #18
0
        public Fits(ccdsoftImage tsximg)
        {
            //Using FITS file information...
            //Compute pixel scale = 206.256 * pixel size (in microns) / focal length
            FitsTarget = GetFitsString(tsximg, "OBJECT");
            string fitsUDT = GetFitsString(tsximg, "DATE-OBS").Split('.')[0];

            //DateTime utcDT = DateTime.ParseExact(fitsUDT,"yyyy-MM-ddTHH:mm:ss", CultureInfo.CurrentCulture);
            //Gregorian Calander culture doesn't work in 64 bits -- wrote my own parser
            string[] dsts   = fitsUDT.Split('T');
            string[] ds     = dsts[0].Split('-');
            string[] dt     = dsts[1].Split(':');
            int      year   = Convert.ToInt16(ds[0]);
            int      month  = Convert.ToInt16(ds[1]);
            int      day    = Convert.ToInt16(ds[2]);
            int      hour   = Convert.ToInt16(dt[0]);
            int      minute = Convert.ToInt16(dt[1]) % 60;
            int      second = Convert.ToInt16(dt[2]);
            //
            DateTime utcDT = new DateTime(year, month, day, hour, minute, second);

            FitsUTCDate     = utcDT.Date.ToShortDateString();
            FitsUTCTime     = utcDT.TimeOfDay.ToString();
            FitsUTCDateTime = utcDT;
            PixSize         = GetFits(tsximg, "XPIXSZ");
            PixSize         = GetFits(tsximg, "XPIXELSZ") ?? PixSize;
            Gain            = GetFits(tsximg, "EGAIN");
            FocalLength     = GetFits(tsximg, "FOCALLEN");
            Aperture        = GetFits(tsximg, "APTDIA");
            Exposure        = GetFits(tsximg, "EXPTIME");
            Filter          = GetFitsString(tsximg, "FILTER");
            PixBits         = (int)GetFits(tsximg, "BITPIX");
            ImagePixWidth   = (int)(tsximg.FITSKeyword("NAXIS1") ?? 0);
            ImagePixHeight  = (int)(tsximg.FITSKeyword("NAXIS2") ?? 0);
            BinX            = (int)tsximg.FITSKeyword("XBINNING");
            BinY            = (int)tsximg.FITSKeyword("YBINNING");
            FitsRA          = GetFits(tsximg, "OBJCTRA");
            FitsDec         = GetFits(tsximg, "OBJCTDEC");
            try { Pedistal = (int)(tsximg.FITSKeyword("PEDISTAL") ?? 0); }
            catch { Pedistal = 0; }
            FitsAirMass = GetFits(tsximg, "AIRMASS");
        }
Пример #19
0
 public static bool DialogOpenFitsFile(ccdsoftImage tsximg)
 {
     using (OpenFileDialog fitsDialog = new OpenFileDialog())
     {
         fitsDialog.Filter = "*.fit|*.fit";
         if (fitsDialog.ShowDialog() == DialogResult.OK)
         {
             tsximg.Path = fitsDialog.FileName;
             try { tsximg.Open(); }
             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message);
                 return(false);
             }
             return(true);
         }
         else
         {
             return(false);
         }
     }
 }
Пример #20
0
            public RADecToXY(string wcsfilepath, double tRA, double tDec)
            {
                //Open reference image in TSX.  Plate solve.
                ccdsoftImage tsx_img = new ccdsoftImage();

                tsx_img.Path = wcsfilepath;
                tsx_img.Open();
                tsx_img.DetachOnClose = 0;
                try
                {
                    tsx_img.InsertWCS(true);
                }
                catch
                {
                    tsx_img.Close();
                    plateSolveResult = false;
                    return;
                }
                tsx_img.RADecToXY(tRA, tDec);
                targetX     = Convert.ToInt32(tsx_img.RADecToXYResultX());
                targetY     = Convert.ToInt32(tsx_img.RADecToXYResultY());
                northangle  = tsx_img.NorthAngle;
                imagescale  = tsx_img.ScaleInArcsecondsPerPixel;
                imagewidth  = tsx_img.WidthInPixels;
                imageheight = tsx_img.HeightInPixels;
                //Check for some catastrophic problem with the image link result
                if ((targetX < 0) || (targetX > imagewidth) || (targetY < 0) || (targetY > imageheight))
                {
                    plateSolveResult = false;
                }
                else
                {
                    plateSolveResult = true;
                };

                tsx_img.Close();
                return;
            }
Пример #21
0
        static double PlateSolve()
        {
            //runs an image link on the current location to get PA data
            //assume camera, mount etc are connected and properly configured.
            ccdsoftCamera tsxcc = new ccdsoftCamera
            {
                Autoguider   = 0,
                Frame        = ccdsoftImageFrame.cdLight,
                ExposureTime = 10,
                Delay        = 0,
                Asynchronous = 0,
                AutoSaveOn   = 1
            };

            tsxcc.TakeImage();

            ccdsoftImage tsxi  = new ccdsoftImage();
            ImageLink    tsxil = new ImageLink
            {
                scale      = TSXLink.FOVI.GetFOVScale(), //set Scale
                pathToFITS = tsxcc.LastImageFileName
            };

            tsxil.execute();
            ImageLinkResults tsxir = new ImageLinkResults();
            double           iPA   = tsxir.imagePositionAngle;

            //Check for image link success, return 0 if not.
            if (tsxir.succeeded == 1)
            {
                return(iPA);
            }
            else
            {
                return(0);
            }
        }
Пример #22
0
        public void Store(string filepath)
        //Saves the image data as a new file through TSX
        //Adjust to 256 bit depth because TSX DataArray is still broken
        //  Change later
        {
            double       bitdepth = 256;
            ccdsoftImage tsx_im   = new ccdsoftImage();

            tsx_im.New(pixelSizeX, pixelSizeY, pixeldepth);
            var imgarr = tsx_im.DataArray;

            for (int i = 0; i < imagePixels.Length; i++)
            {
                imgarr[i] = imagePixels[i] / bitdepth;
            }
            tsx_im.DataArray = imgarr;
            tsx_im.Path      = filepath;
            tsx_im.Save();
            tsx_im.DetachOnClose = 0;
            tsx_im.Close();
            tsx_im = null;
            GC.Collect();
            return;
        }
Пример #23
0
 public SexTractor()
 {
     //ccdsoftCamera tsxa = new ccdsoftCamera();
     timg = new ccdsoftImage();
     return;
 }
Пример #24
0
 public SexTractor()
 {
     timg = new ccdsoftImage();
 }
Пример #25
0
 public static void CloseFitsFile(ccdsoftImage tsximg)
 {
     try { tsximg.Close(); }
     catch { return; };
     return;
 }
Пример #26
0
        public void ExposureAnalysis()
        {
            //Create image object
            ccdsoftImage tsx_im = new ccdsoftImage();
            int          imgerr = 0;

            //Open the active image, if any
            try
            {
                imgerr = tsx_im.AttachToActiveImager();
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("No Image Available:  " + imgerr.ToString());
                return;
            }

            string resultstr;
            int    totalexp = 60;   //Minutes for total exposure sequence

            double gain     = 0.37; //electrons per ADU for SBIG STF8000M as spec//d
            double pedestal = 0;    //base pedestal
            double rnoise   = 9.3;  //read out noise in electrons
            double noisefac = 0.05; //maximum tolerable contribution of readout noise
            double slambda  = 15;   //Faint target ADU minimum
            double snrtgt   = 0.9;  //fraction of maximum achievable signal to noise ratio (Cannistra)

            int px;
            int py;
            int pxbin;
            int pybin;

            double exptime;

            double avgABU;
            double esky;
            double torn;

            int exp1;
            int reps1;
            int exp2;
            int reps2;
            int exp3;
            int reps3;

            //Presumably an Image Link has already been performed
            //Check on this is TBD

            px    = tsx_im.FITSKeyword("NAXIS1");
            py    = tsx_im.FITSKeyword("NAXIS2");
            pxbin = tsx_im.FITSKeyword("XBINNING");
            pybin = tsx_im.FITSKeyword("YBINNING");
            //gain = tsx_im.FITSKeyword("EGAIN");
            exptime = tsx_im.FITSKeyword("EXPTIME");

            px = px - 1;
            py = py - 1;

            avgABU = tsx_im.averagePixelValue();
            esky   = ((avgABU - pedestal) * gain) / exptime;
            torn   = Math.Pow(rnoise, 2) / ((Math.Pow((1 + noisefac), 2) - 1) * esky);

            exp1  = (int)(torn / 2);
            reps1 = (int)((((totalexp * 60) / torn) - 1) * 2);
            exp2  = (int)((slambda * Math.Sqrt(totalexp * 60)) / (2 * Math.Sqrt(avgABU / exptime)));
            reps2 = (int)((totalexp * 60) / exp2);
            exp3  = (int)((Math.Pow(snrtgt, 2) * Math.Pow(rnoise, 2)) / ((esky) * (1 - Math.Pow(snrtgt, 2))));
            reps3 = (int)((totalexp * 60) / exp3);

            i_smith_exp  = exp1;
            i_smith_rep  = reps1;
            i_anstey_exp = exp2;
            i_anstey_rep = reps2;
            i_anstey_exp = exp3;
            i_anstey_rep = reps3;

            resultstr = ("Smith Model (at tolerable noise factor = 0.05):" + "\r\n" +
                         "     " + exp1.ToString() + " second exposure with" + "\r\n" +
                         "     " + reps1.ToString() + " repetitions per hour." + "\r\n" + "\r\n" +
                         "Anstey Model (at faint target minimum = 15):" + "\r\n" +
                         "     " + exp2.ToString() + " second exposure with" + "\r\n" +
                         "     " + reps2.ToString() + " repetitions per hour." + "\r\n" + "\r\n" +
                         "Cannestra Model (at SNR = 90% of maximum):" + "\r\n" +
                         "     " + exp3.ToString() + " second exposure with" + "\r\n" +
                         "     " + reps3.ToString() + " repetitions per hour.");

            System.Windows.Forms.MessageBox.Show(resultstr, "Results", System.Windows.Forms.MessageBoxButtons.OK);
        }
Пример #27
0
        private bool ShootTarget(TargetList.TargetXDescriptor currentTarget)
        {
            Configuration cfg         = new Configuration();
            int           repetitions = Convert.ToInt32(cfg.ImagesPerSample);
            ccdsoftCamera tsx_cc      = new ccdsoftCamera
            {
                AutoSaveOn           = 0, //Autosave Off
                FilterIndexZeroBased = freshImageFilter,
                ExposureTime         = freshImageExposure,
                Subframe             = 0,
                Frame        = ccdsoftImageFrame.cdLight,
                Asynchronous = 1        //Asynchronous on
            };

            //Set up for noise reduction, if any
            switch (cfg.CalibrationType)
            {
            case "None":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdNone;
                LogEntry("No image calibration.");
                break;
            }

            case "Auto":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdAutoDark;
                LogEntry("Auto Dark image calibration set");
                break;
            }

            case "Full":
            {
                tsx_cc.ImageReduction = ccdsoftImageReduction.cdBiasDarkFlat;
                Reduction calLib  = new Reduction();
                string    binning = "1X1";
                int       camTemp = (int)tsx_cc.TemperatureSetPoint;
                if (!calLib.SetReductionGroup(freshImageFilter, freshImageExposure, camTemp, binning))
                {
                    LogEntry("No calibration library found: " + "B_" + binning + "T_" + camTemp + "E_" + freshImageFilter.ToString("0") + "F_" + freshImageFilter.ToString("0"));
                    return(false);

                    break;
                }
                LogEntry("Full image calibration set: " + calLib.ReductionGroupName);
                break;
            }
            }
            //Loop on repetitions of image
            do
            {
                SetNextImagePath(cfg.ImageBankFolder + "\\" + freshImageName);
                ccdsoftImage tsx_im = new ccdsoftImage
                {
                    Path = freshImagePath
                };

                LogEntry("Imaging " + currentTarget.Name + " at RA: " + Utility.SexidecimalRADec(freshImageRA, true) +
                         " / Dec: " + Utility.SexidecimalRADec(freshImageDec, false));
                LogEntry("Filter set to " + freshImageFilter.ToString("0"));
                LogEntry("Imaging target for " + freshImageExposure.ToString("0.0") + " secs");
                tsx_cc.TakeImage();
                //Wait for completion
                while (tsx_cc.State != ccdsoftCameraState.cdStateNone)
                {
                    System.Threading.Thread.Sleep(1000);
                    System.Windows.Forms.Application.DoEvents();
                }
                tsx_im.AttachToActiveImager();
                tsx_im.setFITSKeyword("OBJECT", freshImageName);
                tsx_im.Save();
                repetitions--;
            } while (repetitions > 0);
            LogEntry("Imaging target Complete");
            return(true);
        }
Пример #28
0
        public bool NewStar(string gname, string dfilepath, string rfilepath)
        {
            //Look for star-like reminant in difference image using the TSX "ShowInventory" (Sextractor) function
            //   return true if star-like object found, false if not.
            //

            //Open a new TSX Image object, then load and open difference image
            ccdsoftImage tsx_dif = new ccdsoftImage();

            tsx_dif.Path = dfilepath;
            tsx_dif.Open();
            //Prepare TSX to close the image window when closing the image
            tsx_dif.DetachOnClose = 0;
            //Look for stars using Sextractor
            //  If fails, close the object and image
            try
            {
                int tdstat = tsx_dif.ShowInventory();
            }
            catch
            {
                tsx_dif.Close();
                LogEntry("No suspects:  Sextractor failed on Difference Image.");
                return(false);
            }
            // Sextractor didnt// run into any problems, but may have found nothing
            //   Check how many objects found, if none then close up and return false
            //   If something is found, then leave the window open and return "true"
            var dMagArr = tsx_dif.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryMagnitude);
            //double[] FWHMArr = Convert.ToDouble(tDiff.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryFWHM));
            var dXPosArr = tsx_dif.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryX);
            var dYPosArr = tsx_dif.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryY);
            //double[] ElpArr = Convert.ToDouble(tDiff.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryEllipticity));
            var dClsArr = tsx_dif.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryClass);

            if (dMagArr.Length == 0)
            {
                tsx_dif.Close();
                LogEntry("No suspects:  No light sources found on Difference Image.");
                return(false);
            }
            else
            {
                //We have at least one hit in the box.  Now look to see if any don//t match up with
                //  light sources found in the reduced reference image.
                //Open a new TSX Image object, then load and open difference image
                ccdsoftImage tsx_ref = new ccdsoftImage();
                tsx_ref.Path = rfilepath;
                tsx_ref.Open();
                //Prepare TSX to close the image window when closing the image
                tsx_ref.DetachOnClose = 0;
                //Look for stars using Sextractor
                //  If fails, close the object and image
                try
                {
                    int cdstat = tsx_ref.ShowInventory();
                }
                catch
                {
                    tsx_ref.Close();
                    tsx_dif.Close();
                    LogEntry("No suspects:  Sextractor failed on Reference Image.");
                    return(false);
                }
                // Sextractor didnt// run into any problems, but may have found nothing
                //   Check how many objects found, if none then close up and return false
                //   If something is found, then leave the window open and return "true"
                var rMagArr = tsx_ref.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryMagnitude);
                //double[] FWHMArr = Convert.ToDouble(tDiff.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryFWHM));
                var rXPosArr = tsx_ref.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryX);
                var rYPosArr = tsx_ref.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryY);
                //double[] ElpArr = Convert.ToDouble(tDiff.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryEllipticity));
                var rClsArr = tsx_ref.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryClass);
                //So let//s make being within 20 pixels (40 arcsec) of each other sufficient for calling two light sources the same.
                //Proceed through the light source array looking for matches, there shouldn//t be many
                int     proximity = 20;
                Boolean nomatch;
                for (int di = 0; di < dXPosArr.Length; di++)
                {
                    double dXpos = Convert.ToDouble(dXPosArr[di]);
                    double dYpos = Convert.ToDouble(dYPosArr[di]);
                    double dCls  = Convert.ToDouble(dClsArr[di]);
                    nomatch = true;
                    if (dCls >= 0.8)
                    {
                        for (int ri = 0; ri < rXPosArr.Length; ri++)
                        {
                            double rXpos = Convert.ToDouble(rXPosArr[ri]);
                            double rYpos = Convert.ToDouble(rYPosArr[ri]);

                            if ((Math.Abs(dXpos - rXpos) <= proximity) && (Math.Abs(dYpos - rYpos) <= proximity))
                            {
                                nomatch = false;
                                break;
                            }
                        }
                        if (nomatch)
                        {
                            // A suspect has been found. Log it//s x,y location on the Difference image, then
                            //  Get its location (RA,Dec) by using XYToRADec method that runs yet another Image Link
                            //  on the current image file (not the cropped one), extrapolating the cropped difference image x,y
                            //  to the uncropped current image, then using TSX to convert the extrapolated X,Y to an RA,Dec.
                            //
                            //  Add to Suspect List then, log, close, collect and return

                            //  We may do more later...
                            LogEntry("Suspect without alibi in " + dfilepath + " at X= " + Convert.ToInt32(dXpos) + "   Y= " + Convert.ToInt32(dYpos));

                            double    xCurPos = ((dXpos - (tsx_dif.WidthInPixels) / 2)) + (grandeWidth / 2);
                            double    yCurPos = ((dYpos - (tsx_dif.HeightInPixels) / 2)) + (grandeHeight / 2);
                            XYToRADec ss_perp = new XYToRADec(curImagePath, xCurPos, yCurPos);
                            double    pRA     = ss_perp.RA;
                            double    pDec    = ss_perp.Dec;
                            LogEntry("Suspect//s coordinates (RA,Dec) = " + pRA.ToString() + " Hrs, " + pDec.ToString() + " Deg");

                            //Now create a new entry and save the suspect in the suspect file
                            Suspect ss_sus = new Suspect();
                            ss_sus.GalaxyName = gname;
                            ss_sus.Event      = DateTime.Now;
                            ss_sus.SuspectRA  = pRA;
                            ss_sus.SuspectDec = pDec;
                            ss_sus.SuspectCurrentLocationX = dXpos;
                            ss_sus.SuspectCurrentLocationY = dYpos;
                            ss_sus.Store();

                            tsx_dif.Close();
                            tsx_dif = null;
                            tsx_ref.Close();
                            tsx_ref = null;
                            ss_perp = null;
                            ss_sus  = null;
                            GC.Collect();
                            return(true);
                        }
                    }
                }
                //If no suspects found, log, close, collect and return;
                LogEntry("All suspects have alibis from Reference image.");
                tsx_dif.Close();
                tsx_dif = null;
                tsx_ref.Close();
                tsx_ref = null;
                return(false);
            }
        }
Пример #29
0
    /// Windows C# Sample Console Application: ImageAnalysis
    ///
    /// ------------------------------------------------------------------------
    ///
    ///               Author: R.McAlister (2017)
    ///
    /// ------------------------------------------------------------------------
    ///
    /// This application demonstrates some of the functionality of the ccdsoftCamera and Image classes
    ///
    /// The example takes a 60 second exposure then produces a recommendation window to display computed
    ///   optimal exposure length and duration for a one hour shoot, based on average background noise.
    ///
    /// The algorithms are based on work by ...
    ///   John Smith: http://www.hiddenloft.com/notes/SubExposures.pdf
    ///   Charles Anstey: http://www.cloudynights.com/item.php?item_id=1622
    ///   Steve Cannistra: http://www.starrywonders.com/snr.html
    ///
    /// Note:  Where the required parameters like "gain" are not supplied through TSX, they are arbitrarily set for
    ///   an SBIG STF8300
    ///
    public void ImageAnalysisSample()
    {
        ///Open camera control and connect it to hardware
        ccdsoftCamera tsx_cc = new ccdsoftCamera();

        try {
            tsx_cc.Connect();
        }
        catch {
            MessageBox.Show("Camera Connect Error");
        };

        ///turn on autosave
        tsx_cc.AutoSaveOn = 1;
        ///Set for 60 second exposure, light frame with autodark
        tsx_cc.ExposureTime         = 60;
        tsx_cc.Frame                = ccdsoftImageFrame.cdLight;
        tsx_cc.ImageReduction       = ccdsoftImageReduction.cdAutoDark;
        tsx_cc.FilterIndexZeroBased = 3;  ///Assumed Lumescent, but change accordingly
        tsx_cc.Delay                = 5;  ///Possible filter change = 5 sec delay
        tsx_cc.Asynchronous         = 1;  ///Going to do a wait loop
        tsx_cc.TakeImage();
        while (tsx_cc.State == ccdsoftCameraState.cdStateTakePicture)
        {
            System.Threading.Thread.Sleep(1000);
        }
        ;

        ///Create image object
        ccdsoftImage tsx_im = new ccdsoftImage();
        int          imgerr = 0;

        ///Open the active image, if any
        try {
            imgerr = tsx_im.AttachToActive();
        }
        catch {
            MessageBox.Show("No Image Available:  " + imgerr.ToString());
            return;
        };

        const int totalexp = 60; ///Minutes for total exposure sequence

        double dGain     = 0.37; ///electrons per ADU for SBIG STF8000M as spec///d
        int    iPedestal = 0;    ///base pedestal
        double dRnoise   = 9.3;  ///read out noise in electrons
        double dNoiseFac = 0.05; ///maximum tolerable contribution of readout noise
        double dExpFac   = 1;    ///Exposure reduction factor
        double dSLambda  = 15;   ///Faint target ADU minimum
        double dSNRMax   = 0.9;  ///fraction of maximum achievable signal to noise ratio (Cannistra)

        ///Presumably an Image Link has already been performed
        ///Check on this is TBD

        int iPX    = tsx_im.FITSKeyword("NAXIS1");
        int iPY    = tsx_im.FITSKeyword("NAXIS2");
        int iPXBin = tsx_im.FITSKeyword("XBINNING");
        int iPYBin = tsx_im.FITSKeyword("YBINNING");
        ///Dim igain as integer = tsx_im.FITSKeyword("EGAIN");         ///TSX doesn///t pick this up, yet
        double dExpTime = tsx_im.FITSKeyword("EXPTIME");

        iPX = iPX - 1;
        iPY = iPY - 1;

        double dAvgABU = tsx_im.averagePixelValue();
        double dEsky   = ((dAvgABU - iPedestal) * dGain) / dExpTime;
        double dTorn   = (System.Math.Pow(dRnoise, 2) / (((System.Math.Pow((1 + dNoiseFac), 2) - 1) * dEsky)));

        ///Smith algorithm
        int iExp1  = (int)(dTorn / 2);
        int iReps1 = (int)((((totalexp * 60) / dTorn) - 1) * 2);
        ///Anstey algorithm
        int iExp2  = (int)((dSLambda * System.Math.Sqrt(totalexp * 60)) / (2 * System.Math.Sqrt(dAvgABU / dExpTime)));
        int iReps2 = (int)((totalexp * 60) / iExp2);
        ///Cannestr algorithm
        int iExp3  = (int)((System.Math.Pow(dSNRMax, 2) * System.Math.Pow(dRnoise, 2)) / ((dEsky) * (1 - System.Math.Pow(dSNRMax, 2))));
        int iReps3 = (int)((totalexp * 60) / iExp3);

        ///Display Results
        MessageBox.Show("Smith Model (at tolerable noise factor = 0.05):" + "\r\n" +
                        "     " + iExp1.ToString() + " second exposure with" + "\r\n" +
                        "     " + iReps1.ToString() + " repetitions per hour." + "\r\n" + "\r\n" +
                        "Anstey Model (at faint target minimum = 15):" + "\r\n" +
                        "     " + iExp2.ToString() + " second exposure with" + "\r\n" +
                        "     " + iReps2.ToString() + " repetitions per hour." + "\r\n" + "\r\n" +
                        "Cannestra Model (at SNR = 90% of maximum):" + "\r\n" +
                        "     " + iExp3.ToString() + " second exposure with" + "\r\n" +
                        "     " + iReps3.ToString() + " repetitions per hour.");

        return;
    }
Пример #30
0
        public string Display(string galaxyName, double suspectRAhrs, double suspectDecdeg)
        {
            const int sampleSize = 20;

            //Test code for PlateSolve2 Wrapper
            //CancellationToken cToken;
            TargetName   = galaxyName;
            TargetRAhrs  = suspectRAhrs;
            TargetDecdeg = suspectDecdeg;
            string followUpfileName = FollowUpPath + "\\" + TargetName + ".fit";

            TargetImageDir = ImageBankPath + "\\" + TargetName;
            //Show suspect in astroimage form, if PlateSolve2 is installed
            // if not, then an exception will be thrown

            //
            //test code
            //fileName = "C:\\Users\\Rick McAlister\\Documents\\SuperScan\\Image Bank\\NGC 1023\\NGC 1023_2019-10-31-2138.fit";
            //fileName = "C:\\Users\\Rick McAlister\\Documents\\SuperScan\\Image Bank\\NGC 1023\\CurrentImage.fit";
            //

            TargetFits = new FitsFile(followUpfileName, true);
            double pixSize = 1;

            if (TargetFits.FocalLength != 0)
            {
                pixSize = (206.265 / TargetFits.FocalLength) * TargetFits.XpixSz;
            }
            //
            ccdsoftImage tsxim = new ccdsoftImage();

            tsxim.Path = FollowUpPath + "\\" + galaxyName + ".fit";
            tsxim.Open();
            //Try to image link.  If not successful, probably too few stars
            //  if so, just return out of this;
            ImageLink tsxil = new ImageLink();

            tsxil.pathToFITS = tsxim.Path;
            try { tsxil.execute(); }
            catch (Exception ex)
            {
                return("Image Link Error: " + ex.Message);
            }
            //Show pic on scrren
            tsxim.Visible = 0;

            ImageLinkResults tsxilr = new ImageLinkResults();
            int    rlt     = tsxilr.succeeded;
            string rltText = tsxilr.errorText;

            try
            {
                //tsxim.InsertWCS(true);
                tsxim.ShowInventory();
            }
            catch (Exception ex)
            {
                string evx = ex.Message;
                return(evx);
            }

            //Look for a light source within 10 pixels of the target RA/Dec
            //The developer is picking an arbitrary 10 pixel square box as "near"
            int iLS = FindClosestLightSource(tsxim, TargetRAhrs, TargetDecdeg, 10);

            if (iLS == -1)
            {
                return("No light source found at suspect location\r\n  **Aborting check**");
            }

            //Success -- light source at target location.  Get magnitude and X,Y coordinates for all light sources
            var rMagArr = tsxim.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryMagnitude);
            var rXArr   = tsxim.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryX);
            var rYArr   = tsxim.InventoryArray((int)ccdsoftInventoryIndex.cdInventoryY);

            double rMag;
            string cName;
            int    starIndex    = 0;
            int    starCount    = 0;
            int    minStarCount = sampleSize;
            double tMag         = rMagArr[iLS];

            //Collect a set of catalog stars that have positions that match up
            //  with reference light sources of similar intensity to the target
            //  light source.
            //
            //  first, create data arrays for reference magnitudes and catalog magnitudes
            double[] refMag = new double[sampleSize];
            double[] catMag = new double[sampleSize];
            double[] difMag = new double[sampleSize];
            //double[] meanDev = new double[sampleSize];
            //  second, create TSX objects for the star chart and object information
            sky6StarChart         tsxsc = new sky6StarChart();
            sky6ObjectInformation tsxoi = new sky6ObjectInformation();

            //loop over all the stars in the light source magnitude array,
            // or until a sufficient number of stars are found that match  up
            do
            {
                //Compare the reference light source magnitude to the target light source magnitude
                //  if within 1 magnitude of each other then look up the associated star, if any
                rMag = (double)rMagArr[starIndex];
                if (Math.Abs(tMag - rMag) <= 1.0)
                {
                    //Get the RA/Dec location of the reference light source
                    tsxim.XYToRADec(rXArr[starIndex], rYArr[starIndex]);
                    double rRA  = tsxim.XYToRADecResultRA();
                    double rDec = tsxim.XYToRADecResultDec();
                    //Center the star chart on the RA/Dec coordinates
                    tsxsc.RightAscension = rRA;
                    tsxsc.Declination    = rDec;
                    int Xcen = tsxsc.WidthInPixels / 2;
                    int Ycen = tsxsc.HeightInPixels / 2;
                    //find the star at the center of the chart
                    tsxsc.ClickFind(Xcen, Ycen);
                    //get the name of the star, if any
                    tsxoi.Property(Sk6ObjectInformationProperty.sk6ObjInfoProp_SOURCE_CATALOG);
                    string cSrc = tsxoi.ObjInfoPropOut;
                    //if there is a name, then get its properties
                    if (cSrc != "")
                    {
                        //Get the name of the star
                        tsxoi.Property(Sk6ObjectInformationProperty.sk6ObjInfoProp_NAME1);
                        cName = tsxoi.ObjInfoPropOut;
                        //Get the catalog magnitude of the star
                        tsxoi.Property(Sk6ObjectInformationProperty.sk6ObjInfoProp_MAG);
                        catMag[starCount] = tsxoi.ObjInfoPropOut;
                        refMag[starCount] = rMag;
                        starCount++;
                    }
                }
                starIndex++;
            } while ((starCount < minStarCount) && (starIndex < rMagArr.Length));

            //Compute the difference bewtween reference magnitude and catalog magnitude
            for (int i = 0; i < starCount; i++)
            {
                difMag[i] = refMag[i] - catMag[i];
            }
            //Compute the average difference
            double avgMagDif = 0;

            for (int i = 0; i < starCount; i++)
            {
                avgMagDif += difMag[i];
            }
            avgMagDif = avgMagDif / starCount;
            //Compute the mean square of the deviation
            double avgMagDev = 0;

            for (int i = 0; i < starCount; i++)
            {
                avgMagDev += Math.Pow((difMag[i] - avgMagDif), 2);
            }
            avgMagDev = Math.Sqrt(avgMagDev / starCount);

            //Compute the adjusted magnitude for target
            double avgTgtAdjMag = tMag - avgMagDif;
            //Compute the adjusted magnitude error
            double meanDevTgtAdjMag = avgMagDev;

            //Return center of starchart to target location
            //Set the center of view to the suspect//s RA/Dec and light up the target icon
            //
            //Recenter the star chart on the RA/Dec coordinates
            tsxsc.RightAscension = TargetRAhrs;
            tsxsc.Declination    = TargetDecdeg;
            int Xtcen = tsxsc.WidthInPixels / 2;
            int Ytcen = tsxsc.HeightInPixels / 2;

            //find the star at the center of the chart
            tsxsc.ClickFind(Xtcen, Ytcen);
            tsxoi.Property(Sk6ObjectInformationProperty.sk6ObjInfoProp_NAME1);
            string starName = tsxoi.ObjInfoPropOut;

            //Open astrodisplay form of follow up image

            tsxim = null;
            tsxoi = null;
            tsxsc = null;
            //Report on computed apparant magnitude
            return("Nearest star: " + starName + "\r\n" +
                   "Adjusted apparent magnitude = " +
                   avgTgtAdjMag.ToString() + "  +/- " +
                   meanDevTgtAdjMag.ToString());
        }