예제 #1
0
        private void ToTSXButton_Click(object sender, EventArgs e)
        {
            //Tries to look up the name in the target box.  If found, then a new target plan is
            //opened.  Disconnect the telescope (in case centering is forced), use the target box to find
            //and and center the star chart and FOV on the target.
            //If not throw a log entry and return;
            //Remove spaces from target name if any
            //PlanTargetBox.Text = PlanTargetBox.Text.Replace(" ", "");
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();

            NHUtil.ButtonRed(SelectButton);
            TSXLink.Target tgt = TSXLink.StarChart.FindTarget(PlanTargetBox.Text);
            if (tgt != null)
            {
                TSXLink.Connection.DisconnectDevice(TSXLink.Connection.Devices.Mount);
                TargetPlan newtPlan = new TargetPlan(tgt.Name);
                newtPlan.TargetPA            = TSXLink.FOVI.GetFOVPA;
                newtPlan.TargetAdjustEnabled = false;
                PlanTargetBox.Text           = newtPlan.TargetName;
                TSXLink.StarChart.SetFOV(2);
                LoadTargetPlanList();
                openSession.CurrentTargetName = newtPlan.TargetName;
                lg.LogIt("A new target plan has been created for " + newtPlan.TargetName);
            }
            else
            {
                lg.LogIt(PlanTargetBox.Text + ": target not found.");
            }
            NHUtil.ButtonGreen(SelectButton);
            Show();
        }
예제 #2
0
        public static void RunShutDownApp()
        {
            //If ShutDownOn is set, then RunShutDown gets the postscan filepath from the Humason config file, if any
            //  then launches it and waits for completion.

            SessionControl openSession = new SessionControl();
            Process        pSystemExe  = new Process();

            if (openSession.ShutDownFilePath != null)
            {
                LogEvent lg = new LogEvent();
                lg.LogIt("Running Shut Down Process");
                pSystemExe.StartInfo.FileName = openSession.ShutDownFilePath;
                try
                {
                    pSystemExe.Start();
                    if (openSession.IsShutDownWaitEnabled)
                    {
                        pSystemExe.WaitForExit();
                    }
                }
                catch { }
                lg.LogIt("Shut Down Process Complete");
            }
            return;
        }
예제 #3
0
        private void Presetbutton_Click(object sender, EventArgs e)
        {
            //Moves focuser to critical focus position for current temperature based on "Current.foc" focus training file:
            //   Checks for focuser connection
            //   Gets current temperature from focuser
            //   Calls function to compute new position from a selected focus training data file and current temperature
            //   Moves focuser to new position from current position

            NHUtil.ButtonRed(Presetbutton);
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            //Get a filter focus file path from the configuration file, then validate/change via dialog
            FilterFileDialog.InitialDirectory = openSession.FocuserDataFolder;
            FilterFileDialog.FileName         = "";

            DialogResult focusfilelist = FilterFileDialog.ShowDialog();

            //Check for a null return (e.g. no file selected)
            //  just log it and return if nothing there
            if (focusfilelist != DialogResult.OK)
            {
                lg.LogIt("No focus preset file selected");
                NHUtil.ButtonGreen(Presetbutton);
                return;
            }
            //Else...
            string focusfile = FilterFileDialog.FileNames[0];

            //Save the new (or unchanged) file path
            int baseFilterId = tPlan.FocusFilter;

            lg.LogIt("Presetting focus position");

            double currenttemp      = TSXLink.Focus.GetTemperature();
            double newfocusposition = AutoFocus.ComputeNewFocusPosition(focusfile, currenttemp, baseFilterId);

            if (newfocusposition == 0)
            {
                //Insufficient data to compute new position so, just leave it.
                lg.LogIt("Focus preset aborted -- insufficient data to compute new position");
                NHUtil.ButtonGreen(Presetbutton);
                return;
            }
            else
            {
                TSXLink.Focus.MoveTo(newfocusposition);
            }
            lg.LogIt("Focus preset completed");
            NHUtil.ButtonGreen(Presetbutton);
            return;
        }
예제 #4
0
        private void FromTSXButton_Click(object sender, EventArgs e)
        {
            /* Method gets whatever target is showing in the find function in TSX
             * normally by using a click on a star chart object.  If no object has been
             * choosen (Mouse click position) or simply no target (null) then return
             * Otherwise, clear the spaces out of the name and check for characters (like ":")
             * that won't work in a file name.  If illegal characters, then return
             * Otherwise, find an existing or open new target plan for this target name
             * and make it the target plan for the current session
             */

            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();

            //get the current target name from TSX and save it.
            NHUtil.ButtonRed(AcquireButton);
            //Retrieve current target from TSX
            TSXLink.Target tgt = TSXLink.StarChart.FindTarget();
            //Check to see if we're looking at a "Mouse Click Postion"
            //   if so, just get out of this
            if ((tgt.Name != "Mouse click position") && (tgt != null))
            {
                //Remove spaces from target name if any
                tgt.Name = tgt.Name.Replace(" ", "");
                //Remove known "illegal" characters
                if (tgt.Name.Contains(":"))
                {
                    lg.LogIt("Unsupported filename characters in target name " + tgt.Name);
                    MessageBox.Show("Unsupported characters in target name : " + tgt.Name);
                }
                else
                {
                    TargetPlan newtPlan = new TargetPlan(tgt.Name)
                    {
                        TargetAdjustEnabled = false,
                        TargetRA            = tgt.RA,
                        TargetDec           = tgt.Dec
                    };
                    newtPlan.TargetPA  = TSXLink.FOVI.GetFOVPA;
                    PlanTargetBox.Text = newtPlan.TargetName;
                    TSXLink.StarChart.SetFOV(2);
                    LoadTargetPlanList();
                    openSession.CurrentTargetName = newtPlan.TargetName;
                    lg.LogIt("A new target plan has been created for " + newtPlan.TargetName);
                }
            }
            NHUtil.ButtonGreen(AcquireButton);
            this.Show();
        }
예제 #5
0
        private void DisconnectButton_Click(object sender, EventArgs e)
        {
            LogEvent lg = new LogEvent();

            NHUtil.ButtonRed(DisconnectButton);
            lg.LogIt("Disconnecting");
            if (ParkMountCheckBox.Checked)
            {
                lg.LogIt("Parking mount");
                TSXLink.Connection.SecureMount();
                ParkMountCheckBox.Checked = false;
            }
            TSXLink.Connection.DisconnectAllDevices();
            NHUtil.ButtonGreen(DisconnectButton);
            return;
        }
예제 #6
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);
        }
예제 #7
0
        public static bool WaitLoop(DateTime endTime)
        {
            LogEvent lg = new LogEvent();

            lg.LogIt("Waiting until " + endTime.ToString("HH:mm"));
            do
            {
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(1000); //wait a second
                if (FormHumason.IsAborting())
                {
                    lg.LogIt("Wait Loop Aborted");
                    return(false);
                }
            } while (DateTime.Now < endTime);
            return(true);
        }
예제 #8
0
        //Class encapsulates autofocus
        // Note that @Focus must be already configured for:
        //   1. Automatically slew to appropriate focus star or already centered on an appropriate focus star
        //   2. Automatically setting exposure time

        public static void FocusIt(int aftype)
        {
            //Execute TSX @Focus2 (ftype = 2) or @Focus3 (ftype = 3)
            //  Save current object information
            //  Open and connect Autofocus
            //  Turn on temperature compensation
            //  Move filter to clear filter
            //  Run Focus@2 or AtFocus 3 for all five filters

            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Initiating Auto Focus" + aftype.ToString());
            //Get current temperature and focus position
            double nowTemp = TSXLink.Focus.GetTemperature();

            lg.LogIt("Current focuser temperature is " + nowTemp.ToString("0.0") + "C");
            double nowPos = TSXLink.Focus.GetPosition();

            lg.LogIt("Current focuser position is " + nowPos.ToString("0"));
            AstroImage asti = new Humason.AstroImage
            {
                Camera         = AstroImage.CameraType.Imaging,
                ImageReduction = AstroImage.ReductionType.AutoDark,
                Frame          = AstroImage.ImageType.Light,
                Filter         = tPlan.FocusFilter,
                Exposure       = tPlan.FocusExposure,
                Delay          = 0
            };

            TSXLink.Focus.RunTempComp();
            lg.LogIt("Focusing with filter " + asti.Filter.ToString());
            switch (aftype)
            {
            case 2:
                TSXLink.Focus.RunAtFocusAny(asti, 2);
                if (!TSXLink.DataWizard.Clear_Observing_List(tPlan.TargetName))
                {
                    lg.LogIt("Clear Observing List Failed");
                }
                break;

            case 3:
                TSXLink.Focus.RunAtFocusAny(asti, 3);
                break;

            default:
                lg.LogIt("Unknown AtFocus selection -- focus failed");
                break;
            }
            lg.LogIt("@Focus" + aftype.ToString() + " complete");
            nowPos = TSXLink.Focus.GetPosition();
            lg.LogIt("New focuser position is " + nowPos.ToString("0"));
        }
