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