tscollection.h 8.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*! \file tscollection.h
 * \brief provide a container for a collection of time series with header data (prototypes)
 * 
 * ----------------------------------------------------------------------------
 * 
 * \author Thomas Forbriger
 * \date 29/12/2018
 * 
 * provide a container for a collection of time series with header data
 * (prototypes)
 * 
 * Copyright (c) 2018 by Thomas Forbriger (BFO Schiltach) 
 * 
 *
 * ----
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * ----
 *
 * REVISIONS and CHANGES 
 *  - 29/12/2018   V1.0   Thomas Forbriger
 * 
 * ============================================================================
 */

// include guard
#ifndef TS_TSCOLLECTION_H_VERSION

#define TS_TSCOLLECTION_H_VERSION \
  "TS_TSCOLLECTION_H   V1.0"

42
#include<vector>
43
#include<tsxx/error.h>
44
45
46
47
48
#include<tsxx/wid2timeseries.h>

namespace ts {

  /*! \brief A class template for a list of time series with SFF header.
49
50
51
   *
   * A TimeSeriesCollection is a vector of ts::TimeSeries with some additional
   * member functions.
52
53
54
55
56
   *
   * \param T value type of series container
   */
  template<typename T>
    class TimeSeriesCollection: 
57
      public std::vector<TimeSeries<aff::Series<T>, ::sff::WID2> >
58
59
60
  {
    public:
      /*! \name Type definitions.
61
62
       *
       * Provided to define proper base types of class template
63
64
65
66
67
68
69
       */
      //!@{
      typedef T Tvalue;
      typedef aff::Series<Tvalue> Tseries;
      typedef ::sff::WID2 Theader;
      typedef ts::TimeSeries<Tseries, Theader> Ttimeseries;
      typedef ts::TimeSeries<typename Tseries::Tcoc, Theader> Tconsttimeseries;
70
      typedef std::vector<Ttimeseries> Tbase;
71
      //!@}
72
      
73
      //! Check consistency
74
      bool are_consistent(const ::sff::WID2compare comparer) const;
75
      //! Check whether all time series have a common time window
76
      bool overlap() const;
77
78
79
80
81
82
      //! Synchronize header with series
      void synchronize_nsamples();
      //!  Trim to same start time
      void trim_to_date();
      //! Trim to same number of samples
      void trim_to_nsamples();
83
84
85

  }; // class TimeSeriesCollection

86
87
  /* ---------------------------------------------------------------------- */

88
89
90
91
92
93
94
95
96
97
  /*! \brief Check consistency
   *
   * Check the consistency of the time series in the collections based on
   * header data. For example this can be used to check whether all time
   * series have the same number of samples.
   *
   * \param comparer defines the header fields to be compared
   * \return true, if comparer returns true for comparison of all pairs
   *         of time series headers in the collection
   */
98
99
100
101
102
103
  template<typename T>
    bool TimeSeriesCollection<T>::are_consistent(const ::sff::WID2compare comparer) const
    {
      bool retval=true;
      if (this->size() > 1)
      {
104
        typename Tbase::const_iterator i_series=this->begin();
105
106
107
108
        Theader refheader=i_series->header;
        ++i_series;
        while ((i_series != this->end()) && retval)
        {
109
110
          retval=comparer(refheader, i_series->header);
          ++i_series;
111
112
113
114
115
        }
      }
      return(retval);
    } // bool TimeSeriesCollection<T>::are_consistent(const ::sff::WID2compare comparer) const

116
117
  /* ---------------------------------------------------------------------- */

118
119
120
121
122
123
124
  /*! \brief Check whether all time series have a common time window
   *
   * Check whether all time series overlap in time. This is a necessary
   * prerequisite for trimming all time series to a common time window.
   *
   * \return true, if time series overlap
   */
125
126
127
128
129
130
131
132
133
  template<typename T>
    bool TimeSeriesCollection<T>::overlap() const
    {
      bool retval=true;
      if (this->size() > 1)
      {
        typename Tbase::const_iterator i_series=this->begin();
        Theader header=i_series->header;
        libtime::TAbsoluteTime begin=header.date;
134
        libtime::TAbsoluteTime end=::sff::wid2lastsample(header);
135
136
137
138
139
        ++i_series;
        while ((i_series != this->end()) && retval)
        {
          header=i_series->header;
          libtime::TAbsoluteTime thisbegin=header.date;
140
          libtime::TAbsoluteTime thisend=::sff::wid2lastsample(header);
141
142
143
144
145
146
147
148
149
          begin = thisbegin > begin ? thisbegin : begin;
          end = thisend < end ? thisend : end;
          ++i_series;
        }
        retval=(end >= begin);
      }
      return(retval);
    } // bool TimeSeriesCollection<T>::overlap() const

150
151
152
153
154
155
156
157
158
159
  /* ---------------------------------------------------------------------- */