예제 #9
0
        public void TabUpdate()
        {
            LogEvent lg = new LogEvent();
            //If the targetname is empty, then check for a target name in TSX Find,
            //If still empty then just return
            string currentPlan = TargetBox.Text;

            if (currentPlan == "")
            {
                lg.LogIt("Error: Attempted to update empty target sequence");
                MessageBox.Show("Please load a target plan before attempting to update.");
                return;
            }
            lg.LogIt("Updating Sequence");
            UpdateSequence();
            lg.LogIt("Sequence Updated");
            return;
        }
예제 #10
0
        public static void InitializeSystem()
        {
            SessionControl openSession = new SessionControl();

            //Power on and connect devices as configured
            LogEvent lg = new LogEvent();

            lg.LogIt("Connecting");
            openSession = new SessionControl();
            if (openSession.IsHomeMountEnabled)
            {
                TSXLink.Connection.DeployMount();
            }
            //Make sure themount is Parked
            TSXLink.Mount.Park();
            TSXLink.Connection.ConnectAllDevices();
            //fCameraForm.RefreshFilterList();
            lg.LogIt("Devices Connected");
        }
예제 #11
0
        //Method for initiating an abort event as called from a method that wants to speak one
        public void AbortIt(string abortmessage)
        {
            //Logs the abort event
            LogEvent lg = new LogEvent();

            lg.LogIt("Abort Initiated: " + abortmessage);

            //Raises an abort event for anyone who is listening
            RaiseAbortEvent(abortmessage);
            //tell the operations class that there is an abort
            FormHumason.SetAbort();
        }
예제 #12
0
        public static bool PlateSolveIt()
        {
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);
            AstroImage     asti        = new AstroImage
            {
                Exposure       = tPlan.PlateSolveExposureTime,
                Filter         = tPlan.ClearFilter,
                ImageReduction = AstroImage.ReductionType.AutoDark,
                Delay          = 0
            };

            lg.LogIt("Plate Solve: Imaging");
            Imaging imgo = new Imaging();

            string path = imgo.TakeLightFrame(asti);

            lg.LogIt("Plate Solve: Image Linking");
            //tsxl.scale = 1.70;
            //tsxl.unknownScale = true;
            TSXLink.PlateSolution dSolve = TSXLink.ImageSolution.PlateSolve(path);
            if (dSolve == null)
            {
                lg.LogIt("Plate Solve: Image Link Failed: ");
                return(false);
            }
            lg.LogIt("Plate Solve: Image Link Successful");
            ImagePA  = dSolve.ImagePA;
            ImageRA  = dSolve.ImageRA;
            ImageDec = dSolve.ImageDec;

            if (tPlan.RotatorEnabled)
            {
                //RotatorOffset = ImagePA - NHUtil.ReduceTo360( RealRotatorPA);
                RotatorOffset = AstroMath.Transform.NormalizeDegreeRange(ImagePA - RealRotatorPA);
            }
            return(true);
        }
예제 #13
0
        public static void RunStartUpApp()
        {
            //If StageSystemOn is set, then RunStageSystem gets the StageSystem filepath from the Humason config file, if any
            //  then launches it and waits for completion.

            SessionControl openSession = new SessionControl();
            Process        pSystemExe  = new Process();

            if (openSession.StartUpFilePath != null)
            {
                LogEvent lg = new LogEvent();
                lg.LogIt("Running Start Up Process");
                pSystemExe.StartInfo.FileName = openSession.StartUpFilePath;
                pSystemExe.Start();
                if (openSession.IsStartUpWaitEnabled)
                {
                    pSystemExe.WaitForExit();
                }

                lg.LogIt("Start Up Process Complete");
            }
            return;
        }
예제 #14
0
        //*** Logs calibration vectors in configuration file
        public static void LogVectors()
        {
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);
            LogEvent       lg          = new LogEvent();
            //Get calibration vectors
            //Make null image def to retrieve directly from TSX
            //Null definition
            AstroImage asti = new AstroImage()
            {
                Camera = AstroImage.CameraType.Guider
            };

            TSXLink.Camera gCam = new TSXLink.Camera(asti);
            //Write vectors to tPlan file
            //Store vectors
            tPlan.CalVectorXPosXComponent = gCam.CalibrationVectorXPositiveXComponent;
            tPlan.CalVectorXPosYComponent = gCam.CalibrationVectorXPositiveYComponent;
            tPlan.CalVectorXPosXComponent = gCam.CalibrationVectorXPositiveXComponent;
            tPlan.CalVectorXPosYComponent = gCam.CalibrationVectorXPositiveYComponent;
            tPlan.CalVectorYNegXComponent = gCam.CalibrationVectorXNegativeXComponent;
            tPlan.CalVectorYNegYComponent = gCam.CalibrationVectorXNegativeYComponent;
            tPlan.CalVectorYNegXComponent = gCam.CalibrationVectorXNegativeXComponent;
            tPlan.CalVectorYNegYComponent = gCam.CalibrationVectorXNegativeYComponent;

            //write a line of the 8 log vectors
            lg.LogIt("Calibration Vectors:  ");
            lg.LogIt("CalVectorXPosXComponent: " + tPlan.CalVectorXPosXComponent);
            lg.LogIt("CalVectorXPosYComponent: " + tPlan.CalVectorXPosYComponent);
            lg.LogIt("CalVectorXNegXComponent: " + tPlan.CalVectorXPosXComponent);
            lg.LogIt("CalVectorXNegYComponent: " + tPlan.CalVectorXPosYComponent);
            lg.LogIt("CalVectorYPosXComponent: " + tPlan.CalVectorXNegXComponent);
            lg.LogIt("CalVectorYPosYComponent: " + tPlan.CalVectorXNegYComponent);
            lg.LogIt("CalVectorYNegXComponent: " + tPlan.CalVectorXNegXComponent);
            lg.LogIt("CalVectorYNegYComponent: " + tPlan.CalVectorXNegYComponent);
        }
예제 #15
0
        private void MakeFlatsButton_Click(object sender, EventArgs e)
        {
            //Make flat request entries based on current target name and rotator info
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);
            FlatManager    nhFlat      = new FlatManager();

            //Get filter set
            List <Filter> fset = tPlan.FilterWheelList;

            if (fset == null)
            {
                lg.LogIt("No filters have been configured");
                return;
            }
            string tname           = tPlan.TargetName;
            double rPA             = (double)RotatorPANum.Value;
            int    flatRepetitions = openSession.FlatsRepetitions;
            //If the last image was shot to the west, then the rotator should alread be in the west position,
            //  which will mean that a single set will have the rotator already positioned collectly
            string sop = "East";

            foreach (Filter fi in fset)
            {
                fi.Repeat = flatRepetitions;
                Flat iFlat = new Flat(tname, sop, rPA, fi, openSession.IsFlatFlipEnabled);
                nhFlat.AddFlat(iFlat);
            }
            //Check to see if there is a rotator enabled, if so, and flip is enabled, then make a second set for the east side
            if ((openSession.IsFlatsRotationEnabled) && (openSession.IsFlatFlipEnabled))
            {
                rPA = AstroMath.Transform.NormalizeDegreeRange(rPA + 180);
                sop = "West";
                foreach (Filter fi in fset)
                {
                    fi.Repeat = flatRepetitions;
                    Flat iFlat = new Flat(tname, sop, rPA, fi, openSession.IsFlatFlipEnabled);
                    nhFlat.AddFlat(iFlat);
                }
            }
        }
예제 #16
0
        private static void GracefulAbort()
        {
            //Abort has been pushed or automatically called by procedure due to some error
            //If start is not active or attended is checked then we want to just park the scope and disconnect all
            //devices.
            //If start is active, then we want to treat this as a catastrophic event and simply
            //stop everything by parking
            SessionControl openSession = new SessionControl();

            LogEvent lg = new LogEvent();

            lg.LogIt("Aborting and Closing Down");
            FormHumason.SetAbort();

            //All done.  Abort autoguiding, assuming is running -- should be off, but you never know
            AutoGuide.AutoGuideStop();

            //If autorun set and we're running unattended, then shut down, or... just park the mount, home the dome and disconnect
            if (openSession.IsAutoRunEnabled && !openSession.IsAttended)
            {
                LaunchPad.RunShutDownApp();
            }
            else if (FormHumason.SessionState != FormHumason.SessionStateFlag.Stopped)
            {
                lg.LogIt("Parking Mount");
                try { TSXLink.Mount.Park(); }
                catch (Exception ex) { lg.LogIt("Could not Park: " + ex.Message); }
                //home dome (don't close as autorun is not enabled
                lg.LogIt("Homing Dome");
                if (openSession.IsDomeAddOnEnabled)
                {
                    TSXLink.Dome.HomeDome();
                }
                lg.LogIt("Disconnecting all devices");
                TSXLink.Connection.DisconnectAllDevices();
                FormHumason.SetStopped();
            }
            lg.LogIt("Abort Completed -- awaiting new orders, Captain");
            return;
        }
