private TargetData GraphSource(TargetData sourceStar) { //This routine produces a 3D graph of a star//s astrometric information, from the center out to twice the FWHM radius. // using the Source Inventory as at the inventory Index //Check to see if the star was in the inventory array // if not, then just return int inventoryIndex = sourceStar.InventoryArrayIndex; if (inventoryIndex < 0) { return(sourceStar); } //Get the star center (x,y) and 2xFWHM (in pixels), as well as the maximum X and Y values double XMax = TSX_Image.WidthInPixels - 1; double YMax = TSX_Image.HeightInPixels - 1; double XCen = (double)XPosArr[inventoryIndex]; double YCen = (double)YPosArr[inventoryIndex]; int fwhmSpan = (int)((double)FWHMArr[inventoryIndex] * 2); if (fwhmSpan < 0) { fwhmSpan = 0; } //Calculate the lowest and highest X positions for twice the FWHM int Pix0 = (int)(XCen - (fwhmSpan / 2)); if (Pix0 < 0) { Pix0 = 0; } double PixN = XCen + (fwhmSpan / 2); if (PixN > XMax) { PixN = XMax; } Series[] Ypix = new Series[fwhmSpan]; object[] Yline; StarADUChart.Series.Clear(); SourceFWHMBox.Text = ((double)FWHMArr[inventoryIndex]).ToString("0.00"); SourceEllipticityBox.Text = ((double)EllipticityArr[inventoryIndex]).ToString("0.00"); sourceStar.SourceEllipticity = (double)EllipticityArr[inventoryIndex]; sourceStar.SourceFWHM = (double)FWHMArr[inventoryIndex]; //Convert X,Y coordinates to RA,Dec coordinates double cerr = TSX_Image.XYToRADec((double)XPosArr[inventoryIndex], (double)YPosArr[inventoryIndex]); sourceStar.SourceRA = TSX_Image.XYToRADecResultRA(); sourceStar.SourceDec = TSX_Image.XYToRADecResultDec(); //Cataloged star should have already been found during Analysis StarADUChart.Titles[0].Text = sourceStar.APASSCatalogName; //PhotometryCatMagBox.Text = sourceStar.CatMagnitude.ToString("0.00"); //PhotometrySourceMagBox.Text = ((double)MagArr[inventoryIndex]).ToString("0.00"); //PhotometryAllCatalogCorrectedMagBox.Text = ((double)MagArr[inventoryIndex] + MeanMagDelta).ToString("0.00"); //Create the graph series for the 2XFWHM X range around X center, for the 2XFWHM Y range around the Y center // making sure to cut off any excursion either below 0 or about the X or Y ranges // //So... for a 2XFWHM number of data series, int maxStarADU = 0; for (int i = 0; i < fwhmSpan; i++) { //Create a series object for the scanned line and attach it to the graph Ypix[i] = new Series(i.ToString()); StarADUChart.Series.Add(Ypix[i]); //Scan in the } data series from the image, if it runs over the range, presumably it will truncate normally int lineIndex = (int)(i + YCen - (fwhmSpan / 2)); if (lineIndex >= 0 && lineIndex < YMax) { Yline = TSX_Image.scanLine(lineIndex); //Write the pixel values to the series while checking for saturation (indicate in the label). // and for the maximum ADU value for (int j = Pix0; j <= PixN; j++) { if (j < Yline.Length) { int adu = (int)Yline[j]; if (adu > maxStarADU) { maxStarADU = adu; } Ypix[i].Points.Add(adu * PixelScale_arcsec); } } } //Set the chart configuration and display Ypix[i].XValueType = ChartValueType.Auto; Ypix[i].ChartType = SeriesChartType.SplineArea; Ypix[i].MarkerStyle = MarkerStyle.Circle; } //set the maximum ADU as the value at the center if (maxStarADU > SaturationADU) { MaxADULabel.ForeColor = Color.Black; MaxADULabel.BackColor = Color.Pink; } else { MaxADULabel.ForeColor = Color.White; MaxADULabel.BackColor = Color.Empty; } SourcePeakADUBox.Text = maxStarADU.ToString("0"); sourceStar.SourceADU = maxStarADU; //All done return(sourceStar); }
private TargetData GraphMagnitudes(TargetData tData) { //Graphs the ccd magnitude against the catalog magnitude // for all light sources for which cooresponding cataloged stars // can be found. //List of star names found from catalog for stars List <string> catStarNames = new List <string>(); //List of magnitudes as determined by TSX List <double> sexMagPlotPoints = new List <double>(); //List of magnitudes as taken from catalog data List <double> catMagPlotPoints = new List <double>(); //List of ADU's as determined from image data List <double> imgADUPlotPoints = new List <double>(); //List of valid Target Data objects from APASS database List <TargetData> validCatalogedStars = new List <TargetData>(); magArrPlotIndex = new List <int>(); //Clear the Photometry Chart of plotted points PhotometryChart.Series[0].Points.Clear(); //Display the total number of stars to analyze from the image light source arrays SourceCountBox.Text = "/" + MagArr.Length.ToString("0"); Color savebackcolor = SourceCountBox.BackColor; for (int sIdx = 0; sIdx < WCSActiveArr.Length; sIdx++) { //Use a count down of the star count as a progress bar SourceCountBox.Text = (sIdx + 1).ToString("0") + "/" + WCSActiveArr.Length.ToString("0"); //if the source is "active" (meaning used for imagelinking) // get it's RA/Dec and pull up its Inventory data // Search the catalogs and create a target data object, // and, if found, add the source and catalog magnitudes // and save to the culled list of targets (validStarPoints) if ((int)(double)WCSActiveArr[sIdx] == 1) { //Gather Inventory at WCS target double raStar = (double)WCSRAArr[sIdx]; double decStar = (double)WCSDecArr[sIdx]; //Get the Inventory for the light source nearest this ra,dec location var wcsInventory = TSX_Image.FindInventoryAtRADec(raStar, decStar); //Load the information into a Target Data object try { TargetData wcsStarData = new TargetData() { SourceRA = raStar, SourceDec = decStar, SourceUncorrectedMagnitude = (double)wcsInventory[(int)TSXEnums.ccdsoftInventoryIndex.cdInventoryMagnitude] }; //Add catalog data based on nearest APASS star wcsStarData = NearestCatalogedStar.AcquireNearestQualifiedStar(wcsStarData); //Get ADU at image X,Y position // Note: the Zero Y line is the top line of the image int xPos = (int)wcsInventory[(int)TSXEnums.ccdsoftInventoryIndex.cdInventoryX]; int yPos = (int)wcsInventory[(int)TSXEnums.ccdsoftInventoryIndex.cdInventoryY]; object[] xDataLine = TSX_Image.scanLine(yPos); int xyADU = (int)xDataLine[xPos]; wcsStarData.SourceADU = xyADU; //Put the equivalent filter magnitude in the catalog magnitude field wcsStarData = Filters.SetMagnitudeForFilter(wcsStarData, tData.ImageFilter); if (wcsStarData.IsAPASSCataloged && wcsStarData.IsGAIACataloged && wcsStarData.APASSCatalogMagnitude < 30 && wcsStarData.GAIACatalogMagnitude < 30 && wcsStarData.SourceADU <= NonLinearADU && !wcsStarData.IsGCVSCataloged) { validCatalogedStars.Add(wcsStarData); } } catch { }; } } //Create arrays for source and catalog magnitudes double[] apassMagDeltaArray = new double[validCatalogedStars.Count]; double[] gaiaMagDeltaArray = new double[validCatalogedStars.Count]; double[] sourceMagDeltaArray = new double[validCatalogedStars.Count]; double[] apass_gaia_differenceArray = new double[validCatalogedStars.Count]; for (int i = 0; i < validCatalogedStars.Count; i++) { apassMagDeltaArray[i] = validCatalogedStars[i].APASSCatalogMagnitude; gaiaMagDeltaArray[i] = validCatalogedStars[i].GAIACatalogMagnitude; sourceMagDeltaArray[i] = validCatalogedStars[i].SourceUncorrectedMagnitude; apass_gaia_differenceArray[i] = validCatalogedStars[i].APASSCatalogMagnitudeG - validCatalogedStars[i].GAIACatalogMagnitudeG; } //Calculate APASS statistics try { //Regression of APASS star magnitudes to linear function mx+b Tuple <double, double> lineFitSourceToAPASS = MathNet.Numerics.Fit.Line(sourceMagDeltaArray, apassMagDeltaArray); double sourceCorrectedSourceToAPASS = (tData.SourceUncorrectedMagnitude * lineFitSourceToAPASS.Item2) + lineFitSourceToAPASS.Item1; //Calculation of r2 double rSquaredSourceToAPASS = MathNet.Numerics.GoodnessOfFit.RSquared(sourceMagDeltaArray.Select (x => lineFitSourceToAPASS.Item1 + (lineFitSourceToAPASS.Item2 * x)), apassMagDeltaArray); //Calculation of APASS Population Standard Error double pseSourceToAPASS = MathNet.Numerics.GoodnessOfFit.PopulationStandardError(sourceMagDeltaArray.Select (x => lineFitSourceToAPASS.Item1 + (lineFitSourceToAPASS.Item2 * x)), apassMagDeltaArray); tData.APASSMagnitudeGradient = lineFitSourceToAPASS.Item2; tData.APASSMagnitudeIntercept = lineFitSourceToAPASS.Item1; tData.APASSSourceCorrectedMagnitude = sourceCorrectedSourceToAPASS; tData.APASSMagnitudeRSquared = rSquaredSourceToAPASS; tData.APASSMagPopulationStandardError = pseSourceToAPASS; // } catch { } //Calculate GAIA statistics try { //Regression of APASS star magnitudes to linear function mx+b Tuple <double, double> lineFitSourceToGAIA = MathNet.Numerics.Fit.Line(sourceMagDeltaArray, gaiaMagDeltaArray); double sourceCorrectedSourceToGAIA = (tData.SourceUncorrectedMagnitude * lineFitSourceToGAIA.Item2) + lineFitSourceToGAIA.Item1; //Calculation of r2 double rSquaredSourceToGAIA = MathNet.Numerics.GoodnessOfFit.RSquared(sourceMagDeltaArray.Select (x => lineFitSourceToGAIA.Item1 + (lineFitSourceToGAIA.Item2 * x)), gaiaMagDeltaArray); //Calculation of APASS Population Standard Error double pseSourceToGAIA = MathNet.Numerics.GoodnessOfFit.PopulationStandardError(sourceMagDeltaArray.Select (x => lineFitSourceToGAIA.Item1 + (lineFitSourceToGAIA.Item2 * x)), gaiaMagDeltaArray); tData.GAIAMagnitudeGradient = lineFitSourceToGAIA.Item2; tData.GAIAMagnitudeIntercept = lineFitSourceToGAIA.Item1; tData.GAIASourceCorrectedMagnitude = sourceCorrectedSourceToGAIA; tData.GAIAMagnitudeRSquared = rSquaredSourceToGAIA; tData.GAIAMagPopulationStandardError = pseSourceToGAIA; } catch { } //Plot the APASS catalog vrs source mag for (int sIdx = 0; sIdx < validCatalogedStars.Count; sIdx++) { double catMag = validCatalogedStars[sIdx].APASSCatalogMagnitude; double sexMag = validCatalogedStars[sIdx].SourceUncorrectedMagnitude; if (Utility.IsBetween(maxMagVal, catMag, minMagVal)) { sexMagPlotPoints.Add(sexMag); catMagPlotPoints.Add(catMag); magArrPlotIndex.Add(sIdx); //get index for next point in graphed series int pLast = PhotometryChart.Series[0].Points.Count; //Add the next point to the graph PhotometryChart.Series[0].Points.AddXY(sexMag, catMag); } } //Calculate vectors for the ceiling and floor of photometry chart, if any if (sexMagPlotPoints.Count > 0) { double[] catVals = new double[sexMagPlotPoints.Count]; double[] sexVals = new double[sexMagPlotPoints.Count]; for (int i = 0; i < sexMagPlotPoints.Count; i++) { catVals[i] = catMagPlotPoints[i]; sexVals[i] = sexMagPlotPoints[i]; } tData.APASSStarCount = apassMagDeltaArray.Length; tData.GAIAStarCount = gaiaMagDeltaArray.Length; PhotometryChart.ChartAreas[0].AxisX.Interval = 1; PhotometryChart.ChartAreas[0].AxisY.Interval = 1; PhotometryChart.ChartAreas[0].AxisX.Maximum = Math.Ceiling(sexVals.Max()) + 1; PhotometryChart.ChartAreas[0].AxisX.Minimum = Math.Floor(sexVals.Min()) - 1; PhotometryChart.ChartAreas[0].AxisY.Maximum = Math.Ceiling(catVals.Max()) + 1; PhotometryChart.ChartAreas[0].AxisY.Minimum = Math.Floor(catVals.Min()) - 1; } return(tData); }
private TargetData Analyze(string targetName, double targetRA, double targetDec) { //This is the primary routine. The current image in TSX is activated and FITS information acquired. // The image is { sent through image link to compute WCS information for each star. // The results are sorted by magnitude, averaged, seeing estimated and results displayed. // Configuration cfg = new Configuration(); TargetData targetData = new TargetData() { TargetName = targetName, TargetRA = targetRA, TargetDec = targetDec }; //tsximg = new ccdsoftImage(); TSXimglnk = new ImageLink(); //Using FITS file information... FITImage = new Fits(TSX_Image); //Compute pixel scale = 206.256 * pixel size (in microns) / focal length //Set initial values in case the FITS words aren't there FITImage.PixSize = FITImage.PixSize ?? 9; //if (FITImage.FocalLength == null) // MessageBox.Show("Focal Length was not set for this FITS image: defaulting to 2000 mm"); FITImage.FocalLength = FITImage.FocalLength ?? 2563; //mm //if (FITImage.Aperture == null) // MessageBox.Show("Aperture was not set for this FITS image: defaulting to 254 mm"); FITImage.Aperture = FITImage.Aperture ?? 356.0; //mm FocalRatio = (double)FITImage.FocalLength / (double)FITImage.Aperture; targetData.ImageFilter = FITImage.Filter; targetData.ImageDate = FITImage.FitsUTCDateTime; targetData.AirMass = (double)(FITImage.FitsAirMass ?? 0); FITImage.Exposure = FITImage.Exposure ?? 0; // focal length must be set to correct value in FITS header -- comes from camera set up in TSX PixelScale_arcsec = ConvertToArcSec((double)FITImage.PixSize, (double)FITImage.FocalLength); //Set the pixel scale for an InsertWCS image linking TSX_Image.ScaleInArcsecondsPerPixel = PixelScale_arcsec; //set saturation threshold SaturationADU = Math.Pow(2, (double)FITImage.PixBits) * 0.95; //set nonlinear threshold NonLinearADU = Convert.ToDouble(cfg.ADUMax); //ImageLink for light sources (Insert WCS) try { int ferr = TSX_Image.InsertWCS(true); } catch { targetData.IsImageLinked = false; return(targetData); } targetData.IsImageLinked = true; //Collect astrometric light source data from the image linking into single index arrays: // magnitude, fmhm, ellipsicity, x and y position try { MagArr = (TSX_Image.InventoryArray((int)TSXEnums.ccdsoftInventoryIndex.cdInventoryMagnitude)); } catch { targetData.IsImageLinked = false; return(targetData); } FWHMArr = TSX_Image.InventoryArray((int)TSXEnums.ccdsoftInventoryIndex.cdInventoryFWHM); //FMHW, we think EllipticityArr = TSX_Image.InventoryArray((int)TSXEnums.ccdsoftInventoryIndex.cdInventoryEllipticity); //Ellipsity, we think XPosArr = TSX_Image.InventoryArray((int)TSXEnums.ccdsoftInventoryIndex.cdInventoryX); //X position, we think YPosArr = TSX_Image.InventoryArray((int)TSXEnums.ccdsoftInventoryIndex.cdInventoryY); //Y position, we think //Collect light sources used for image linking try { WCSActiveArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdActive); } catch { return(targetData); } WCSRAArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSRA); WCSDecArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSDec); WCSXPosArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSX); WCSYPosArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSY); WCSResidualArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSResidual); WCSCatalogIDArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSCatalogID); WCSPositionErrorArr = TSX_Image.WCSArray((int)TSXEnums.ccdsoftWCSIndex.cdWCSPositionError); //Fill in Seeing Analysis information in the windows form: //Instrument info FocalLengthBox.Text = ((double)FITImage.FocalLength).ToString("0"); ApertureBox.Text = ((double)FITImage.Aperture).ToString("0"); FocalRatioBox.Text = FocalRatio.ToString("0.0"); PixSizeMicronBox.Text = ((double)FITImage.PixSize).ToString("0.0"); PixSizeArcSecBox.Text = (ConvertToArcSec((double)FITImage.PixSize, (double)FITImage.FocalLength)).ToString("0.00"); MaxResolutionArcSecBox.Text = ((ConvertToArcSec((double)FITImage.PixSize, (double)FITImage.FocalLength)) * 3.3).ToString("0.00"); AirMassBox.Text = ((double)(FITImage.FitsAirMass ?? 0)).ToString("0.000"); double FWHMAvg_pixels = MathNet.Numerics.Statistics.ArrayStatistics.Mean(Array.ConvertAll <object, double>(FWHMArr, x => (double)x)); EllipticityAvg = MathNet.Numerics.Statistics.ArrayStatistics.Mean(Array.ConvertAll <object, double>(EllipticityArr, x => (double)x)); //Star Size = (Seeing * Focal Length)/206.3 => Seeing = Star Size *206.3/focal length or Seeing = FWHM * focal length/ 206.3* microns; double FWHMAvg_arcsec = FWHMAvg_pixels * TSX_Image.ScaleInArcsecondsPerPixel; double FWHMAvg_micron = FWHMAvg_pixels * (double)FITImage.PixSize; SeeingMeanFWHMBox.Text = FWHMAvg_arcsec.ToString("0.00"); FWHMSeeing_arcsec = FWHMAvg_micron * 206.3 / ((double)FITImage.FocalLength); SeeingClassBox.Text = GetSeeingClass(FWHMAvg_arcsec, (double)FITImage.Aperture); targetData.ComputedSeeing = GetSeeingClass(FWHMAvg_arcsec, (double)FITImage.Aperture); SeeingMeanEllipticityBox.Text = EllipticityAvg.ToString("0.00"); //Create sorted index of stars, based on magnitude, high to low //Generate initial ordered array //Set the global sort array index to the first (greatest magnitude) entry {. //Create new target data for this variable target targetData = SearchForLightSourceInventory(TSX_Image, targetData); targetData = NearestCatalogedStar.AcquireNearestQualifiedStar(targetData); if (FitsIsOpen) { //Done //Display target, date and time for fits file FitsNameBox.Text = FITImage.FitsTarget; FitsDateBox.Text = FITImage.FitsUTCDate; FitsTimeBox.Text = FITImage.FitsUTCTime; //MeanLumBox.Text = MeanAduToMag(24000).ToString("0.0"); double backgroundADU = TSX_Image.Background; SourceBackgroundADUBox.Text = backgroundADU.ToString("0"); FitsExposureBox.Text = ((double)FITImage.Exposure).ToString("0.0"); FitsFilterBox.Text = FITImage.Filter; //Set the global value for the maximum pixel (used for determine staturation) at 95% of maximum ADU } return(targetData); }