diff --git a/source/Classes/TimeSeriesFile.vb b/source/Classes/TimeSeriesFile.vb index 2fc1fc81..482ec4fe 100644 --- a/source/Classes/TimeSeriesFile.vb +++ b/source/Classes/TimeSeriesFile.vb @@ -32,6 +32,8 @@ Public MustInherit Class TimeSeriesFile CSV DFS0 GISMO_WEL + HYBNAT_BCS + HYBNAT_WEL HYDRO_AS_DAT HYSTEM_WEL JAMS @@ -63,6 +65,7 @@ Public MustInherit Class TimeSeriesFile ''' Public MustInherit Class FileExtensions Public Shared ReadOnly ASC As String = ".ASC" + Public Shared ReadOnly BCS As String = ".BCS" 'BGS HYBNAT BCS format Public Shared ReadOnly BIN As String = ".BIN" 'SYDRO binary format Public Shared ReadOnly CSV As String = ".CSV" Public Shared ReadOnly DAT As String = ".DAT" @@ -73,7 +76,7 @@ Public MustInherit Class TimeSeriesFile Public Shared ReadOnly REG As String = ".REG" Public Shared ReadOnly SMB As String = ".SMB" Public Shared ReadOnly TEN As String = ".TEN" - Public Shared ReadOnly TXT As String = ".TXT" 'SWMM routing interface file, SWMM LID report file or generic text file + Public Shared ReadOnly TXT As String = ".TXT" 'SWMM routing interface file, SWMM LID report file or generic text file Public Shared ReadOnly UVF As String = ".UVF" Public Shared ReadOnly WBL As String = ".WBL" 'SYDRO binary WEL format Public Shared ReadOnly WEL As String = ".WEL" @@ -92,6 +95,7 @@ Public MustInherit Class TimeSeriesFile "Text files (*.txt)|*.txt|" & "CSV files (*.csv)|*.csv|" & "DHI MIKE DFS0 files (*.dfs0)|*.dfs0|" & + "HYBNAT files (*.bcs, *.wel)|*.bcs;*.wel|" & "HYDRO_AS-2D result files (*.dat)|*.dat|" & "Hystem-Extran files (*.dat, *.reg)|*.dat;*.reg|" & "JAMS timeseries result files (*.dat)|*.dat|" & @@ -154,7 +158,7 @@ Public MustInherit Class TimeSeriesFile End Property ''' - ''' Stores the TimeSeries read from the file. + ''' Stores the TimeSeries read from the file. ''' The key corresponds to the column index stored as in . ''' Public TimeSeries As Dictionary(Of Integer, TimeSeries) @@ -347,7 +351,7 @@ Public MustInherit Class TimeSeriesFile ''' ''' Index of the desired timeseries within the file ''' The timeseries - ''' If the timeseries has not been imported yet, an import is initiated. + ''' If the timeseries has not been imported yet, an import is initiated. ''' Throws an exception if the timeseries cannot be found in the file. Public ReadOnly Property getTimeSeries(Optional index As Integer = 0) As TimeSeries Get @@ -369,7 +373,7 @@ Public MustInherit Class TimeSeriesFile ''' ''' Title of the desired timeseries. ''' The timeseries - ''' If the timeseries has not been imported yet, an import is initiated. + ''' If the timeseries has not been imported yet, an import is initiated. ''' Throws an exception if the timeseries cannot be found in the file. Public ReadOnly Property getTimeSeries(title As String) As TimeSeries Get @@ -530,6 +534,10 @@ Public MustInherit Class TimeSeriesFile Return FileExtensions.DFS0 Case FileTypes.GISMO_WEL Return FileExtensions.ASC + Case FileTypes.HYBNAT_BCS + Return FileExtensions.BCS + Case FileTypes.HYBNAT_WEL + Return FileExtensions.WEL Case FileTypes.HYDRO_AS_DAT Return FileExtensions.DAT Case FileTypes.HYSTEM_WEL @@ -635,6 +643,11 @@ Public MustInherit Class TimeSeriesFile fileType = FileTypes.ASC End If + Case FileExtensions.BCS + 'HYBNAT BCS file + Log.AddLogEntry(levels.info, $"Assuming HYBNAT BCS format for file {fileName}.") + fileType = FileTypes.HYBNAT_BCS + Case FileExtensions.BIN 'SYDRO binary file Log.AddLogEntry(levels.info, $"Assuming SYDRO binary format for file {fileName}.") @@ -754,6 +767,10 @@ Public MustInherit Class TimeSeriesFile 'SYDRO binary WEL file Log.AddLogEntry(levels.info, $"Detected SYDRO binary WEL format for file {fileName}.") fileType = FileTypes.WBL + ElseIf Fileformats.HYBNAT_WEL.verifyFormat(file) Then + 'HYBNAT WEL file + Log.AddLogEntry(levels.info, $"Detected HYBNAT WEL format for file {fileName}.") + fileType = FileTypes.HYBNAT_WEL End If Case FileExtensions.WVP @@ -816,6 +833,10 @@ Public MustInherit Class TimeSeriesFile FileInstance = New Fileformats.DFS0(file) Case FileTypes.GISMO_WEL FileInstance = New Fileformats.GISMO_WEL(file) + Case FileTypes.HYBNAT_BCS + FileInstance = New Fileformats.HYBNAT_BCS(file) + Case FileTypes.HYBNAT_WEL + FileInstance = New Fileformats.HYBNAT_WEL(file) Case FileTypes.HYSTEM_REG FileInstance = New Fileformats.HystemExtran_REG(file) Case FileTypes.HYSTEM_WEL diff --git a/source/FileFormats/HYBNAT_BCS.vb b/source/FileFormats/HYBNAT_BCS.vb new file mode 100644 index 00000000..a5c56a93 --- /dev/null +++ b/source/FileFormats/HYBNAT_BCS.vb @@ -0,0 +1,186 @@ +'BlueM.Wave +'Copyright (C) BlueM Dev Group +' +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU Lesser General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU Lesser General Public License for more details. +' +'You should have received a copy of the GNU Lesser General Public License +'along with this program. If not, see . +' +Imports System.IO + +Namespace Fileformats + + ''' + ''' Class for HYBNAT BCS files + ''' + Public Class HYBNAT_BCS + Inherits TimeSeriesFile + + ''' + ''' The unit of the time series + ''' + ''' Is fixed for each type of file + Private _unit As String + + ''' + ''' Referencedate for the beginning of the simulation + ''' + ''' default: 01.01.2000 00:00:00 + Public refDate As DateTime + + ''' + ''' Set if the import dialog should be used + ''' + ''' + ''' True + ''' + Public Overrides ReadOnly Property UseImportDialog() As Boolean + Get + Return True + End Get + End Property + + ''' + ''' Instanciates a new HYBNAT BCS file + ''' + ''' Path to file + ''' + Public Sub New(file As String) + + Call MyBase.New(file) + + 'Default settings + iLineHeadings = 1 + iLineData = 2 + UseUnits = False + _unit = "m³/s" + IsColumnSeparated = True + Separator = Constants.semicolon + DateTimeColumnIndex = 0 + refDate = New DateTime(2000, 1, 1, 0, 0, 0) + + Call readSeriesInfo() + + End Sub + + ''' + ''' Checks if the file is a HYBNAT BCS file + ''' + ''' Path to file + ''' Boolean + ''' Check is based on file extension and line 1 (must start with "time;") + Public Shared Function verifyFormat(file As String) As Boolean + 'Check if file name ends with ".bcs" + Dim filename As String = Path.GetFileName(file).ToLower() + If Not filename.EndsWith(".bcs") Then Return False + + 'Open file + Dim stream As New FileStream(file, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, System.Text.Encoding.Default) + Dim syncReader = TextReader.Synchronized(reader) + + 'Check if first line starts with "time;" + If Not syncReader.ReadLine.ToString.Trim().StartsWith("time;") Then Return False + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + + 'File is valid + Return True + End Function + + ''' + ''' Read number of columns and their names + ''' + ''' + Public Overrides Sub readSeriesInfo() + 'Clear series infos + TimeSeriesInfos.Clear() + + 'Open file + Dim stream As New FileStream(File, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, System.Text.Encoding.Default) + Dim syncReader = TextReader.Synchronized(reader) + + 'Read first line for column names + Dim columnNames() As String = syncReader.ReadLine.Split(Separator.ToChar) + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + + 'Store series info + For i = 0 To columnNames.Count - 1 + 'Overjump time column and empty columns + If i = DateTimeColumnIndex Then Continue For + If columnNames(i).Trim() = "" Then Continue For + + 'Add series info + Dim seriesInfo = New TimeSeriesInfo With { + .Name = columnNames(i).Trim(), + .Unit = _unit, + .Index = i + 1 + } + TimeSeriesInfos.Add(seriesInfo) + Next + End Sub + + ''' + ''' Reads the time series from the file + ''' + ''' + Public Overrides Sub readFile() + 'Show dialog for setting the reference date + Dim dlg As New HYDRO_AS_2D_Diag() + dlg.ShowDialog() + refDate = dlg.DateTimePicker_refDate.Value + + 'Instantiate time series + For Each seriesInfo As TimeSeriesInfo In SelectedSeries + Dim timeSeries = New TimeSeries(seriesInfo.Name) With { + .Unit = seriesInfo.Unit, + .DataSource = New TimeSeriesDataSource(File, seriesInfo.Name), + .Interpretation = BlueM.Wave.TimeSeries.InterpretationEnum.Instantaneous + } + MyBase.TimeSeries.Add(seriesInfo.Index, timeSeries) + Next + + 'Open file and overjump line with headings + Dim stream As New FileStream(Me.File, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, Me.Encoding) + Dim syncReader = TextReader.Synchronized(reader) + syncReader.ReadLine() + + 'Read data until end of file + Do + 'Get values and datetime (calculate from reference date and seconds) + Dim values = syncReader.ReadLine.Split(Separator.ToChar) + Dim datetime = refDate + New TimeSpan(0, 0, Helpers.StringToDouble(values(DateTimeColumnIndex))) + + 'Add nodes to time series + For Each seriesInfo As TimeSeriesInfo In SelectedSeries + TimeSeries(seriesInfo.Index).AddNode(datetime, Helpers.StringToDouble(values(seriesInfo.Index - 1))) + Next + Loop Until syncReader.Peek() = -1 + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + End Sub + + End Class + +End Namespace \ No newline at end of file diff --git a/source/FileFormats/HYBNAT_WEL.vb b/source/FileFormats/HYBNAT_WEL.vb new file mode 100644 index 00000000..a8ded348 --- /dev/null +++ b/source/FileFormats/HYBNAT_WEL.vb @@ -0,0 +1,260 @@ +'BlueM.Wave +'Copyright (C) BlueM Dev Group +' +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU Lesser General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU Lesser General Public License for more details. +' +'You should have received a copy of the GNU Lesser General Public License +'along with this program. If not, see . +' +Imports System.IO + +Namespace Fileformats + + ''' + ''' Class for HYBNAT WEL files + ''' + Public Class HYBNAT_WEL + Inherits TimeSeriesFile + + ''' + ''' The name of the element in the WEL-file + ''' + ''' + Private _elmentName As String + + ''' + ''' The element type in the WEL-file + ''' + ''' + ''' First character of the element name + ''' ( + ''' N: natural catchment + ''' K: urban catchment + ''' E: point discharge + ''' P: observation station + ''' T: transport element + ''' V: branching element + ''' B: reservoir + ''' ) + ''' + Private _elementType As Char + + ''' + ''' Referencedate for the beginning of the simulation + ''' + ''' default: 01.01.2000 00:00:00 + Public refDate As DateTime + + ''' + ''' Set if the import dialog should be used + ''' + ''' + ''' True + ''' + Public Overrides ReadOnly Property UseImportDialog() As Boolean + Get + Return True + End Get + End Property + + ''' + ''' Instanciates a new HYBNAT WEL file + ''' + ''' Path to file + ''' + Public Sub New(file As String) + + Call MyBase.New(file) + + 'Default settings + UseUnits = True + IsColumnSeparated = True + DateTimeColumnIndex = 0 + refDate = New DateTime(2000, 1, 1, 0, 0, 0) + + Call readSeriesInfo() + + End Sub + + ''' + ''' Checks if the file is a HYBNAT WEL files + ''' + ''' Path to file + ''' Boolean + ''' Check is based on line 4 (must start with "Ganglinien:") + Public Shared Function verifyFormat(file As String) As Boolean + 'Check if file name ends with .wel + Dim filename As String = Path.GetFileName(file).ToLower() + If Not filename.EndsWith(".wel") Then Return False + + 'Open file + Dim stream As New FileStream(file, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, System.Text.Encoding.Default) + Dim syncReader = TextReader.Synchronized(reader) + + 'Overjump first 3 lines + For i = 1 To 3 + syncReader.ReadLine() + Next + + 'Check if line 4 starts with "Ganglinien:" + If Not syncReader.ReadLine.ToString.Trim().StartsWith("Ganglinien:") Then Return False + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + + 'Valid file + Return True + End Function + + ''' + ''' Read number of columns and their names + ''' + ''' + Public Overrides Sub readSeriesInfo() + 'Clear series infos + TimeSeriesInfos.Clear() + + 'Open file + Dim stream As New FileStream(File, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, System.Text.Encoding.Default) + Dim syncReader = TextReader.Synchronized(reader) + + 'Overjump first 3 lines + For i = 1 To 3 + syncReader.ReadLine() + Next + + 'Determine element name and type + _elmentName = syncReader.ReadLine.ToString.Split(":")(1).Split("/")(0).Trim() + _elementType = _elmentName.Substring(0, 1) + + 'Jump back to beginning of file + stream.Seek(0, SeekOrigin.Begin) + reader = New StreamReader(stream, Me.Encoding) + syncReader = TextReader.Synchronized(reader) + + 'Set line numbers for headings, units and data according to element type + Select Case _elementType + Case "N", "K", "T", "B" + iLineHeadings = 17 + iLineUnits = 18 + iLineData = 20 + Case "E" + iLineHeadings = 8 + iLineUnits = 9 + iLineData = 11 + Case "P" + iLineHeadings = 11 + iLineUnits = 12 + iLineData = 14 + Case "V" + iLineHeadings = 14 + iLineUnits = 15 + iLineData = 17 + Case Else + Throw New Exception($"Unknown HYBNAT element type '{_elementType}'!") + End Select + + 'Overjump lines until headings + For i = 1 To iLineHeadings - 1 + syncReader.ReadLine() + Next + + 'Read headings and units + Dim columnNames() As String = syncReader.ReadLine.Split(New Char() {" "}, System.StringSplitOptions.RemoveEmptyEntries) + Dim columnUnits() As String = syncReader.ReadLine.Split(New Char() {" "}, System.StringSplitOptions.RemoveEmptyEntries) + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + + 'Store series info + For i = 0 To columnNames.Count - 1 + 'Overjump time column + If i = DateTimeColumnIndex Then Continue For + + 'Rename units + If columnUnits(i) = "cbm/s" Then columnUnits(i) = "m³/s" + + 'Add series info + Dim seriesInfo = New TimeSeriesInfo With { + .Name = $"{_elmentName} ({columnNames(i)})", + .Unit = columnUnits(i), + .Index = i + 1 + } + TimeSeriesInfos.Add(seriesInfo) + Next + End Sub + + ''' + ''' Reads the time series from the file + ''' + ''' + Public Overrides Sub readFile() + 'Show dialog for setting the reference date + Dim dlg As New HYDRO_AS_2D_Diag() + dlg.ShowDialog() + refDate = dlg.DateTimePicker_refDate.Value + + 'Instantiate time series + For Each sInfo As TimeSeriesInfo In SelectedSeries + Dim timeSeries = New TimeSeries(sInfo.Name) With { + .Unit = sInfo.Unit, + .DataSource = New TimeSeriesDataSource(File, sInfo.Name) + } + + 'Set interpretation mode + If timeSeries.Unit = "mm" Then + timeSeries.Interpretation = BlueM.Wave.TimeSeries.InterpretationEnum.BlockRight + Else + timeSeries.Interpretation = BlueM.Wave.TimeSeries.InterpretationEnum.Instantaneous + End If + + MyBase.TimeSeries.Add(sInfo.Index, timeSeries) + Next + + 'Open file + Dim stream As New FileStream(Me.File, FileMode.Open, IO.FileAccess.Read) + Dim reader As New StreamReader(stream, Me.Encoding) + Dim syncReader = TextReader.Synchronized(reader) + + 'Overjump lines with headings and units + For i = 1 To iLineData - 1 + syncReader.ReadLine() + Next + + 'Read data + Do + 'Get values and datetime (calculate from reference date and hours, round to full minutes) + Dim values() As String = syncReader.ReadLine.Split(New Char() {" "}, System.StringSplitOptions.RemoveEmptyEntries) + If values(0).StartsWith("-") Then Exit Do + Dim datetime = refDate + New TimeSpan(0, Helpers.StringToDouble(values(0)) * 60, 0) + + 'Add nodes to time series + For Each seriesInfo As TimeSeriesInfo In SelectedSeries + TimeSeries(seriesInfo.Index).AddNode(datetime, Helpers.StringToDouble(values(seriesInfo.Index - 1))) + Next + Loop Until syncReader.Peek() = -1 + + 'Close file + syncReader.Close() + reader.Close() + stream.Close() + End Sub + + End Class + +End Namespace \ No newline at end of file diff --git a/source/Wave.vbproj b/source/Wave.vbproj index 0f283d09..47d3e48c 100644 --- a/source/Wave.vbproj +++ b/source/Wave.vbproj @@ -215,6 +215,8 @@ Form + +