예제 #17
0
        //public static LogEvent lg;

        public FormHumason()
        {
            settings = new Properties.Settings();

            InitializingHumason = true;

            InitializeComponent();
            ColorButtonsGreen();

            //Event Handlers
            //Add the method for handling target reset events to the queue of such handlers (if any others.._
            //AbortEvent ag = new AbortEvent();
            //ag.AbortEventHandler += AbortReportEvent_Handler;

            //Add log event generator
            StatusReportEvent = new LogEvent();
            StatusReportEvent.LogEventHandler += LogReportUpdate_Handler;

            //Open session and default target xml data
            SessionControl openSession = new SessionControl();
            TargetPlan     dtPlan      = new TargetPlan("Default");

            openSession.DefaultTargetPlanPath = dtPlan.DefaultPlanPath;

            //Initialize tab forms
            fSessionForm = new FormSessionControl {
                TopLevel = false
            };
            SessionTab.Controls.Add(fSessionForm);
            fSessionForm.Show();

            fTargetForm = new FormTarget {
                TopLevel = false
            };
            TargetTab.Controls.Add(fTargetForm);
            fTargetForm.Show();

            fDeviceForm = new FormDevices {
                TopLevel = false
            };
            DevicesTab.Controls.Add(fDeviceForm);
            fDeviceForm.Show();

            fFlatsForm = new FormFlats {
                TopLevel = false
            };
            FlatsTab.Controls.Add(fFlatsForm);
            fFlatsForm.Show();

            fGuideForm = new FormAutoGuide {
                TopLevel = false
            };
            GuideTab.Controls.Add(fGuideForm);
            fGuideForm.Show();

            fFocusForm = new FormAutoFocus {
                TopLevel = false
            };
            FocusTab.Controls.Add(fFocusForm);
            fFocusForm.Show();

            if (settings.RotatorDeviceEnabled)
            {
                fRotateForm = new FormRotate {
                    TopLevel = false
                };
                RotatorTab.Controls.Add(fRotateForm);
                fRotateForm.Show();
            }
            else
            {
                HumasonTabs.TabPages.Remove(RotatorTab);
            }

            fPlanForm = new FormPlan {
                TopLevel = false
            };
            PlanTab.Controls.Add(fPlanForm);
            fPlanForm.Show();

            if (settings.HasDomeAddOn)
            {
                fDomeForm = new FormDome {
                    TopLevel = false
                };
                DomeTab.Controls.Add(fDomeForm);
                fDomeForm.Show();
            }
            else
            {
                HumasonTabs.TabPages.Remove(DomeTab);
            }

            //Open log and subscribe this form to the log event
            StatusReportEvent.CreateLog();

            // 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 = "Humason V" + this.Text;
            // Place initial inforamtion in Log
            StatusReportEvent.LogIt("********* New Humason Run **********\r\n");
            StatusReportEvent.LogIt("* " + this.Text + "  " + DateTime.Now.ToShortDateString() + " **" + "\r\n");
            StatusReportEvent.LogIt("******* Humason Initialized ********");
            // All done with initialization
            InitializingHumason = false;
            TopMost             = true;
        }
예제 #18
0
        //public static SessionControl openSession;

        public static bool ImagingControl()
        {
            //Runs the photo shoot shebang
            //First a little housekeeping -- configuration update and make sure the clock is set right
            //if Autorun staging is set, wait on autostaging time, then run the staging app
            //if Autorun start is set, wait on autostart time, then run the starting app
            //Wait on Sequence start
            //
            //LogEvent lg = new LogEvent();
            LogEvent lg = FormHumason.StatusReportEvent;

            TargetEvent tg = new TargetEvent();

            SessionControl openSession = new SessionControl();

            //Run a quick check on all the things that might be wrong, based on past history
            //  the main thing being that there is at least one target plan queued.
            lg.LogIt("Running diagnostics");
            if (!Diagnostics.CheckUp())
            {
                lg.LogIt("Diagnostics abort");
                return(false);;
            }

            lg.LogIt("Diagnostics success");
            //All selected devices should be on-line and connected
            //Load the first target plan so we can pull some information for this session
            lg.LogIt("Loading first session target plan");
            if (!FormHumason.fPlanForm.IsTopPlanTargetName())
            {
                lg.LogIt("No Target Plan");
                return(false);
            }
            openSession.CurrentTargetName = FormHumason.fPlanForm.GetTopPlanTargetName();
            TargetPlan ftPlan = new TargetPlan(openSession.CurrentTargetName);

            //Flush it out, if we have to
            if (ftPlan.IsSparsePlan())
            {
                lg.LogIt("Sparse Plan -- filling out from default");
                ftPlan.FlushOutFromDefaultPlan();
            }
            //Update the form and regenerate the sequence
            tg.RaiseNewTargetPlan(ftPlan.TargetName);

            //Get the staging, start and shut down times from this initial target, although may not be used
            openSession.StagingTime = DateTime.Now;
            openSession.StartUpTime = ftPlan.SequenceStartTime;
            // openSession.ShutDownTime = fSequenceForm.DawnTimeBox.Value;
            openSession.ShutDownTime = ftPlan.SequenceDawnTime;

            //Save configuration set up, reset the progess bar and make sure that the TSX clock is set to current time
            //fSequenceForm.UpdateFormFromPlan();
            TSXLink.StarChart.SetClock(0, true);

            //Await Staging and Start Up
            //  If autorun enabled, then run the staging time autorun script/app
            if (openSession.IsAutoRunEnabled && openSession.IsStagingEnabled)
            {
                LaunchPad.WaitStaging();
            }
            //check for abort having been set.  Gracefully shut everything back down if it has.
            if (FormHumason.IsAborting())
            {
                GracefulAbort();
            }

            //  If autorun enabled, then run the start up time autorun script/app
            if (openSession.IsAutoRunEnabled && openSession.IsStartUpEnabled)
            {
                LaunchPad.WaitStartUp();
            }
            //check for abort having been set.  Gracefully shut everything back down if it has.
            if (FormHumason.IsAborting())
            {
                GracefulAbort();
            }

            //Both Staging and Start Up have been run. All devices should be powered, but not necessarily connected
            //Power up and connect devices (if not done already)
            lg.LogIt("Initializing system");
            InitializeSystem();

            //Remove all flat requests from the flats file
            //   No, don't
            //FlatManager nhFlat = new FlatManager();
            //nhFlat.FlatSetClearAll();
            //nhFlat = null;

            //Check for proximity to meridian flip
            //  if HA of target is within 10 minutes, then just wait it out at
            //Get target HA
            TSXLink.Target tgto;
            lg.LogIt("Checking for new target to clear meridian");
            string raS  = ftPlan.TargetRA.ToString();
            string decS = ftPlan.TargetDec.ToString();

            tgto = TSXLink.StarChart.FindTarget(raS + "," + decS);
            double ha = tgto.HA.TotalMinutes;

            while ((ha >= -10) && (ha <= 0))
            {
                System.Threading.Thread.Sleep(10000);
                tgto = TSXLink.StarChart.FindTarget(ftPlan.TargetName);
                ha   = tgto.HA.TotalMinutes;
            }
            lg.LogIt("New target is clear of meridian");

            //Make sure the mount is unparked
            TSXLink.Mount.UnPark();
            //Make sure tracking is turned on
            TSXLink.Mount.TurnTrackingOn();

            //Bring camera to temperature (if not already), then clear the objects
            AstroImage asti = new AstroImage()
            {
                Camera = AstroImage.CameraType.Imaging
            };

            TSXLink.Camera cCam = new TSXLink.Camera(asti);
            cCam.CCDTemperature = ftPlan.CameraTemperatureSet;
            cCam = null; asti = null;

            //************************  Starting up the target plans  *************************
            //
            //  This loop is to run each of the plans in the schedule list sequentially.
            //  The current plan has already progressed through any staging and starting scripts
            //      and the next step will be to wait on the starting time, if it hasn't passed already
            //  At the end of the loop, the current plan will be deleted from the schedule and the next one, if any
            //      loaded.  If none, then the shutdown script of the last plan will be run (if autorun is set for that plan).
            //
            while (FormHumason.fPlanForm.IsTopPlanTargetName())
            {
                //Load the top scheduled plan
                string tgtName = FormHumason.fPlanForm.GetTopPlanTargetName();
                openSession.CurrentTargetName = tgtName;
                TargetPlan tPlan = new TargetPlan(tgtName);

                lg.LogIt(" ******************* Imaging Target: " + openSession.CurrentTargetName);
                if (tPlan.IsSparsePlan())
                {
                    lg.LogIt("Sparse Plan -- filling out from default");
                    tPlan.FlushOutFromDefaultPlan();
                }
                //Try to move to target, if this fails just abort
                Sequencer imgseq = new Sequencer();
                if (!imgseq.CLSToTargetPlanCoordinates())
                {
                    GracefulAbort(); break;
                }

                //check for abort having been set.  Gracefully shut everything back down if it has.
                if (FormHumason.IsAborting())
                {
                    GracefulAbort(); break;
                }

                //Now lets get the rotator positioned properly, plate solve, then rotate, then plate solve
                if (tPlan.RotatorEnabled)
                {
                    lg.LogIt("Rotating to PA @ " + tPlan.TargetPA.ToString("0.00"));
                    if (!Rotator.RotateToImagePA(tPlan.TargetPA))
                    {
                        lg.LogIt("Failed to properly rotate. Aborting.");
                        GracefulAbort();
                    }
                    else
                    {
                        lg.LogIt("Rotation complete and verified");
                        // Because rotation may not be quite symmetrical, do another CLS to make sure
                        //  the guide star and target is still centered

                        lg.LogIt("CLS to center target after rotation");
                        if (!imgseq.CLSToTargetPlanCoordinates())
                        {
                            lg.LogIt("Failed to center target after rotation");
                            GracefulAbort();
                        }
                        ;
                    }
                }
                else
                {
                    lg.LogIt("Rotator not enabled");
                }

                //check for abort having been set.  Gracefully shut everything back down if it has.
                if (FormHumason.IsAborting())
                {
                    GracefulAbort(); break;
                }

                //Update the sequence for whatever time it is now
                try { imgseq.SeriesGenerator(); }
                catch
                {
                    lg.LogIt("Make Series Error");
                    GracefulAbort(); break;
                }
                //
                // Run Imaging Sequence
                imgseq.PhotoShoot();
                //
                //
                //All done.  Abort autoguiding, assuming is running -- should be off, but you never know
                AutoGuide.AutoGuideStop();
                //check for abort having been set.  Gracefully shut everything back down if it has.
                if (FormHumason.IsAborting())
                {
                    GracefulAbort(); break;
                }
                //Done with imaging on this plan.
                //Store the ending time
                tPlan.SequenceEndTime = DateTime.Now;
                //Save the plan in the sequence complete summary file
                openSession.AddSequenceCompleteSummary();
                //string tName = tPlan.GetItem(TargetPlan.sbTargetNameName); //why??
                //Remove the plan from the schedule and look for the next
                FormHumason.fPlanForm.RemoveTopPlan();
            }

            //done with imaging.  Check on flats  See if any flats have been requested

            FlatManager fmgr = new FlatManager();

            if (fmgr.HaveFlatsToDo() && !FormHumason.IsAborting())
            {
                fmgr.TakeFlats();
            }

            //If autorun set, then run it, or... just park the mount
            if (openSession.IsAutoRunEnabled)
            {
                LaunchPad.RunShutDownApp();
            }
            else
            {
                try { TSXLink.Mount.Park(); }
                catch (Exception ex) { lg.LogIt("Could not Park: " + ex.Message); }
            }
            return(true);
        }
