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); }
//Grease slick to check if autoguiding is already running public static bool IsAutoGuideOn() { SessionControl openSession = new SessionControl(); TargetPlan tPlan = new TargetPlan(openSession.CurrentTargetName); AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Guider }; TSXLink.Camera gCam = new TSXLink.Camera(asti); return(gCam.IsAutoGuideOn()); }
//Aborts autoguiding, if running public static void AutoGuideStop() { //Halt Autoguiding //Open default image so we can turn the guider off then open guider and turn it off AstroImage asti = new AstroImage() { Camera = AstroImage.CameraType.Guider }; TSXLink.Camera gCam = new TSXLink.Camera(asti); gCam.AutoGuiderOff(); }
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); }
//*** 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); }
//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); }
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); }
//*** 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"); }
//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); }