Source code for irfpy.util.time_panel

''' Utility for time series panels, such as E-t diagram

.. codeauthor:: Yoshifumi Futaana

The function :func:`reform` will create a new matrix considering the data gap.
'''
from irfpy.util import exception as _ex

import numpy as _np


[docs]def reform(time_list, value_matrix, sampling_time): ''' Time series data is reformed considering the sampling time. :param time_list: ``np.array`` of the time when the data is sampled. (N,) shape. Float or ``datetime.datetime`` object. :param value_matrix: ``np.array`` of the data with (N, S) shape. S is the number of the spectrum data. :param sampling_time: Intrinsic sampling time. ``Float`` with a unit of day if ``time_list`` is float, but ``datetime.timedelta`` if time_list is ``datetime.datetime``. Usually, the observed data is given by the time and spectrum. For example, >>> import numpy as np >>> time_list = np.array([735000, 735001, 735002, 735004, 735005, 735006]) >>> img = np.array([[1, 1, 2,], [1, 2, 2,], ... [2, 2, 1,], [0, 2, 3,], ... [1, 3, 2,], [2, 1, 0,]]) A simple way to show this data is using ``meshcolor`` function. .. code-block:: python # Note: the second argument is "4", not "3". plt.meshcolor(t, np.arange(4), img.T) Then, you may get:: - 2 1 - v v 3| -| 2 2 1 1 3 2 2| -| 1 2 2 2 2 3 1| -| 1 1 2 2 0 1 0+------------- 0|1|2|3|4|5|6 +7.35e5 Here are two problems: 1. No data is shown for 735006. This is because the "end" time of the data is not specified. Most likely you want to plot the last (2, 1, 0) data between 735006 and "735007" 2. The data at 735003 is (likely) missing, because of some reasons. However, the program does not know it, so that the data (2, 2, 1) at 735002 is plotted until 735004. Both problems can be solved if you know the "sampling time". In this sample case, 1 day could be the most reasonable sampling time. >>> time_list2, value_matrix2 = reform(time_list, img, 1) will give you a reformed time list and value matrix (np.ma.array). >>> print(time_list2) [735000 735001 735002 735003 735004 735005 735006 735007] >>> print(value_matrix2) [[1.0 1.0 2.0] [1.0 2.0 2.0] [2.0 2.0 1.0] [-- -- --] [0.0 2.0 3.0] [1.0 3.0 2.0] [2.0 1.0 0.0]] Use :func:`reform2` if the time resolution changes. ''' n_time = time_list.shape[0] n_value = value_matrix.shape[0] if n_time != n_value: raise _ex.PyanaError( 'Element number error. time_list has {} element but value has {} element. They should be the same'.format( n_time, n_value)) # First, the end time is added. This can be done for free. time_list2 = _np.hstack([time_list, [time_list[-1] + sampling_time]]) value_matrix2 = value_matrix.copy() # Calculate the delta. delta_time_list2 = time_list2[1:] - time_list2[:-1] # Check if the delta > sampling_time, which include data gap datagap_index = _np.where(delta_time_list2 > sampling_time)[0] for idx in datagap_index[::-1]: # Iterate reversely. Index saved then. time_before = time_list2[:idx + 1] time_after = time_list2[idx + 1:] time_list2 = _np.hstack([time_before, [time_before[-1] + sampling_time], time_after]) value_before = value_matrix2[:idx + 1, :] value_after = value_matrix2[idx + 1:, :] insert_values = _np.zeros_like(value_matrix[0, :]) + _np.nan value_matrix2 = _np.vstack([value_before, insert_values, value_after]) value_matrix2 = _np.ma.masked_invalid(value_matrix2) return time_list2, value_matrix2
[docs]def reform2(time_list, value_matrix, sampling_time_list): """ Same functionality as reform, but different sampling time. :param time_list: ``np.array`` of the time when the data is sampled. (N,) shape. Float or ``datetime.datetime`` object. :param value_matrix: ``np.array`` of the data with (N, S) shape. S is the number of the spectrum data. :param sampling_time_list: List of sampling time. (N,) shape. Numpy array of ``Float`` with a unit of day if ``time_list`` is float, but numpy array of ``datetime.timedelta`` if time_list is ``datetime.datetime``. >>> import numpy as np >>> time_list = np.array([7350, 7351, 7352, 7354, 7355, 7356]) >>> img = np.array([[1, 1, 2,], [1, 2, 2,], ... [2, 2, 1,], [0, 2, 3,], ... [1, 3, 2,], [2, 1, 0,]]) >>> timeresolution = np.array([1, 1.5, 1, 0.5, 0.8, 2]) >>> time_list3, value_matrix3 = reform2(time_list, img, timeresolution) >>> print(time_list3) # doctest: +NORMALIZE_WHITESPACE [7350. 7351. 7352. 7353. 7354. 7354.5 7355. 7355.8 7356. 7358. ] >>> print(value_matrix3) [[1.0 1.0 2.0] [1.0 2.0 2.0] [2.0 2.0 1.0] [-- -- --] [0.0 2.0 3.0] [-- -- --] [1.0 3.0 2.0] [-- -- --] [2.0 1.0 0.0]] """ n_time = time_list.shape[0] n_value = value_matrix.shape[0] n_resol = sampling_time_list.shape[0] if n_time != n_value: raise _ex.IrfpyException( 'Element number error. time_list has {} element but value has {} element. They should be the same'.format( n_time, n_value)) if n_time != n_resol: raise _ex.IrfpyException( 'Element number error. time_list has {} element but resolution has {} element. They should be the same'.format( n_time, n_resol)) # Calculate the end time starttime = _np.array(time_list) # (N,) endtime = starttime + _np.array(sampling_time_list) # (N,) new_tlist = [starttime[0]] new_vallist = [value_matrix[0]] for iStart in range(1, n_time): if starttime[iStart] > endtime[iStart - 1]: new_tlist.append(endtime[iStart - 1]) new_vallist.append(_np.zeros_like(value_matrix[iStart]) + _np.nan) new_tlist.append(starttime[iStart]) new_vallist.append(value_matrix[iStart]) else: new_tlist.append(starttime[iStart]) new_vallist.append(value_matrix[iStart]) new_tlist.append(endtime[-1]) new_vallist = _np.ma.masked_invalid(new_vallist) new_tlist = _np.array(new_tlist) return new_tlist, new_vallist