예제 #19
0
        /// <summary>
        /// Saves the most recent image capture to Humason image directory for that night (as defined by start time)
        /// </summary>
        /// <param name="targetName"></param>
        /// <param name="filterName"></param>
        /// <param name="targetPA"></param>
        /// <param name="sidePoint"></param>
        public static void SaveLightImage(string targetName, string filterName, string targetPA, string sidePoint)
        {
            //The NH image directory originates from the NH form and stored in the Session class.
            //Get Humason directory name, create image directory if it doesn't exist yet
            LogEvent       lg             = new LogEvent();
            SessionControl openSession    = new SessionControl();
            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
            TargetPlan tPlan = new TargetPlan(openSession.CurrentTargetName);

            DateTime sequenceStartDate = tPlan.SequenceStartTime;
            string   targetImageDir    = nhImageDirName + "\\" + sequenceStartDate.ToString("yyyyMMdd") + "_" + targetName;

            if (!Directory.Exists(targetImageDir))
            {
                Directory.CreateDirectory(targetImageDir);
            }
            //Create Data Files directory if it doesn't exit yet
            string targetImageDataDir = targetImageDir + "\\Data 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 +
                                         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

            //Add some FITSKeywords for future reference
            //Correct the OBJECT Keyword if using coordinates instead of a target name
            tsxi.setFITSKeyword("OBJECT", targetName);
            //Enter the rotator angle
            if (tPlan.RotatorEnabled)
            {
                tsxi.setFITSKeyword("ROTATOR", Rotator.RealRotatorPA.ToString());
            }
            //Enter Image Position Angle as saved
            tsxi.setFITSKeyword("ORIENTAT", tPlan.TargetPA);

            //Set save path and save
            tsxi.Path = targetImageDataPath;
            tsxi.Save();
            lg.LogIt("Image saved: " + targetImageDataPath);
        }
