######################################################################## # # Copyright (c) Vaisala Group 2012. All rights reserved. # # The terms "Vaisala" and "Vaisala Group" are defined as # "Vaisala Oyj and all its subsidiaries". # # Module name : WriteEdt.py # Context : Applicable with Vaisala MW41 Sounding System # # Original release : 2012 # ######################################################################## ################################################################################# # # Import required Python modules. # ################################################################################# import clr import System import math import sys from System.IO import Directory, Path from System import Array from System import Type from math import * ################################################################################# # # Referencies for required interfaces to the sounding system. # ################################################################################# clr.AddReference('IScripting') clr.AddReference('SystemEvent') clr.AddReference('DataTypes') from Vaisala.Soundings.Framework import IExecutableScript from Vaisala.Soundings.Framework import ISounding from Vaisala.Soundings.Framework.DataTypes import SystemEvent from Vaisala.Soundings.Framework.DataTypes import SignificantLevel from Vaisala.Soundings.Framework.DataTypes import SurfaceObservations from Vaisala.Soundings.Framework.DataTypes import StdPressureLevel from Vaisala.Soundings.Framework.DataTypes.PTU import SynchronizedSoundingData ################################################################################# # Defines used in the script. ################################################################################# __Version__ = "1.1." + filter(str.isdigit, "$Revision: 38207 $") __MissingData__ = -32768 __MissingValue__ = "////////" __KelvinToC__ = 273.15 __ColumnSeparator__ = "\t" __Columns__ = [" Time", " Height", "Pressure", " Temp", "Humidity", " WDir", " WSpeed", " Lat", " Lon"] ################################################################################# # # WriteEdt class for implementing the script. Note that file should be named same as # executed class. # # Class should implement at least method defined by IExecutableScript interface. # ################################################################################# class WriteEdt(IExecutableScript): """WriteEdt example script In this script we receive notifications from sounding system and write EDT to the file when sounding is ongoing. After sounding is terminated also STD and significant levels are written to same file. Command line options: -f File where to write EDT. -All Create EDT file from all soundings in the database. """ def __init__(self, args): """Initialize script Arguments: args -- Array of command line arguments. """ self.LaunchTime = 0 # Shupe modification 20160623: Commented out default name, added 2 lines for new default name # self.WriteFile = "C:\\temp\\EDT.txt" tmp = SoundingInterface.GetSoundingInformation() self.WriteFile = "C:\\SoundingArchive\\" + tmp.StationName + "_" + tmp.SoundingStartTime.ToString("yyyyMMdd_HHmmss") + "_edt.txt" createAll = False # Read command line options. i = 0 while (i < len(args)) : if (args[i] == "-f") : i = i + 1 if (i < len(args)) : self.WriteFile = args[i] elif (args[i] == "-All") : createAll = True i = i + 1 dir = Path.GetDirectoryName(self.WriteFile) if not Directory.Exists(dir) : Directory.CreateDirectory(dir) if (createAll) : soundings = SoundingInterface.GetSoundings() print '' print 'Total ', soundings.Count, ' soundings in the database.' print '' for s in soundings: print "Sounding started at %s, termination reason: %s" % (s.SoundingStartTime, s.ReasonForTermination) print "Duration %d s, ascent rate %.1f m/s, min press %.1f hPa, max alt %d m" % (s.Duration, s.AscentRate, s.MinPressure, s.MaxAltitude) # Create report from sounding. SoundingInterface.ActiveSoundingId = s.Id # Shupe modification 20160623: commented out default name, added new default name # self.WriteFile = dir + "\\EDT_" + s.SoundingStartTime.ToString("yyyyMMdd_HHmmss") + ".txt" self.WriteFile = dir + "\\" + s.StationName + "_" + s.SoundingStartTime.ToString("yyyyMMdd_HHmmss") + "_edt.txt" self.CreateReport() # Done -> exit SoundingInterface.StopScript() sys.exit(0) else : # Order notifications of SystemEvent and SynchronizedSoundingData from Sounding system types = Array[Type]([clr.GetClrType(SystemEvent), clr.GetClrType(SynchronizedSoundingData)]) SoundingInterface.OrderNotifications(types) def get_Name(self): return "Write EDT example" def get_Description(self): return "Write EDT to the file when sounding is ongoing." def get_Author(self): return "@Vaisala" def get_Version(self): return __Version__ def HandleData(self, data): """ Handle sounding data. Arguments: data -- Sounding data """ # Get method name to be called from data type. method_name = 'handle_' + str(data.GetType().Name) method = getattr(self, method_name) method(data) def handle_SystemEvent(self, event): """ Handle sounding system events. Arguments: event -- Sounding system event """ if event.EventName == "SoundingCreated": # Update active sounding id when new sounding is created. SoundingInterface.ActiveSoundingId = event.Data elif event.EventName == "BalloonReleased": self.SoundingStart() elif event.EventName == "SoundingCompleted": self.SoundingEnd() # Done -> exit SoundingInterface.StopScript() sys.exit(0) def SoundingStart(self) : """Clear EDT file and write new header to it.""" # SoundingInterface object is provided by sounding system to the script. # Object provides ISounding interface methods. soundingInfo = SoundingInterface.GetSoundingInformation() self.LaunchTime = soundingInfo.LaunchTime # Shupe modification 20160627. Add the output filename here, which overwrites all previous filenames self.WriteFile = "C:\\SoundingArchive\\" + soundingInfo.StationName + "_" + soundingInfo.SoundingStartTime.ToString("yyyyMMdd_HHmmss") + "_edt.txt" edtFile = open(self.WriteFile, "w") edtFile.write("Station: " + soundingInfo.StationName + "\n") edtFile.write("Latitude: " + "%6.4f" % (soundingInfo.Latitude) + "\n") edtFile.write("Longitude: " + "%6.4f" % (soundingInfo.Longitude) + "\n") edtFile.write("Altitude: " + "%.1f" % (soundingInfo.Altitude) + "\n") edtFile.write("SW version: " + soundingInfo.SoftwareVersion + "\n\n") edtFile.write("Start time: " + soundingInfo.SoundingStartTime.ToString() + "\n\n") header = __ColumnSeparator__.join(__Columns__) edtFile.write(header + "\n") edtFile.close() # Printing to console. Note that this is shown only when manually starting the script # with ScriptExecutor.exe print "Writing EDT to ", self.WriteFile def SoundingEnd(self) : """Write sounding status to file.""" soundingInfo = SoundingInterface.GetSoundingInformation() edtFile = open(self.WriteFile, "a") edtFile.write("\n\nReason for termination: " + soundingInfo.ReasonForTermination.ToString() + "\n") edtFile.write("Ascent rate: " + "%.1f" % (soundingInfo.AscentRate) + "\n") edtFile.write("Operator: " + soundingInfo.OperatorId + "\n") if (soundingInfo.Comments is not None) : edtFile.write("Comments: " + soundingInfo.OperatorInfo.Comments + "\n") edtFile.close() self.WriteStandardLevels() self.WriteSignificantLevels() def handle_SynchronizedSoundingData(self, edt): """ Write EDT to file when it is received as event. Arguments: edt -- EDT data """ toFile = open(self.WriteFile, "a") line = self.FormatLine(edt.RadioRxTime, self.LaunchTime, edt.GeopotentialHeight, edt.Pressure, edt.Temperature, edt.Humidity, edt.WindDir, edt.WindSpeed, edt.Latitude, edt.Longitude) toFile.write(line + "\n") toFile.close() def WriteStandardLevels(self) : """Write standard levels to file.""" toFile = open(self.WriteFile, "a") toFile.write("\nStandard levels:\n") header = __ColumnSeparator__.join(__Columns__) toFile.write(header + "\n") for level in SoundingInterface.GetStdPressureLevel() : line = self.FormatLine(level.RadioRxTime, self.LaunchTime, level.GeopotentialHeight, level.Pressure, level.Temperature, level.Humidity, level.WindDir, level.WindSpeed, level.Latitude, level.Longitude) toFile.write(line + "\n") toFile.close() def WriteSignificantLevels(self) : """Write significant levels to file.""" toFile = open(self.WriteFile, "a") toFile.write("\nSignificant levels:\n") columns = __Columns__ columns.append("SIGP") header = __ColumnSeparator__.join(columns) toFile.write(header + "\n") for level in SoundingInterface.GetSignificantLevel() : line = self.FormatLine(level.RadioRxTime, self.LaunchTime, level.GeopotentialHeight, level.Pressure, level.Temperature, level.Humidity, level.WindDir, level.WindSpeed, level.Latitude, level.Longitude) toFile.write(line + __ColumnSeparator__) flags = [] if (level.IsTemperature): flags.append('T') else: flags.append(' ') if (level.IsHumidity): flags.append('U') else: flags.append(' ') if (level.IsWindDir): flags.append('d') else: flags.append(' ') if (level.IsWindSpeed): flags.append('f') else: flags.append(' ') if (level.IsWindVector): flags.append('v') else: flags.append(' ') if (level.IsTropopause): flags.append('Tr') else: flags.append(' ') if (level.IsWindMax): flags.append('Mw') else: flags.append(' ') toFile.write("".join(flags) + "\n") toFile.close() def FormatLine(self, rxTime, launchTime, height, pressure, temperature, humidity, dir, speed, latitude, longitude) : """Returns one level data as string.""" columns = [] if (rxTime == __MissingData__) : columns.append(__MissingValue__) else : time = round(rxTime, 2) - round(launchTime, 2) columns.append("%8.1f" % time) if (height == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.f" % (height)) if (pressure == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.1f" % (pressure)) if (temperature == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.1f" % (temperature - __KelvinToC__)) if (humidity == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.1f" % (humidity)) if (dir == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.1f" % (dir)) if (speed == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.1f" % (speed)) if (latitude == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.4f" % (latitude)) if (longitude == __MissingData__) : columns.append(__MissingValue__) else : columns.append("%8.4f" % (longitude)) return __ColumnSeparator__.join(columns) def CreateReport(self): """ Create EDT report from current sounding. """ self.SoundingStart() for edt in SoundingInterface.GetSynchronizedSoundingData() : self.handle_SynchronizedSoundingData(edt) self.SoundingEnd()