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(); }
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; }
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; }
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(); }
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; }
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); }
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); }
//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")); }
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; }
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"); }
//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(); }
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); }
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; }
//*** 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); }
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); } } }
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; }
//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; }
//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); }
/// <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); }
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); }
//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); }
//*** 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)); }
//*** 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); } }
//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"); }
//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"); }
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); }
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); }
//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); }
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; }