예제 #20
0
        public static bool DitherAndStart()
        {
            //Dithers the camera by a small random amount and waits until complete
            //  returns true if guider has returned to certain bounds in a reasonable
            //  time.  Turns off autoguider and returns false if not.
            const int    MinDitherPixels = -5;
            const int    MaxDitherPixels = 5;
            const double MinGuiderError  = 1;

            SessionControl openSession = new SessionControl();
            //Prep class invocations: configuration, logging and TSX autoguider
            LogEvent   lg    = new LogEvent();
            TargetPlan tPlan = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Dithering: Autoguide off");
            AutoGuideStop();
            AstroImage asti = new AstroImage()
            {
                Camera = AstroImage.CameraType.Guider
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            //Open guider
            TSXLink.Camera gCam = new TSXLink.Camera(asti);
            //Turn off autoguide
            //Get current X/Y guide star position
            double guideX = gCam.GuideStarX;
            double guideY = gCam.GuideStarY;
            //Compute random pixel offsets and adjust current values
            Random rndm = new Random();
            int    offX = rndm.Next(MinDitherPixels, MaxDitherPixels);
            int    offY = rndm.Next(MinDitherPixels, MaxDitherPixels);

            gCam.GuideStarX = guideX + offX;
            gCam.GuideStarY = guideY + offY;
            lg.LogIt("Dithering: Dithered by " + offX + " in X and " + offY + " in Y");
            //Restart autoguiding
            lg.LogIt("Dithering: Starting Autoguider");
            AutoGuideStart();
            //Monitor guide errors for 10 cycles, if RMS error not within MinError
            //  within those cycles, then shutdown autoguiding and return false
            double cycleTime = tPlan.GuideExposure;

            for (int cy = 0; cy < 10; cy++)
            {
                double rms = Math.Sqrt(Math.Pow(gCam.GuideErrorX, 2) + Math.Pow(gCam.GuideErrorY, 2));
                lg.LogIt("Dithering: Guider error at " + rms.ToString("0.00"));
                if (rms < MinGuiderError)
                {
                    //Convergence successful -- clean up and return true
                    lg.LogIt("Dithering: Converged");
                    return(true);
                }
                else
                {
                    System.Threading.Thread.Sleep((int)(cycleTime * 1000));
                }                                                            // sleep in milliseconds
            }
            //Convergence failed, turn off autoguiding, clean up and return false
            lg.LogIt("Dithering: Convergence failed.  Autoguiding stopped");
            AutoGuideStop();
            return(false);
        }
예제 #21
0
        //SexTractor-based method for getting the ADU of a guide star
        public static double GetGuideStarADU(double exposure)
        {
            //Determines the ADU for the X/Y centroid of the maximum FWHM star in a subframe
            //
            //Take a subframe image on the guider using TSX guide star coordinates and trackbox size
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Creating Guider Subframe Image");

            AstroImage asti = new AstroImage
            {
                Camera   = AstroImage.CameraType.Guider,
                SubFrame = 1,
                Frame    = AstroImage.ImageType.Light,
                BinX     = tPlan.GuiderBinning,
                BinY     = tPlan.GuiderBinning,
                Delay    = 0,
                Exposure = exposure
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            TSXLink.Camera gCam = new TSXLink.Camera(asti)
            {
                AutoSaveOn = 1//Turn on autosave so we can extract a star inventory via ShowInventory()
            };
            //Center up AO, just in case and if enabled
            if (tPlan.AOEnabled)
            {
                gCam.CenterAO();
            }

            //Compute the subframe from the trackbox size
            int sizeX = gCam.TrackBoxX;
            int sizeY = gCam.TrackBoxY;

            gCam.SubframeTop    = (int)(tPlan.GuideStarY * tPlan.GuiderBinning) - (sizeY / 2);
            gCam.SubframeBottom = (int)(tPlan.GuideStarY * tPlan.GuiderBinning) + (sizeY / 2);
            gCam.SubframeLeft   = (int)(tPlan.GuideStarX * tPlan.GuiderBinning) - (sizeX / 2);
            gCam.SubframeRight  = (int)(tPlan.GuideStarX * tPlan.GuiderBinning) + (sizeX / 2);

            //Take an image f
            int tstat = gCam.GetImage();

            if (tstat != 0)
            {
                lg.LogIt("Autoguider Image Error: " + tstat.ToString());
                return(0);
            }
            lg.LogIt("Guider Subframe image successful");

            //Next step is to generate the collection of stars in the subframe
            TSXLink.SexTractor sEx = new TSXLink.SexTractor();
            int xStat = sEx.SourceExtractGuider();

            lg.LogIt("Light source extraction complete");

            List <double> FWHMlist = sEx.GetSourceExtractionList(TSXLink.SexTractor.SourceExtractionType.sexFWHM);
            List <double> CenterX  = sEx.GetSourceExtractionList(TSXLink.SexTractor.SourceExtractionType.sexX);
            List <double> CenterY  = sEx.GetSourceExtractionList(TSXLink.SexTractor.SourceExtractionType.sexY);
            int           iMax     = sEx.GetListLargest(FWHMlist);

            double maxStarADU = 0;

            try
            {
                maxStarADU = sEx.GetPixelADU((int)CenterX[iMax], (int)CenterY[iMax]);
            }
            catch (Exception ex)
            {
                lg.LogIt("Light Source error -- no stars?");
            }
            if (maxStarADU == 0)
            {
                maxStarADU = gCam.MaximumPixel;
            }
            return(maxStarADU);
        }
예제 #22
0
        //*** Optimize Exposure determines the best exposure time for the target star
        public static double OptimizeExposure()
        {
            //Get the best exposure time based on the target ADU
            //
            //Subrountine loops up to 4 times, taking an image, and calulating a new exposure that comes closest to meeting ADU goal
            //
            //Take an image with current exposure set from last guider exposure
            //If the max ADu is 100 or less, then there was no star at all.  Double the exposure upto MaxGuiderExposure
            //If the returned exposure is 64000 or more, then the star was probably saturated.  Halve the exposure down to no less than the minguider exposure.
            //If not within 20% of targetADU, then recalculate and rerun
            //If within 20% then recalculate and done, then update the exposure settings and return the exposure
            //
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);
            double         exposure    = tPlan.GuideExposure;
            double         tgtADU      = tPlan.GuideStarADU;
            double         maxExposure = tPlan.MaximumGuiderExposure;
            double         minExposure = tPlan.MinimumGuiderExposure;

            //set the maximum number of iterations based on the maximum number of halves or doubles that could be performed.
            lg.LogIt("Attempting to find optimal guide star exposure");

            //Only take at max 4 shots at getting a good exposure, otherwise return the max or min
            for (int i = 0; i < 4; i++)
            {
                //Start at the initial exposure.  This is a minimum.
                //Take a subframe image
                //Get maximum pixels ADU
                //
                double maxPixel = GetGuideStarADU(exposure);  //Uses SexTractor engine
                lg.LogIt("Guide star ADU at " + maxPixel.ToString())
                ;
                //Check through too low, too high and just right
                if (maxPixel < 500)  //way too low
                {
                    exposure = LimitMaxMin((exposure * 2), maxExposure, minExposure);
                    lg.LogIt("Guide Star exposure too low. Reset to " + exposure.ToString("0.00") + " secs");
                }
                else if (maxPixel > 60000.0)  //too close to saturation
                {
                    exposure = LimitMaxMin((exposure / 2), maxExposure, minExposure);
                    lg.LogIt("Guide Star exposure set too high. Reset to " + exposure.ToString("0.00") + " secs");
                }
                else if (!(NHUtil.CloseEnough(maxPixel, tgtADU, 20.0)))  //if not quite close enought recalculate exposure try again
                {
                    if (maxPixel > tgtADU)
                    {
                        exposure = LimitMaxMin(((tgtADU / maxPixel) * exposure), maxExposure, minExposure);
                        lg.LogIt("Guide Star ADU is " + maxPixel.ToString("0") + ": Exposure too high at " + exposure.ToString("0.00") + " secs");
                    }
                    else
                    {
                        exposure = LimitMaxMin(((tgtADU / maxPixel) * exposure), maxExposure, minExposure);
                        lg.LogIt("Guide Star ADU is " + maxPixel.ToString("0") + ": Exposure too low at " + exposure.ToString("0.00") + " secs");
                    }
                }
                else
                {
                    exposure = LimitMaxMin(((tgtADU / maxPixel) * exposure), maxExposure, minExposure);
                    break;
                }
            }
            lg.LogIt("Guide Star target exposure set to " + exposure.ToString("0.00") + " secs");
            return(LimitMaxMin(exposure, maxExposure, minExposure));
        }
예제 #23
0
        //*** SetAutoGuideStar picks a guide star and places a subframe around it
        public static bool SetAutoGuideStar()
        {
            // Subroutine takes a picture, picks a guide star, computes a subframe to put around it,
            //  loads the location and subframe into the autoguider
            //

            // Subroutine picks a guide star, computes a subframe to put around it based on current TSX settings
            // and loads the location and subframe into the autoguider
            //
            int MagWeight  = 1;
            int FWHMWeight = 1;
            int ElpWeight  = 1;
            int ClsWeight  = 1;

            // Algorithm:
            //
            //   Compute optimality and normalizaton values (see below)
            //   Eliminate all points near edge and with neighbors
            //   Compute optimality differential and normalize, and add
            //   Select best (least sum) point
            //
            // Normalized deviation from optimal where optimal is the best value for each of the four catagories:
            //   Magnitude optimal is lowest magnitude
            //   FWHM optimal is average FWHM
            //   Ellipticity optimal is lowest ellipticity
            //   Class optimal is lowest class
            //
            // Normalized means adjusted against the range of highest to lowest becomes 1 to 0, unless there is only one datapoint
            //
            //

            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Finding guide star coordinates");
            AstroImage asti = new AstroImage
            {
                Camera   = AstroImage.CameraType.Guider,
                SubFrame = 0,
                Frame    = AstroImage.ImageType.Light,
                BinX     = tPlan.GuiderBinning,
                BinY     = tPlan.GuiderBinning,
                Delay    = 0,
                Exposure = tPlan.GuideExposure
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            TSXLink.Camera guider = new TSXLink.Camera(asti)
            {
                AutoSaveOn = 1
            };
            //Center AO, if configured
            if (tPlan.AOEnabled)
            {
                guider.CenterAO();
            }

            //Take an image f
            int camResult = guider.GetImage();

            //acquire the current trackbox size (need it later)
            int TrackBoxSize = guider.TrackBoxX;

            TSXLink.SexTractor tsex = new TSXLink.SexTractor();

            try
            {
                int sStat = tsex.SourceExtractGuider();
            }
            catch (Exception ex)
            {
                // Just close up, TSX will spawn error window
                lg.LogIt("Some problem with guider image: " + ex.Message);
                tsex.Close();
                return(false);
            }

            int Xsize = tsex.WidthInPixels;
            int Ysize = tsex.HeightInPixels;

            // Collect astrometric light source data from the image linking into single index arrays:
            //  magnitude, fmhm, ellipsicity, x and y positionc
            //

            double[] MagArr    = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexMagnitude);
            int      starCount = MagArr.Length;

            if (starCount == 0)
            {
                lg.LogIt("No astrometric sources found");
                tsex.Close();
                return(false);
            }
            double[] FWHMArr = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexFWHM);
            double[] XPosArr = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexX);
            double[] YPosArr = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexY);
            double[] ElpArr  = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexEllipticity);
            double[] ClsArr  = tsex.GetSourceExtractionArray(TSXLink.SexTractor.SourceExtractionType.sexClass);

            // Get some useful statistics
            // Max and min magnitude
            // Max and min FWHM
            // Max and min ellipticity
            // max and min class
            // Average FWHM

            double maxMag  = MagArr[0];
            double minMag  = MagArr[0];
            double maxFWHM = FWHMArr[0];
            double minFWHM = FWHMArr[0];
            double maxElp  = ElpArr[0];
            double minElp  = ElpArr[0];
            double maxCls  = ClsArr[0];
            double minCls  = ClsArr[0];

            double avgFWHM = 0;
            double avgMag  = 0;

            for (int i = 0; i < starCount; i++)
            {
                if (MagArr[i] < minMag)
                {
                    minMag = MagArr[i];
                }
                if (MagArr[i] > maxMag)
                {
                    maxMag = MagArr[i];
                }
                if (FWHMArr[i] < minFWHM)
                {
                    minFWHM = FWHMArr[i];
                }
                if (FWHMArr[i] > maxFWHM)
                {
                    maxFWHM = FWHMArr[i];
                }
                if (ElpArr[i] < minElp)
                {
                    minElp = ElpArr[i];
                }
                if (ElpArr[i] > maxElp)
                {
                    maxElp = ElpArr[i];
                }
                if (ClsArr[i] < minCls)
                {
                    minCls = ClsArr[i];
                }
                if (ClsArr[i] > maxCls)
                {
                    maxCls = ClsArr[i];
                }
                avgFWHM += FWHMArr[i];
                avgMag  += MagArr[i];
            }

            avgFWHM /= starCount;
            avgMag  /= starCount;

            // Create a set of "best" values
            double optMag  = minMag;    // Magnitudes increase with negative values
            double optFWHM = avgFWHM;   // Looking for the closest to maximum FWHM
            double optElp  = minElp;    // Want the minimum amount of elongation
            double optCls  = maxCls;    // 1 = star,0 = galaxy
                                        // Create a set of ranges
            double rangeMag  = maxMag - minMag;
            double rangeFWHM = maxFWHM - minFWHM;
            double rangeElp  = maxElp - minElp;
            double rangeCls  = maxCls - minCls;
            // Create interrum variables for weights
            double normMag;
            double normFWHM;
            double normElp;
            double normCls;
            // Count keepers for statistics
            int SourceCount   = 0;
            int EdgeCount     = 0;
            int NeighborCount = 0;
            int edgekeepout;

            // Create a selection array to store normilized and summed difference values
            double[] NormArr = new double[starCount];

            // Convert all points to normalized differences, checking for zero ranges (e.g.single or identical data points)
            for (int i = 0; i < starCount; i++)
            {
                if (rangeMag != 0)
                {
                    normMag = 1 - Math.Abs(optMag - MagArr[i]) / rangeMag;
                }
                else
                {
                    normMag = 0;
                }
                if (rangeFWHM != 0)
                {
                    normFWHM = 1 - Math.Abs(optFWHM - FWHMArr[i]) / rangeFWHM;
                }
                else
                {
                    normFWHM = 0;
                }
                if (rangeElp != 0)
                {
                    normElp = 1 - Math.Abs(optElp - ElpArr[i]) / rangeElp;
                }
                else
                {
                    normElp = 0;
                }
                if (rangeCls != 0)
                {
                    normCls = 1 - Math.Abs(optCls - ClsArr[i]) / rangeCls;
                }
                else
                {
                    normCls = 0;
                }

                // Sum the normalized points, weight and store value
                NormArr[i]   = (normMag * MagWeight) + (normFWHM * FWHMWeight) + (normElp * ElpWeight) + (normCls * ClsWeight);
                SourceCount += 1;

                // Remove neighbors and edge liers
                edgekeepout = openSession.GuideStarEdgeMargin;

                if (IsOnEdge((int)XPosArr[i], (int)YPosArr[i], Xsize, Ysize, edgekeepout))
                {
                    NormArr[i] = -1;
                }
                else
                {
                    for (int j = i + 1; j < starCount - 1; j++)
                    {
                        if (IsNeighbor((int)XPosArr[i], (int)YPosArr[i], (int)XPosArr[j], (int)YPosArr[j], TrackBoxSize))
                        {
                            NormArr[i] = -2;
                        }
                    }
                }
            }

            // Now find the best remaining entry

            int bestOne = 0;

            for (int i = 0; i < starCount; i++)
            {
                if (NormArr[i] > NormArr[bestOne])
                {
                    bestOne = i;
                }
            }

            guider.GuideStarX   = XPosArr[bestOne] * asti.BinX;
            guider.GuideStarY   = YPosArr[bestOne] * asti.BinY;
            asti.SubframeLeft   = (int)(XPosArr[bestOne] - (TrackBoxSize / 2)) * asti.BinX;
            asti.SubframeRight  = (int)(XPosArr[bestOne] + (TrackBoxSize / 2)) * asti.BinX;
            asti.SubframeTop    = (int)(YPosArr[bestOne] - (TrackBoxSize / 2)) * asti.BinY;
            asti.SubframeBottom = (int)(YPosArr[bestOne] + (TrackBoxSize / 2)) * asti.BinY;

            if (NormArr[bestOne] != -1)
            {
                tPlan.GuideStarX = guider.GuideStarX / asti.BinX;
                tPlan.GuideStarY = guider.GuideStarY / asti.BinY;
                lg.LogIt("Guide star coordinates set");
                tsex.Close();
                return(true);
            }
            else
            {
                // run statistics -- only if (total failure
                for (int i = 0; i < SourceCount; i++)
                {
                    if (NormArr[i] == -1)
                    {
                        EdgeCount += 1;
                    }
                    if (NormArr[i] == -2)
                    {
                        NeighborCount += 1;
                    }
                }
                lg.LogIt("No Guide star found out of " +
                         SourceCount.ToString() + " stars, " +
                         NeighborCount.ToString() + " had neighbors and " +
                         EdgeCount.ToString() + " were on the edge.");
                lg.LogIt("No Guide star coordinates set");
                tsex.Close();
                return(false);
            }
        }