  /*! \brief Synchronize header with series
   *
   * Set actual number of samples and nsamples in header to the smaller of
   * both.
   */
  template<typename T>
    void TimeSeriesCollection<T>::synchronize_nsamples() 
    {
160
      typename Tbase::iterator i_series=this->begin();
161
162
163
      while (i_series != this->end())
      {
        const unsigned int& header_nsamples=i_series->header.nsamples;
164
        unsigned int series_nsamples=i_series->size();
165
166
167
168
        unsigned int nsamples=
          series_nsamples < header_nsamples 
          ? series_nsamples : header_nsamples;
        i_series->header.nsamples=nsamples;
169
        i_series->setlastindex(i_series->f()+nsamples-1);
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
        ++i_series;
      }
    } // void TimeSeriesCollection<T>::synchronize_nsamples() 

  /* ---------------------------------------------------------------------- */

  /*! \brief Trim to same start time
   *
   * Set all start dates to the latest found in the collection.
   */
  template<typename T>
    void TimeSeriesCollection<T>::trim_to_date() 
    {
      if (this->size() > 1)
      {
        // find lastest start date
186
        typename Tbase::iterator i_series=this->begin();
187
188
189
190
191
192
193
194
195
196
        Theader header=i_series->header;
        libtime::TAbsoluteTime begin=header.date;
        ++i_series;
        while (i_series != this->end())
        {
          header=i_series->header;
          libtime::TAbsoluteTime thisbegin=header.date;
          begin = thisbegin > begin ? thisbegin : begin;
          ++i_series;
        }
197
198

        // adjust series and header
199
200
201
202
203
204
205
206
207
208
209
        i_series=this->begin();
        while (i_series != this->end())
        {
          header=i_series->header;
          long int index_offset=wid2isample(header, begin);
          TSXX_assert(index_offset >= 0,
                      "inconsistent header data");
          TSXX_assert(index_offset > header.nsamples,
                      "time series does not overlap with others");
          i_series->header.date=begin;
          i_series->header.nsamples -= index_offset;
210
          i_series->setfirstindex(i_series->f()+index_offset);
211
212
          ++i_series;
        }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
      }
    } // void TimeSeriesCollection<T>::trim_to_date() 

  /* ---------------------------------------------------------------------- */

  /*! \brief Trim to same number of samples
   *
   * Set length of all time series to smallest found in collection.
   */
  template<typename T>
    void TimeSeriesCollection<T>::trim_to_nsamples() 
    {
      this->synchronize_nsamples();
      if (this->size() > 1)
      {
        // find smallest number of samples in collection
229
        typename Tbase::iterator i_series=this->begin();
230
231
232
233
234
235
236
        Theader header=i_series->header;
        unsigned int nsamples=header.nsamples;
        ++i_series;
        while (i_series != this->end())
        {
          header=i_series->header;
          unsigned int thisnsamples=header.nsamples;
237
          nsamples = thisnsamples < nsamples ? thisnsamples : nsamples;
238
239
          ++i_series;
        }
240
241
242
243
244
245

        // adjust number of samples
        i_series=this->begin();
        while (i_series != this->end())
        {
          i_series->header.nsamples = nsamples;
246
          i_series->setlastindex(i_series->f()+nsamples-1);
247
248
          ++i_series;
        }
249
250
251
252
253
      }
    } // void TimeSeriesCollection<T>::trim_to_nsamples() 

  /* ---------------------------------------------------------------------- */

254
255
256
257
258
} // namespace ts

#endif // TS_TSCOLLECTION_H_VERSION (includeguard)

/* ----- END OF tscollection.h ----- */