//Fires up the autoguider including picking a star and optimizing the exposure time public static bool AutoGuideStart() { //Turns on autoguiding, assuming that everything has been initialized correctly //Disconnect the rotator, if any TSXLink.Rotator.Disconnect(); AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging, BinX = GuiderXBinning, BinY = GuiderYBinning, Frame = AstroImage.ImageType.Light, Exposure = GuideExposure, ImageReduction = AstroImage.ReductionType.AutoDark, 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 }; //guide star and exposure should have already been run //turn on guiding bool agStat = gCam.AutoGuiderOn(); return(agStat); }
//Grease slick to check if autoguiding is already running public static bool IsAutoGuideOn() { AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging }; TSXLink.Camera gCam = new TSXLink.Camera(asti); return(gCam.IsAutoGuideOn()); }
//Aborts autoguiding, if running public static bool 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.Imaging }; TSXLink.Camera gCam = new TSXLink.Camera(asti); gCam.AutoGuiderOff(); return(true); }
} = 0.1; //Default minimum exposure time is 0.1seconds //MaxPixel-based method for getting the ADU in a trackbox-sized subframed image (NOte: could be hot pixel) public static double GetGuideStarMaxPixel(double exposure) { //Take a subframe image on the guider that is centered on a previously centered star // and get the maximum pixel ADU //The procedure assumes no hot pixels AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging, Frame = AstroImage.ImageType.Light, BinX = GuiderXBinning, BinY = GuiderYBinning, SubFrame = 1, Delay = 0, Exposure = exposure, ImageReduction = AstroImage.ReductionType.AutoDark }; //Set image reduction TSXLink.Camera gCam = new TSXLink.Camera(asti) { AutoSaveOn = 0 }; //Compute the subframe from the trackbox size int sizeX = gCam.TrackBoxX; int sizeY = gCam.TrackBoxY; gCam.SubframeTop = (int)GuideStarY - (sizeY / 2); gCam.SubframeBottom = (int)GuideStarY + (sizeY / 2); gCam.SubframeLeft = (int)GuideStarX - (sizeX / 2); gCam.SubframeRight = (int)GuideStarX + (sizeX / 2); int tstat = gCam.GetImage(); if (tstat != 0) { return(0); } double maxPixel = gCam.MaximumPixel; return(maxPixel); }
public Camera(AstroImage asti) { tsxc = new ccdsoftCamera { Autoguider = (int)asti.Camera, BinX = asti.BinX, BinY = asti.BinY, Delay = asti.Delay, Frame = (ccdsoftImageFrame)asti.Frame, ImageReduction = (ccdsoftImageReduction)asti.ImageReduction, Subframe = asti.SubFrame, SubframeBottom = asti.SubframeBottom, SubframeTop = asti.SubframeTop, SubframeRight = asti.SubframeRight, SubframeLeft = asti.SubframeLeft, AutoSaveOn = asti.AutoSave, ExposureTime = asti.Exposure, AutoguiderExposureTime = asti.Exposure }; }
//SexTractor-based method for getting the ADU of the star at the center of a trackbox subframe 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 AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging, SubFrame = 1, Frame = AstroImage.ImageType.Light, BinX = GuiderXBinning, BinY = GuiderYBinning, Delay = 0, Exposure = exposure, ImageReduction = AstroImage.ReductionType.AutoDark }; TSXLink.Camera gCam = new TSXLink.Camera(asti) { AutoSaveOn = 1//Turn on autosave so we can extract a star inventory via ShowInventory() }; //Compute the subframe from the trackbox size int sizeX = gCam.TrackBoxX; int sizeY = gCam.TrackBoxY; gCam.SubframeTop = (int)GuideStarY - (sizeY / 2); gCam.SubframeBottom = (int)GuideStarY + (sizeY / 2); gCam.SubframeLeft = (int)GuideStarX - (sizeX / 2); gCam.SubframeRight = (int)GuideStarX + (sizeX / 2); //Take an image f int tstat = gCam.GetImage(); if (tstat != 0) { return(0); } //Next step is to generate the collection of stars in the subframe TSXLink.SexTractor sEx = new TSXLink.SexTractor(); bool xStat = sEx.SourceExtractGuider(); 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); //Find the star with the greatest FWHM int iMax = sEx.GetListLargest(FWHMlist); //Determine the ADU value at the center of this listed star. // if it is zero, then look for the maximum pixel ADU double maxStarADU = 0; try { maxStarADU = sEx.GetPixelADU((int)CenterX[iMax], (int)CenterY[iMax]); } catch (Exception ex) { MessageBox.Show(ex.Message); maxStarADU = 0;; } if (maxStarADU == 0) { maxStarADU = gCam.MaximumPixel; } return(maxStarADU); }
public static bool PickAutoGuideStar(GuideStarCriteria gsc) { // Subroutine takes a picture, picks a guide star, computes a subframe to put around it, // loads the location and subframe into the autoguider // // The only difference in this procedure from SetBestAutoGuideStar is that it finds the largest FWHM star rather than // the average, and this does not exclude prospects because they have neighbors. // 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 // double MagWeight; double FWHMWeight; double ElpWeight; double ClsWeight; bool CheckNeighbors; // 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: round = 1 // Class optimal is highest class: 0 is galaxy, 1 is star // // Normalized means adjusted against the range of highest to lowest becomes 1 to 0, unless there is only one datapoint // // AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging, SubFrame = 0, Frame = AstroImage.ImageType.Light, BinX = GuiderXBinning, BinY = GuiderYBinning, Delay = 0, Exposure = GuideExposure, ImageReduction = AstroImage.ReductionType.AutoDark }; TSXLink.Camera guider = new TSXLink.Camera(asti) { AutoSaveOn = 1 }; //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 { bool sStat = tsex.SourceExtractGuider(); } catch (Exception ex) { // Just close up, TSX will spawn error window MessageBox.Show("Star Extracdtion Error: " + ex.Message); 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) { 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; 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]; } avgFWHM /= starCount; // Create a set of "best" values double optMag; // Magnitudes increase with negative values double optFWHM; // Looking for the closest to maximum FWHM double optElp; // Want the minimum amount of elongation double optCls; // 1 = star,0 = galaxy //Set selection optimization based on criteria type (maybe more in the future) switch (gsc) { case GuideStarCriteria.Clean: optMag = minMag; // Magnitudes increase with negative values optFWHM = avgFWHM; // Looking for the closest to average FWHM optElp = minElp; // Want the minimum amount of elongation optCls = maxCls; // Want closest to star: 1 = star,0 = galaxy MagWeight = 1; //?Equal weighting FWHMWeight = 1; //?Equal weighting ElpWeight = 1; //?Equal weighting ClsWeight = 1; //?Equal weighting CheckNeighbors = true; break; case GuideStarCriteria.Big: optMag = minMag; // Magnitudes increase with negative values optFWHM = maxFWHM; // Looking for the closest to maximum FWHM optElp = minElp; // Want the minimum amount of elongation optCls = maxCls; // Want closest to star: 1 = star,0 = galaxy MagWeight = 1; //?Equal weighting FWHMWeight = 1; //?Equal weighting ElpWeight = 0; //Don't care ClsWeight = 0; //Don't care CheckNeighbors = true; break; case GuideStarCriteria.Bright: optMag = minMag; // Magnitudes increase with negative values optFWHM = maxFWHM; // Looking for the closest to average FWHM optElp = minElp; // Want the minimum amount of elongation optCls = maxCls; // Want closest to star: 1 = star,0 = galaxy MagWeight = 1; //?Equal weighting FWHMWeight = 1; //Don't care ElpWeight = 1; //Don't care ClsWeight = 1; //Don't care CheckNeighbors = true; break; default: optMag = minMag; // Magnitudes increase with negative values optFWHM = avgFWHM; // Looking for the closest to average FWHM optElp = minElp; // Want the minimum amount of elongation optCls = maxCls; // Want closest to star: 1 = star,0 = galaxy MagWeight = 1; //?Equal weighting FWHMWeight = 1; //?Equal weighting ElpWeight = 1; //?Equal weighting ClsWeight = 1; //?Equal weighting CheckNeighbors = true; break; } // 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; double normPt; 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 normPt = ((normMag * MagWeight) + (normFWHM * FWHMWeight) + (normElp * ElpWeight) + (normCls * ClsWeight)); SourceCount += 1; // Tentatively assign nomalized value array the normalized value NormArr[i] = normPt; // Remove neighbors and edge liers edgekeepout = trackBoxSize; if (IsOnEdge((int)XPosArr[i], (int)YPosArr[i], Xsize, Ysize, edgekeepout)) { NormArr[i] = -1; } if (CheckNeighbors) { for (int j = i + 1; j < NormArr.Length - 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; } } //Register the results guider.GuideStarX = XPosArr[bestOne] * guider.BinX; guider.GuideStarY = YPosArr[bestOne] * guider.BinY; asti.SubframeLeft = (int)(XPosArr[bestOne] - (trackBoxSize / 2)) * guider.BinX; asti.SubframeRight = (int)(XPosArr[bestOne] + (trackBoxSize / 2)) * guider.BinX; asti.SubframeTop = (int)(YPosArr[bestOne] - (trackBoxSize / 2)) * guider.BinY; asti.SubframeBottom = (int)(YPosArr[bestOne] + (trackBoxSize / 2)) * guider.BinY; guider.SubframeLeft = asti.SubframeLeft; guider.SubframeRight = asti.SubframeRight; guider.SubframeTop = asti.SubframeTop; guider.SubframeBottom = asti.SubframeBottom; if (NormArr[bestOne] != -1) { GuideStarX = guider.GuideStarX; GuideStarY = guider.GuideStarY; tsex.Close(); return(true); } else { // Debug code: 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; } } tsex.Close(); return(false); } }
} = 1; // 1=1x1, 2=2x2, 3=3x3, 4=4x4 private void StartButton_Click(object sender, EventArgs e) { //Initialize stuff //Verify camera orientation near 0 degrees //Repeat // Move to target area: Dec =0, HA = .1; // Find nearest guide star with magnitude <8 and positive HA (DBQ PEC_Collect.dbq) // Center on target star // Find star // Set Exposure // Find star again // Run Autoguide for 20 minutes // Abort //Loop //Abort autoguiding, if on AutoGuide.AutoGuideStop(); //Set Binning AutoGuide.GuiderXBinning = Binning; AutoGuide.GuiderYBinning = Binning; //Check orientation //slew to west side near meridian at 0 deg declination double altAtZeroDec = 90 - GetLocationLatitude(); TSXLink.ReliableAzAltSlew(183, altAtZeroDec, ""); // Take image, image link it and get Position Angle AstroImage asti = new AstroImage { Camera = AstroImage.CameraType.Imaging, Frame = AstroImage.ImageType.Light, Delay = 0, Exposure = 10, ImageReduction = AstroImage.ReductionType.AutoDark, BinX = Binning, BinY = Binning }; if (PACheckBox.Checked) { TSXLink.Camera gCam = new TSXLink.Camera(asti) { AutoSaveOn = 1 }; int tstat = gCam.GetImage(); TSXLink.PlateSolution psln = TSXLink.ImageSolution.PlateSolve(gCam.LastImageFilename()); //Check for failed image solution. If so, just return as an error message will have bee3n posted already. if (psln == null) { return; } //Check for the image PA to be 0 +/- 3 degrees // if not then give option to opt out. InsertImagePAinLog(psln.ImagePA); ImagePA = psln.ImagePA; if (!PAValid) { DialogResult dr = MessageBox.Show(("PA " + (int)psln.ImagePA + "is not near 0 or 180. Continue?"), "Camera Orientation Error", MessageBoxButtons.YesNo); if (dr == DialogResult.No) { return; } } else { bool checkWest = PADirection ^ psln.ImageIsMirrored ^ TargetIsWest; //Add info to text output: if (psln.ImageIsMirrored) { OutputTextBox.Text += "\n\r\n\r" + " --> Plate Solved PA = " + ((int)psln.ImagePA).ToString() + " degrees and image is mirrored."; } else { OutputTextBox.Text += "\n\r\n\r" + " -->Plate Solved PA = " + ((int)psln.ImagePA).ToString() + " degrees and image is not mirrored."; } if (checkWest) { OutputTextBox.Text += " Check West in TCS."; } else { OutputTextBox.Text += " Do not check West in TCS."; } } //Passed the orientation test, west side } CompletionTime.Text = (DateTime.Now.AddMinutes((double)LoopsCounter.Value * (double)DurationMinutes.Value + 2)).ToString("HH:mm:ss"); //Loops do { //Set loop number and time left TimeLeft.Text = (TimeSpan.FromMinutes((int)DurationMinutes.Value).ToString("T")); //Reset Camera AstroImage nasti = new AstroImage { Camera = AstroImage.CameraType.Imaging, Frame = AstroImage.ImageType.Light, Delay = 0, Exposure = 10, SubFrame = 0, ImageReduction = AstroImage.ReductionType.AutoDark, BinX = Binning, BinY = Binning }; TSXLink.Camera ngCam = new TSXLink.Camera(asti) { AutoSaveOn = 1 }; //Slew to just west of the meridian at 0 deg Declination sky6StarChart tsxsc = new sky6StarChart(); TSXLink.ReliableAzAltSlew(183, altAtZeroDec, ""); //find a target star here //check the focus using this star // selected value = 0 for @focus2 // selected value = 1 for @focus3 // selected value = 2 for none switch (FocusComboBox.SelectedIndex) { case 0: AutoFocus.Check(false); break; case 1: AutoFocus.Check(true); break; case 2: break; default: break; } //*** TSXLink.ReliableAzAltSlew(183, altAtZeroDec, ""); StarList.TargetStarSearch(); //slew to and center on the found star int cls1 = TSXLink.ReliableClosedLoopSlew(StarList.TargetRA, StarList.TargetDec, StarList.TargetName); if (cls1 != 0) { return; } //return to base position, assuming that maybe @focus2 went to the wrong side AutoGuide.GuiderXBinning = Binning; AutoGuide.GuiderYBinning = Binning; //Center up the target star as guide star // ** For tracking log purposes, pick the brightest star. //AutoGuide.SetBestAutoGuideStar(); AutoGuide.PickAutoGuideStar(AutoGuide.GuideStarCriteria.Bright); //Optimize it's exposure level AutoGuide.GuideExposure = AutoGuide.OptimizeExposure(); //Start tracking bool gsStatus = AutoGuide.AutoGuideStart(); //Wait for the duration, checking for abort (e.g. End) int durationSecs = (60 * (int)DurationMinutes.Value); for (int i = 0; i < durationSecs; i++) { System.Threading.Thread.Sleep(1000); TimeLeft.Text = (TimeSpan.FromSeconds(durationSecs - i).ToString("T")); this.Show(); System.Windows.Forms.Application.DoEvents(); if (abortFlag) { break; } } //Wait is over, kill the autoguiding/tracking, increment the loop counter and loop AutoGuide.AutoGuideStop(); LoopsCounter.Value -= 1; //Correct log PA if PA as been checked. TSX will not do this for you. if (PACheckBox.Checked) { FixLog.FixImagePA(ImagePA); } //Check for pause -- used for changing PEC Curves when experimenting if (PauseCheckBox.Checked) { MessageBox.Show("Pausing for configuration changes, if any."); } } while ((abortFlag == false) && (LoopsCounter.Value > 0)); }