예제 #24
0
        //Runs the guider through the calibration routine
        public static void CalibrateAutoguiding(bool subFrameIt, double xSubframeSize, double ySubframeSize)
        {
            //Save current location
            //Make sure Autoguiding is turned off
            //Run local star search and slew to the nearest star of correct magnitude
            //Run autocalibration routine
            //Reload current location and closed loop slew to it
            //Create list of local stars, using the autofocus query
            //  Open DataWizard, set path to AtFocus2.dbq, Open query and run
            LogEvent lg = new LogEvent();

            lg.LogIt("Calibrating Autoguider");
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            //Select star for calibration and set guide star location in TSX
            SetAutoGuideStar();
            //Calibrate using existing calibration parameters, i.e. calibration times, etc
            AstroImage asti = new AstroImage
            {
                Camera   = AstroImage.CameraType.Guider,
                Frame    = AstroImage.ImageType.Light,
                BinX     = tPlan.GuiderBinning,
                BinY     = tPlan.GuiderBinning,
                SubFrame = 0,
                Exposure = tPlan.GuideExposure
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            if (subFrameIt)
            {
                asti.SubFrame = 1;
            }
            //Create camera object from parameters, turn on Autosave
            TSXLink.Camera gCam = new TSXLink.Camera(asti)
            {
                AutoSaveOn = 0
            };
            //Set subframe around star, if enabled.
            if (subFrameIt)
            {
                //Get width of guider FOV in pixels and arcsec
                GuideCamFOV gfov          = new GuideCamFOV();
                double      asWidthX      = gfov.ArcMinSizeX * 60;
                double      asWidthY      = gfov.ArcMinSizeY * 60;
                double      pixWidthX     = gfov.PixelSizeX;
                double      pixWidthY     = gfov.PixelSizeY;
                double      pixPerArcSecX = pixWidthX / asWidthX;
                double      pixPerArcSecY = pixWidthY / asWidthY;
                //Compute the size of a box, in pixels, that would be 2X the calibration range
                //TSX does not compensate for binning in the pixelSize so the results
                //must be doubled if binning 2x2
                int    binMult = tPlan.GuiderBinning;
                double pixBoxX = 2 * (tPlan.XAxisMoveTime * pixPerArcSecX) * binMult;
                double pixBoxY = 2 * (tPlan.YAxisMoveTime * pixPerArcSecX) * binMult;
                //Compute the subframe using the preset guidestar position
                gCam.SubframeTop    = (int)(tPlan.GuideStarY - (pixBoxY / 2));
                gCam.SubframeBottom = (int)(tPlan.GuideStarY + (pixBoxY / 2));
                gCam.SubframeLeft   = (int)(tPlan.GuideStarX - (pixBoxX / 2));
                gCam.SubframeRight  = (int)(tPlan.GuideStarX + (pixBoxX / 2));
            }
            //Take an image for picking a calibration star, but don't save it
            int tstat = gCam.GetImage();

            //Run Calibration, note that the mount calibration will always be done.  The AO calibration is optional.
            lg.LogIt("Calibrating Direct Guide");
            gCam.Calibrate(false);
            if (tPlan.AOEnabled)
            {
                lg.LogIt("Calibrating AO");
                gCam.Calibrate(true);
            }
            //Store vectors
            tPlan.CalVectorXPosXComponent = gCam.CalibrationVectorXPositiveXComponent;
            tPlan.CalVectorXPosYComponent = gCam.CalibrationVectorXPositiveYComponent;
            tPlan.CalVectorXPosXComponent = gCam.CalibrationVectorXPositiveXComponent;
            tPlan.CalVectorXPosYComponent = gCam.CalibrationVectorXPositiveYComponent;
            tPlan.CalVectorYNegXComponent = gCam.CalibrationVectorXNegativeXComponent;
            tPlan.CalVectorYNegYComponent = gCam.CalibrationVectorXNegativeYComponent;
            tPlan.CalVectorYNegXComponent = gCam.CalibrationVectorXNegativeXComponent;
            tPlan.CalVectorYNegYComponent = gCam.CalibrationVectorXNegativeYComponent;
            lg.LogIt("Guider Calibration Complete");
        }
예제 #25
0
        //Fires up the autoguider including picking a star and optimizing the exposure time
        public static void AutoGuideStart()
        {
            //Turns on autoguiding, assuming that everything has been initialized correctly
            LogEvent       lg                    = new LogEvent();
            SessionControl openSession           = new SessionControl();
            TargetPlan     tPlan                 = new TargetPlan(openSession.CurrentTargetName);
            double         autoguideExposureTime = tPlan.GuideExposure;

            lg.LogIt("Starting Autoguiding");
            LogVectors();

            AstroImage asti = new AstroImage
            {
                Camera   = AstroImage.CameraType.Guider,
                BinX     = tPlan.GuiderBinning,
                BinY     = tPlan.GuiderBinning,
                Frame    = AstroImage.ImageType.Light,
                Exposure = tPlan.GuideExposure
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            //Compute delay based on guider cycle time.  Zero means no delay;
            double agDelay = tPlan.GuiderCycleTime;

            if (agDelay > asti.Exposure)
            {
                asti.Delay = agDelay - asti.Exposure;
            }
            else
            {
                asti.Delay = 0;
            }

            //Create new guider object for running the guider
            //then center the AO, if enabled
            TSXLink.Camera gCam = new TSXLink.Camera(asti)
            {
                AutoSaveOn = 0
            }
            ;
            if (tPlan.AOEnabled)
            {
                try { gCam.CenterAO(); }
                catch (Exception e) { lg.LogIt("AO Centering Error: " + e.Message); }
            }

            //guide star and exposure should have already been run
            //turn on guiding
            int agstat = gCam.AutoGuiderOn();

            if (agstat != 0)
            {
                lg.LogIt("Autoguide start up error " + agstat.ToString());
            }
            lg.LogIt("Autoguiding Started");
        }
예제 #26
0
        public static int ComputeNewFocusPosition(string focFilePath, double CurrentTemp, int filterIndex)
        {
            //Opens and interpolates .foc file for luminance filter, returns computed position in steps based on Current Temperature
            LogEvent lg = new LogEvent();

            //File and filter data structure
            int FtextFields     = 2;
            int FtextColorField = 0;
            int FtextDataField  = 1;
            int FdataFieldCount = 4;
            int FposDataOffset  = 1;
            int FtempDataOffset = 3;

            //Open foc file
            lg.LogIt("Reading focus file: " + focFilePath);
            StreamReader sr = new StreamReader(focFilePath);

            try
            {
                string FocuserCount = sr.ReadLine();
            }
            catch (Exception ex)
            {
                lg.LogIt("The focus file could not be found: " + ex.Message);
                return(0);
            }
            lg.LogIt("Focus file read");

            //Open, read in and partially parse the focus file to a text array,) { close it up
            string ConfigName      = sr.ReadLine();
            string FocuserName     = sr.ReadLine();
            string FilterCountText = sr.ReadLine();
            int    filtercount     = Convert.ToInt32(FilterCountText);

            string[,] ftextdata = new string[filtercount, FtextFields];

            //int ftextrecord = 0;
            for (int ftextrecord = 0; ftextrecord < filtercount; ftextrecord++)
            {
                ftextdata[ftextrecord, FtextColorField] = sr.ReadLine();
                ftextdata[ftextrecord, FtextDataField]  = sr.ReadLine();
            }
            sr.Close();

            //Parse out the Luminance data
            string[] fdata_lum    = ftextdata[filterIndex, FtextDataField].Split(',');
            int      focdatacount = (fdata_lum.Length - 1) / FdataFieldCount;

            if (focdatacount < 2)
            {
                lg.LogIt("Too few datapoints to compute focus");
                return(0);
            }
            //parse out temp and position tuples for luminance
            double[] tempdata = new double[30];
            double[] posdata  = new double[30];
            for (int i = 0; i < focdatacount; i++)
            {
                posdata[i]  = Convert.ToDouble(fdata_lum[(i * FdataFieldCount) + FposDataOffset + 1]);
                tempdata[i] = Convert.ToDouble(fdata_lum[(i * FdataFieldCount) + FtempDataOffset + 1]);
            }

            //Compute Least Mean Squares slope and intercept for focus data
            double posmean  = 0;
            double tempmean = 0;

            for (int i = 0; i < focdatacount; i++)
            {
                posmean  += posdata[i];
                tempmean += tempdata[i];
            }
            posmean  = posmean / focdatacount;
            tempmean = tempmean / focdatacount;
            double sumtemppos = 0;
            double sumtemp    = 0;

            for (int i = 0; i < focdatacount; i++)
            {
                sumtemppos += (posdata[i] - posmean) * (tempdata[i] - tempmean);
                sumtemp    += Math.Pow((tempdata[i] - tempmean), 2);
            }
            double slope     = sumtemppos / sumtemp;
            double intercept = posmean - (slope * tempmean);
            //Compute position for current temp
            double currentposition = intercept + slope * CurrentTemp;

            lg.LogIt("Focus position computed: " + ((int)currentposition).ToString());

            //return the computed position for the given temperature
            return((int)currentposition);
        }
예제 #27
0
        public static bool CalibrateRotator()
        {
            ///Calibration procedure for rotator
            ///The purpose is to determine the direction of rotation for positive
            ///  angular input, and the degree the absolute position angle of the rotator
            ///  is offset from the position angle of the camera.
            ///
            ///Plate-solve for the image position angle of the current rotator position
            ///  save the rotator position angle
            ///Rotate +10 degrees (add 10 to current angle reading)
            ///Platesolve the image position angle for this new rotator angle.
            ///  if the new image position angle is 10 greater than the old position angle (mod 360)
            ///    then set the rotator direction vector to 1 (Clockwise), otherwise it's -1 (Counterclockwise).
            ///Rotate -10 degrees to get back to the original position
            ///Plate-solve again to get another image position angle
            ///Average the two angle changes and save the result as the rotator offset value.

            //At this point, the PlateSolve should have "set" the position angle of the rotator

            const double TestAngle = 10;

            //Turn on the logger
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Plate solving current rotator position");
            if (!PlateSolveIt())
            {
                return(false);
            }

            //double rotatorOffset = NHUtil.ReduceTo360(ImagePA - RealRotatorPA);
            double rotatorOffset    = ImagePA - RealRotatorPA;
            int    rotatorDirection = Math.Sign(RealRotatorPA);

            lg.LogIt("Current rotator position solved");

            StartRotatorAngle = RealRotatorPA;
            StartImagePA      = ImagePA;
            //Rotate by +X degrees
            lg.LogIt("Rotating by +" + TestAngle.ToString("0") + " Degrees");
            RotateToRotatorPA(StartRotatorAngle + TestAngle);
            lg.LogIt("Plate solving new position");
            if (!PlateSolveIt())
            {
                return(false);
            }
            lg.LogIt("Rotated position successfully solved");
            EndRotatorAngle = RealRotatorPA;
            EndImagePA      = ImagePA;
            //endImagePA = pSolve2.ImagePA;
            //endRotatorAngle = pSolve2.RotatorPositionAngle;

            //Rotate by -X degrees
            lg.LogIt("Rotating by " + (-TestAngle).ToString("0") + " Degrees");
            RotateToRotatorPA(StartRotatorAngle);
            TSXLink.PlateSolution pSolve3 = new TSXLink.PlateSolution();
            if (pSolve3 == null)
            {
                return(false);
            }

            rotatorOffset = (StartImagePA - StartRotatorAngle);
            if (StartImagePA + TestAngle < 360)
            {
                if (StartImagePA > EndImagePA)
                {
                    rotatorDirection = -1;
                }
                else
                {
                    rotatorDirection = 1;
                }
            }
            else if (StartImagePA < EndImagePA)
            {
                rotatorDirection = -1;
            }
            else
            {
                rotatorDirection = 1;
            }

            RotatorDirection             = rotatorDirection;
            openSession.RotatorDirection = rotatorDirection;
            lg.LogIt("Rotator behavior successfully calibrated");
            return(true);
        }
예제 #28
0
        //Execute TSX_AutoGuide class
        //  Image guider camera
        //  Calibrate autoguide
        //  Autoguide
        //  Autoguide Profiler

        //MaxPixel-based method for getting the ADU of a guide star
        public static double GuideStarMaxPixel(double exposure)
        {
            //Take a subframe image on the guider, assuming it has been already set
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();
            TargetPlan     tPlan       = new TargetPlan(openSession.CurrentTargetName);

            lg.LogIt("Creating Guider Subframe Image");
            AstroImage asti = new AstroImage
            {
                Camera   = AstroImage.CameraType.Guider,
                Frame    = AstroImage.ImageType.Light,
                BinX     = tPlan.GuiderBinning,
                BinY     = tPlan.GuiderBinning,
                SubFrame = 1,
                Delay    = 0,
                Exposure = exposure
            };

            //Set image reduction
            if (tPlan.GuiderAutoDarkEnabled)
            {
                asti.ImageReduction = AstroImage.ReductionType.AutoDark;
            }
            else
            {
                asti.ImageReduction = AstroImage.ReductionType.None;
            }
            //Create camera object and turn turn off autosave, if on
            TSXLink.Camera gCam = new TSXLink.Camera(asti)
            {
                AutoSaveOn = 0
            };
            //Center up AO, just in case and if enabled
            if (tPlan.AOEnabled)
            {
                gCam.CenterAO();
            }

            //Compute the subframe from the trackbox size
            int sizeX = gCam.TrackBoxX;
            int sizeY = gCam.TrackBoxY;

            gCam.SubframeTop    = (int)(tPlan.GuideStarY * tPlan.GuiderBinning) - (sizeY / 2);
            gCam.SubframeBottom = (int)(tPlan.GuideStarY * tPlan.GuiderBinning) + (sizeY / 2);
            gCam.SubframeLeft   = (int)(tPlan.GuideStarX * tPlan.GuiderBinning) - (sizeX / 2);
            gCam.SubframeRight  = (int)(tPlan.GuideStarX * tPlan.GuiderBinning) + (sizeX / 2);

            int tstat = gCam.GetImage();

            if (tstat != 0)
            {
                lg.LogIt("Autoguider Image Error: " + tstat.ToString());
                return(0);
            }
            lg.LogIt("Guider Subframe image successful");

            double maxPixel = gCam.MaximumPixel;

            return(maxPixel);
        }
예제 #29
0
        public void TakeFlats()
        {
            //Pulls flat requests from the flat stack (file) and services accordingly
            LogEvent       lg          = new LogEvent();
            SessionControl openSession = new SessionControl();

            lg.LogIt("Checking for flat requests");

            //Opt out if no flats to look at
            if (!HaveFlatsToDo())
            {
                lg.LogIt("No flats to do");
                return;
            }
            else
            {
                lg.LogIt("Have flats do: Starting Flats");
            }

            //Fire off flatman if enabled, otherwise point the telescope up for dawn or dusk flats
            // Sort flats by filter and source (i.e. twightlight or dawn)
            if (openSession.IsFlatManEnabled)
            {
                //Stage the mount to the flatman
                FlatMan flmn = new FlatMan();
                lg.LogIt("Staging FlatMan");
                bool stgResult = flmn.FlatManStage();
                if (!stgResult)
                {
                    lg.LogIt("FlatMan Staging Failed -- aborting flats");
                    return;
                }
                //If Manual Setup is selected, then pause for user to position the FlatMan for flats
                //  Disconnect imaging devices before attaching panel, then reconnect afterwards
                //    this keeps the SBIG driver from freaking out when the guider USB is hot swapped
                //    with the FlatMan USB (Build 182+)
                if (openSession.IsFlatManManualSetupEnabled)
                {
                    lg.LogIt("Pausing to attach FlatMan panel");
                    lg.LogIt("Disconnecting imaging devices");
                    TSXLink.Connection.DisconnectDevice(TSXLink.Connection.Devices.Camera);
                    TSXLink.Connection.DisconnectDevice(TSXLink.Connection.Devices.Guider);
                    TSXLink.Connection.DisconnectDevice(TSXLink.Connection.Devices.Focuser);
                    TSXLink.Connection.DisconnectDevice(TSXLink.Connection.Devices.Rotator);
                    MessageBox.Show("Attach the FlatMan, then press OK");
                    lg.LogIt("Connecting imaging devices");
                    TSXLink.Connection.ConnectDevice(TSXLink.Connection.Devices.Camera);
                    TSXLink.Connection.ConnectDevice(TSXLink.Connection.Devices.Guider);
                    TSXLink.Connection.ConnectDevice(TSXLink.Connection.Devices.Focuser);
                    TSXLink.Connection.ConnectDevice(TSXLink.Connection.Devices.Rotator);
                }
                //Turn on Flatman panel, if it hasn't been done already
                lg.LogIt("Lighting up FlatMan panel");
                flmn.Light = true;
            }
            else //Dusk or dawn flats
            {
                //Unpark mount, if parked, which it often is to do dusk flats
                TSXLink.Mount.UnPark();
                //point telescope essentially up
                lg.LogIt("Pointing telescope just west of zenith");
                TSXLink.Mount.SlewAzAlt(200.0, (60), "Flat Spot");
                //Turn tracking off
                TSXLink.Mount.TurnTrackingOff();
            }

            //Alright, all ready to go.
            //Loop on the flat entries in the flat stack file, if any
            while (HaveFlatsToDo())
            {
                switch (openSession.FlatLightSource)
                {
                case (LightSource.lsNone):
                {
                    break;
                }

                case (LightSource.lsFlatMan):
                {
                    if (openSession.IsFlatManEnabled)
                    {
                        // **********************  Use Flatman
                        //Rotate to PA, if there is a rotator is enabled
                        Flat iFlat = GetLeastRotatedFlat();
                        if (openSession.IsRotationEnabled)
                        {
                            Rotator.RotateToRotatorPA(iFlat.RotationPA);
                        }
                        Imaging nhi = new Imaging();
                        nhi.DoFlatManFlats(iFlat.TargetName, iFlat.RotationPA, iFlat.SideOfPier, iFlat.FlatFilter);
                        RemoveFlat(iFlat);          //remove flat from flat stack file
                    }
                    break;
                }

                case (LightSource.lsDusk):
                {
                    //  ********************  Use Dusk
                    Flat    iFlat = GetLowestIndexFlat();
                    Imaging nhi   = new Imaging();
                    nhi.DoTwilightFlats(iFlat, true);
                    RemoveFlat(iFlat);          //remove flat from flat stack file
                    break;
                }

                case (LightSource.lsDawn):
                {
                    //  ********************  Use Dawn
                    Flat    iFlat = GetHighestIndexFlat();
                    Imaging nhi   = new Imaging();
                    nhi.DoTwilightFlats(iFlat, false);
                    RemoveFlat(iFlat);          //remove flat from flat stack file
                    break;
                }

                default: break;
                }
            }
            //If FlatMan was used, then shut it down
            if (openSession.IsFlatManEnabled)
            {
                //Turn off flatman functions
                FlatMan flmn = new FlatMan();
                lg.LogIt("Terminating FlatMan");
                //Turn on Flatman panel, if it hasn't been done already
                lg.LogIt("Turning off FlatMan panel");
                flmn.Light = false;
                //If Manual Setup is selected, then pause for user to position the FlatMan for flats
                if (openSession.IsFlatManManualSetupEnabled)
                {
                    lg.LogIt("Pausing to detach FlatMan panel");
                    MessageBox.Show("Detach the FlatMan, then press OK");
                }
            }

            //Turn tracking on
            TSXLink.Mount.TurnTrackingOn();
            //Park the mount
            TSXLink.Mount.Park();
            return;
        }