public bool ExportToCSV(string fileName, CSVExportOptions options)
        {
            var output = new StringBuilder();

            AtmosphericExtinctionCalculator atmExtCalc = null;
            if (options.ExportAtmosphericExtinction)
                atmExtCalc = new AtmosphericExtinctionCalculator(options.RAHours, options.DEDeg, options.LongitudeDeg, options.LatitudeDeg, options.HeightKM);

            string videoSystem;
            double absoluteTimeError = m_TimestampDiscrepencyFlag
                                           ? Math.Abs(m_Header.GetAbsoluteTimeDeltaInMilliseconds(out videoSystem))
                                           : 0;

            uint objCount = m_Header.ObjectCount;
            if (m_LightCurveController.Context.Binning > 0)
            {
                // Binned frames
                int count = m_AllBinnedReadings[0].Count;
                int firstFrameNoInBin = (int)m_Header.MinFrame;

                CSVExportAddCommonHeader(output, options, true);

                output.Append(string.Format("BinNo,Time ({0})", options.FormatTimeLabel()));

                for (int j = 0; j < objCount; j++)
                {
                    output.Append(options.FormatPhotometricValueHeaderForObject(j + 1, false, true));
                }

                bool isBadTime = false;
                double timePrecisionSec = 0;

                double resolutionInSecs = m_LightCurveController.Context.Binning / (2.0 * m_Header.FramesPerSecond);

                if (double.IsInfinity(resolutionInSecs) || double.IsNaN(resolutionInSecs)
                    && m_Header.LcFile != null && m_Header.LcFile.FrameTiming != null && m_Header.LcFile.FrameTiming.Count > 0)
                {

                    List<int> allExposures = m_Header.LcFile.FrameTiming.Select(x => x.FrameDurationInMilliseconds).ToList();
                    allExposures.Sort();
                    resolutionInSecs = m_LightCurveController.Context.Binning * allExposures[allExposures.Count / 2] / 1000.0;
                }

                if (resolutionInSecs < 0.1)
                {
                    timePrecisionSec = 0.001;
                    if (absoluteTimeError > 5) isBadTime = true;
                }
                else if (resolutionInSecs < 1)
                {
                    timePrecisionSec = 0.01;
                    if (absoluteTimeError > 5) isBadTime = true;
                }
                else if (resolutionInSecs < 10)
                {
                    timePrecisionSec = 0.1;
                    if (absoluteTimeError > 50) isBadTime = true;
                }
                else if (absoluteTimeError > 500)
                {
                    timePrecisionSec = 0.01;
                    isBadTime = true;
                }
                else if (!m_LCFile.Footer.ReductionContext.HasEmbeddedTimeStamps
                    /* If the times are entered by the user, only include the times for the frames enterred by the user. Unless the calculated timing descrepency is small (m_TimestampDiscrepencyFlag = false) */)
                {
                    timePrecisionSec = 0.01;
                    isBadTime = m_TimestampDiscrepencyFlag;
                }

                if (isBadTime &&
                    m_LCFile.Footer.ReductionContext.LightCurveReductionType == LightCurveReductionType.MutualEvent && absoluteTimeError/500 < resolutionInSecs)
                {
                    // Force export the time for mutual events where half the resolution is better than the absolute timing error
                    isBadTime = false;
                }

                if (options.PhotometricFormat == PhotometricFormat.Magnitudes && atmExtCalc != null)
                {
                    output.Append(", Atmospheric Extinction, Altitude (deg), Air Mass");
                }

                output.AppendLine();

                for (int i = 0; i < count; i++)
                {
                    if (options.Spacing > 1 && (i - options.ExportStartingFrame) % options.Spacing != 0)
                        // Skip all frames in the 'spaces'
                        continue;

                    if (i < (options.ExportStartingFrame - m_LightCurveController.Context.MinFrame))
                        // Skip all frames before the first frame configured to begin the export from
                        continue;

                    string isCorrectedForInstrumentalDelay;
                    double midBinFrameNumber =  firstFrameNoInBin < m_LightCurveController.Context.BinningFirstFrame
                            ? ((m_LightCurveController.Context.BinningFirstFrame - m_LightCurveController.Context.MinFrame) / 2.0) - 0.5
                            : firstFrameNoInBin + (m_LightCurveController.Context.Binning / 2.0) - 0.5;

                    DateTime middleBinTime = DateTime.MinValue;

                    if (midBinFrameNumber <= m_Header.MaxFrame && midBinFrameNumber >= m_Header.MinFrame)
                    {
                        int midBinFrameNumberInt = (int)midBinFrameNumber;
                        double midBinFrameNumberFrac = midBinFrameNumber - midBinFrameNumberInt;

                        middleBinTime = m_LCFile.GetTimeForFrame(midBinFrameNumberInt, out isCorrectedForInstrumentalDelay);
                        if (middleBinTime > DateTime.MinValue && midBinFrameNumberFrac > 0.00001 && midBinFrameNumberInt + 1 <= m_Header.MaxFrame)
                        {
                            DateTime middleBinPlusOneTime = m_LCFile.GetTimeForFrame(midBinFrameNumberInt + 1, out isCorrectedForInstrumentalDelay);
                            middleBinTime = middleBinTime.AddTicks((long)((middleBinPlusOneTime.Ticks - middleBinTime.Ticks) * midBinFrameNumberFrac));
                        }
                    }

                    string timeStr;
                    if (isBadTime)
                    {
                        if (m_Header.FirstTimedFrameNo >= firstFrameNoInBin && m_Header.FirstTimedFrameNo <= firstFrameNoInBin + m_LightCurveController.Context.Binning)
                            timeStr = options.FormatTime(m_Header.FirstTimedFrameTime, timePrecisionSec);
                        else if (m_Header.LastTimedFrameNo >= firstFrameNoInBin && m_Header.LastTimedFrameNo <= firstFrameNoInBin + m_LightCurveController.Context.Binning)
                            timeStr = options.FormatTime(m_Header.SecondTimedFrameTime, timePrecisionSec);
                        else
                            timeStr = options.FormatInvalidTime(timePrecisionSec);
                    }
                    else
                    {
                        if (middleBinTime == DateTime.MinValue || middleBinTime == DateTime.MaxValue)
                            timeStr = "";
                        else
                            timeStr = options.FormatTime(middleBinTime, timePrecisionSec);
                    }

                    output.AppendFormat("{0},{1}", i + 1, timeStr);

                    for (int j = 0; j < objCount; j++)
                    {
                        BinnedValue reading = m_AllBinnedReadings[j][i];
                        output.Append(options.FormatPhotometricValue(reading.IsSuccessfulReading, reading.AdjustedValue, 0, false, true));
                    }

                    if (options.PhotometricFormat == PhotometricFormat.Magnitudes && atmExtCalc != null &&
                        middleBinTime != DateTime.MinValue && middleBinTime != DateTime.MaxValue)
                    {
                        double altitudeDeg;
                        double airMass;
                        double extinction = atmExtCalc.CalculateExtinction(middleBinTime, out altitudeDeg, out airMass);
                        output.AppendFormat(",{0},{1},{2}", extinction.ToString(5), altitudeDeg.ToString(3), airMass.ToString(5));
                    }

                    output.AppendLine();

                    if (firstFrameNoInBin < m_LightCurveController.Context.BinningFirstFrame)
                        // If this is the first incomplete bin, then next bin's first frame is the first binning frame
                        firstFrameNoInBin = m_LightCurveController.Context.BinningFirstFrame;
                    else
                        firstFrameNoInBin += m_LightCurveController.Context.Binning;
                }
            }
            else
            {
                CSVExportAddCommonHeader(output, options, false);

                int count = m_LightCurveController.Context.AllReadings[0].Count;

                output.Append(string.Format("FrameNo,Time ({0})", options.FormatTimeLabel()));

                for (int j = 0; j < objCount; j++)
                {
                    output.Append(options.FormatPhotometricValueHeaderForObject(j + 1, options.ForceSignalMinusBackground, false));
                }

                for (int j = 0; j < objCount; j++)
                {
                    if (options.ExportObjectPosition) output.AppendFormat(",X ({0}) ,Y ({0})", j + 1);
                    if (options.ExportPsfParameters) output.AppendFormat(",PSF-I0 ({0}) ,PSF-FWHM ({0})", j + 1);
                }

                bool isBadTime = false;
                double timePrecisionSec = 0;

                if (absoluteTimeError > 5)
                {
                    timePrecisionSec = 0.001;
                    isBadTime = true;
                }
                else if (!m_LCFile.Footer.ReductionContext.HasEmbeddedTimeStamps
                    /* If the times are entered by the user, only include the times for the frames enterred by the user. Unless the calculated timing descrepency is small (m_TimestampDiscrepencyFlag = false) */)
                {
                    timePrecisionSec = 0.001;
                    isBadTime = m_TimestampDiscrepencyFlag;
                }
                else
                    timePrecisionSec = 0.001;

                if (options.PhotometricFormat == PhotometricFormat.Magnitudes && atmExtCalc != null)
                {
                    output.Append(", Atmospheric Extinction, Altitude (deg), Air Mass");
                }
                output.AppendLine();

                for (int i = 0; i < count; i++)
                {
                    if (options.Spacing > 1 && (i - options.ExportStartingFrame) % options.Spacing != 0)
                        // Skip all frames in the 'spaces'
                        continue;

                    if (i < (options.ExportStartingFrame - m_LightCurveController.Context.MinFrame))
                        // Skip all frames before the first frame configured to begin the export from
                        continue;

                    uint frameNo = m_LightCurveController.Context.AllReadings[0][i].CurrFrameNo;
                    string isCorrectedForInstrumentalDelay;
                    DateTime currFrameTime = m_LCFile.GetTimeForFrame(frameNo, out isCorrectedForInstrumentalDelay);

                    if (!string.IsNullOrEmpty(m_LightCurveController.Context.InstrumentalDelayConfigName) && isCorrectedForInstrumentalDelay == null)
                        // Single frames not corrected for instrumental delays, where instrumental delays are known, are considered bad times
                        currFrameTime = DateTime.MaxValue;

                    string timeStr;
                    if (isBadTime)
                    {
                        if (currFrameTime == DateTime.MinValue || currFrameTime == DateTime.MaxValue)
                            timeStr = "";
                        else if (frameNo == m_Header.FirstTimedFrameNo)
                            timeStr = options.FormatTime(m_Header.FirstTimedFrameTime, timePrecisionSec);
                        else if (frameNo == m_Header.LastTimedFrameNo)
                            timeStr = options.FormatTime(m_Header.SecondTimedFrameTime, timePrecisionSec);
                        else
                            timeStr = options.FormatInvalidTime(timePrecisionSec);
                    }
                    else
                    {
                        if (currFrameTime == DateTime.MinValue || currFrameTime == DateTime.MaxValue)
                            timeStr = "";
                        else
                            timeStr = options.FormatTime(currFrameTime, timePrecisionSec);
                    }

                    output.AppendFormat("{0},{1}", frameNo, timeStr);

                    for (int j = 0; j < objCount; j++)
                    {
                        LCMeasurement reading = m_LightCurveController.Context.AllReadings[j][i];
                        output.Append(options.FormatPhotometricValue(reading.IsSuccessfulReading, (int)reading.TotalReading, (int)reading.TotalBackground, options.ForceSignalMinusBackground, false));
                    }

                    for (int j = 0; j < objCount; j++)
                    {
                        LCMeasurement reading = m_LightCurveController.Context.AllReadings[j][i];
                        if (options.ExportObjectPosition) output.AppendFormat(",{0},{1}", reading.X0.ToString("0.0"), reading.Y0.ToString("0.0"));
                        if (options.ExportPsfParameters)
                        {
                            if (reading.PsfFit == null)
                            {
                                int x0Int = (int)Math.Round(reading.X0);
                                int y0Int = (int)Math.Round(reading.Y0);

                                reading.PsfFit = new PSFFit(x0Int, y0Int);
                                reading.PsfFit.FittingMethod = PSFFittingMethod.NonLinearFit;
                                int pixelDataWidth = reading.PixelData.GetLength(0);
                                int pixelDataHeight = reading.PixelData.GetLength(1);
                                reading.PsfFit.Fit(
                                    reading.PixelData,
                                    m_LightCurveController.Context.ReProcessFitAreas[reading.TargetNo],
                                    x0Int - reading.PixelDataX0 + (pixelDataWidth / 2) + 1,
                                    y0Int - reading.PixelDataY0 + (pixelDataHeight / 2) + 1,
                                    false);
                            }

                            output.AppendFormat(",{0},{1}", reading.PsfFit.I0.ToString("0.0"), reading.PsfFit.FWHM.ToString("0.000"));
                        }
                    }

                    if (options.PhotometricFormat == PhotometricFormat.Magnitudes && atmExtCalc != null &&
                        currFrameTime != DateTime.MinValue && currFrameTime != DateTime.MaxValue)
                    {
                        double altitudeDeg;
                        double airMass;
                        double extinction = atmExtCalc.CalculateExtinction(currFrameTime, out altitudeDeg, out airMass);
                        output.AppendFormat(",{0},{1},{2}", extinction.ToString(5), altitudeDeg.ToString(3), airMass.ToString(5));
                    }

                    output.AppendLine();
                }
            }

            try
            {
                File.WriteAllText(fileName, output.ToString());
                return true;
            }
            catch(IOException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
示例#2
0
        private void btnOK_Click(object sender, EventArgs e)
        {
            m_ConfirmedDate = null;

            bool dayConfirmationRequired = (rbJulianDays.Checked || (rbMagnitude.Checked && cbxAtmExtExport.Checked));

            if (dayConfirmationRequired)
            {
                DateTime firstTimestamp = LCFile.GetTimeForFrame(LCFile.Header.MinFrame);

                if (firstTimestamp.Year > 1900 && LCFile.Header.TimingType == MeasurementTimingType.EmbeddedTimeForEachFrame)
                {
                    // No need to confirm the date. This is either an ADV file or an AAV file with time OCR-ed on the flly during the recording or AAV file with NTP timestamp
                }
                else
                {
                    var frm = new frmConfirmDay();
                    frm.SelectedDay = firstTimestamp;
                    frm.StartPosition = FormStartPosition.CenterParent;
                    if (frm.ShowDialog(this) != DialogResult.OK)
                        return;
                    DateTime? selectedDate = frm.SelectedDay;

                    if (selectedDate.HasValue)
                        m_ConfirmedDate = selectedDate.Value;
                }
            }

            if (Binning && (nudExportStartFromFrame.Value != nudExportStartFromFrame.Minimum || cbxSpacingOptions.SelectedIndex > 0))
            {
                MessageBox.Show(this, "When binning is used 'spacing' and a specific starting frame cannot be used as export options.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tbxRA.Focus();
                return;
            }

            if (cbxAtmExtExport.Checked)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(tbxRA.Text)) throw new FormatException();
                    m_RAHours = AstroConvert.ToRightAcsension(tbxRA.Text);
                }
                catch (FormatException)
                {
                    MessageBox.Show(this, "Please enter a valid Right Ascension value (e.g. 23 03 12)", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbxRA.Focus();
                    return;
                }

                try
                {
                    if (string.IsNullOrWhiteSpace(tbxDec.Text)) throw new FormatException();
                    m_DEDeg = AstroConvert.ToDeclination(tbxDec.Text);
                }
                catch (FormatException)
                {
                    MessageBox.Show(this, "Please enter a valid Declination value (e.g. +76 13 18)", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbxDec.Focus();
                    return;
                }

                try
                {
                    if (string.IsNullOrWhiteSpace(tbxLatitude.Text)) throw new FormatException();
                    m_Latitude = AstroConvert.ToDeclination(tbxLatitude.Text);
                }
                catch (FormatException)
                {
                    MessageBox.Show(this, "Please enter a valid Latitude value (e.g. -33 12 12)", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbxLatitude.Focus();
                    return;
                }

                try
                {
                    if (string.IsNullOrWhiteSpace(tbxLongitude.Text)) throw new FormatException();
                    m_Longitude = AstroConvert.ToDeclination(tbxLongitude.Text);
                }
                catch (FormatException)
                {
                    MessageBox.Show(this, "Please enter a valid Longitude value (e.g. -86 09 12)", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbxLongitude.Focus();
                    return;
                }

                try
                {
                    if (string.IsNullOrWhiteSpace(tbxHeightKm.Text)) throw new FormatException();
                    m_HeightKm = double.Parse(tbxHeightKm.Text);
                }
                catch (FormatException)
                {
                    MessageBox.Show(this, "Please enter a valid Height value (e.g. 0.150)", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbxHeightKm.Focus();
                    return;
                }

                var calc = new AtmosphericExtinctionCalculator(m_RAHours, m_DEDeg, m_Longitude, m_Latitude, m_HeightKm);
                DateTime firstTimestamp = LCFile.GetTimeForFrame(LCFile.Header.MinFrame);
                if (m_ConfirmedDate != null)
                    firstTimestamp = m_ConfirmedDate.Value.Date.AddTicks(firstTimestamp.Ticks - firstTimestamp.Date.Ticks);

                double zenithAngle = calc.CalculateZenithAngle(firstTimestamp);
                if (zenithAngle > 90)
                {
                    MessageBox.Show(this, "The object is below the horizon.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                var savedSettings = new CoordsAndLocation()
                {
                    RAHours = m_RAHours,
                    DEDeg = m_DEDeg,
                    LatitudeDeg = m_Latitude,
                    LongitudeDeg = m_Longitude,
                    HeightKM = m_HeightKm
                };
                try
                {
                    Properties.Settings.Default.AtmExtRememberedConfig = savedSettings.AsSerialized();
                    Properties.Settings.Default.Save();
                }
                catch { }

            }

            // TODO: Confirm object is above horizon

            DialogResult = DialogResult.OK;

            Close();
        }
示例#3
0
        internal void PopulateMasterSpectraObservationDetails(MasterSpectra spectra)
        {
            var dict = m_VideoController.GetVideoFileTags();

            float lng = float.NaN;
            float lat = float.NaN;
            float ra = float.NaN;
            float dec = float.NaN;
            DateTime? centralTime = null;

            if (spectra.ObservationInfo == null) spectra.ObservationInfo = new ObservationInfo();
            spectra.ObservationInfo.Reset();

            if (dict.ContainsKey("Longitude"))
            {
                if (float.TryParse(dict["Longitude"], NumberStyles.Float, CultureInfo.InvariantCulture, out lng))
                    spectra.ObservationInfo.AddProperty("Longitude", lng.ToString("0.0000", CultureInfo.InvariantCulture));
            }
            if (dict.ContainsKey("Latitude"))
            {
                if (float.TryParse(dict["Latitude"], NumberStyles.Float, CultureInfo.InvariantCulture, out lat))
                    spectra.ObservationInfo.AddProperty("Latitude", lat.ToString("0.0000", CultureInfo.InvariantCulture));
            }
            if (dict.ContainsKey("RA"))
            {
                if (float.TryParse(dict["RA"], NumberStyles.Float, CultureInfo.InvariantCulture, out ra))
                    spectra.ObservationInfo.AddProperty("RA", ra.ToString("0.0000", CultureInfo.InvariantCulture), "hours");
            }
            if (dict.ContainsKey("DEC"))
            {
                if (float.TryParse(dict["DEC"], NumberStyles.Float, CultureInfo.InvariantCulture, out dec))
                    spectra.ObservationInfo.AddProperty("DEC", dec.ToString("0.0000", CultureInfo.InvariantCulture), "degrees");
            }
            if (spectra.MeasurementInfo.FirstFrameTimeStamp.HasValue && spectra.MeasurementInfo.LastFrameTimeStamp.HasValue)
            {
                centralTime = new DateTime((spectra.MeasurementInfo.FirstFrameTimeStamp.Value.Ticks + spectra.MeasurementInfo.LastFrameTimeStamp.Value.Ticks) / 2);
                double jd = JulianDayHelper.JDUtcAtDate(centralTime.Value);
                spectra.ObservationInfo.AddProperty("JD", jd.ToString("0.00000", CultureInfo.InvariantCulture), "UT");
            }

            if (!float.IsNaN(lng) && !float.IsNaN(lat) && !float.IsNaN(ra) && !float.IsNaN(dec) && centralTime.HasValue)
            {
                var extCalc = new AtmosphericExtinctionCalculator(ra, dec, lng, lat, 0);
                double airMass;
                double altitudeDeg;
                extCalc.CalculateExtinction(centralTime.Value, out altitudeDeg, out airMass);

                spectra.ObservationInfo.AddProperty("X", airMass.ToString("0.000", CultureInfo.InvariantCulture), "air mass");
            }

            if (!float.IsNaN(spectra.ZeroOrderFWHM)) spectra.ObservationInfo.AddProperty("FWHM", spectra.ZeroOrderFWHM.ToString("0.00"), "zero order image FWHM");

            if (!float.IsNaN(spectra.MeasurementInfo.Gain)) spectra.ObservationInfo.AddProperty("Gain", spectra.MeasurementInfo.Gain.ToString("0.0", CultureInfo.InvariantCulture), "dB");
            if (!float.IsNaN(spectra.MeasurementInfo.ExposureSeconds)) spectra.ObservationInfo.AddProperty("Exposure", spectra.MeasurementInfo.ExposureSeconds.ToString("0.000", CultureInfo.InvariantCulture), "sec");

            if (dict.ContainsKey("ObjectName")) spectra.ObservationInfo.AddProperty("Target", dict["ObjectName"]);
            if (dict.ContainsKey("Instrument")) spectra.ObservationInfo.AddProperty("Camera", dict["Instrument"]);
            if (dict.ContainsKey("Telescope")) spectra.ObservationInfo.AddProperty("Telescope", dict["Telescope"]);
            if (dict.ContainsKey("Recorder")) spectra.ObservationInfo.AddProperty("Recorder", dict["Recorder"]);
            if (dict.ContainsKey("Observer")) spectra.ObservationInfo.AddProperty("Observer", dict["Observer"]);

            if (spectra.IsCalibrated())
            {
                if (spectra.Calibration.PolynomialOrder == 1)
                    spectra.ObservationInfo.AddProperty("WavelengthCalibration", string.Format("1-st order[{0},{1}]", spectra.Calibration.A, spectra.Calibration.B));
                else if (spectra.Calibration.PolynomialOrder == 2)
                    spectra.ObservationInfo.AddProperty("WavelengthCalibration", string.Format("2-nd order[{0},{1},{2}]", spectra.Calibration.A, spectra.Calibration.B, spectra.Calibration.C));
                else if (spectra.Calibration.PolynomialOrder == 3)
                    spectra.ObservationInfo.AddProperty("WavelengthCalibration", string.Format("3-rd order[{0},{1},{2},{3}]", spectra.Calibration.A, spectra.Calibration.B, spectra.Calibration.C, spectra.Calibration.D));
                else if (spectra.Calibration.PolynomialOrder == 4)
                    spectra.ObservationInfo.AddProperty("WavelengthCalibration", string.Format("4-th order[{0},{1},{2},{3},{4}]", spectra.Calibration.A, spectra.Calibration.B, spectra.Calibration.C, spectra.Calibration.D, spectra.Calibration.E));

                spectra.ObservationInfo.AddProperty("Dispersion", spectra.Calibration.Dispersion.ToString("0.00", CultureInfo.InvariantCulture), "A/pix");
            }
        }