Esempio n. 1
0
def extract_ndates_around_date(self, date, n):
    ###################################################################
    """
    Extract n values before and n values after a given date
    If n values are not available, returns all available values
    .data is set to None if no value at all is available

    :param date: date in decimal year
    :param n: number of observations to be extracted
    
    :return: a new Gts

    """

    # import
    import inspect
    import numpy as np

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    # copy
    new_Gts = self.copy(data_xyz=None)
    new_Gts.data = None

    try:
        sel_data_after = np.copy(self.data[np.where((self.data[:, 0] > date))])
    except:
        print("-- time series ", self.code, " does not have data after ", date)
        return (new_Gts)

    try:
        sel_data_before = np.copy(self.data[np.where(
            (self.data[:, 0] < date))])
    except:
        print("-- time series ", self.code, " does not have data before ",
              date)
        return (new_Gts)

    # extract data
    if sel_data_after.shape[0] > n:
        sel_data_after = sel_data_after[:n, :]

    if sel_data_before.shape[0] > n:
        sel_data_before = sel_data_before[-n:, :]

    sel_data = np.vstack((sel_data_before, sel_data_after))

    new_Gts.data = sel_data

    return (new_Gts)
Esempio n. 2
0
def detrend_annual(self,
                   method='L2',
                   in_place=False,
                   periods=None,
                   exclude_periods=None):
    """
    estimates a trend + annual terms in a time series and removes them
    velocity and annual attribute are saved in Gts.velocity & Gts.annual

    :param periods         : periods used for estimation
    :param exclude_periods : periods to be excluded from estimation
    :param in_place        : if True then replace the current time series
    :return                : the detrended time series
    :note                  : outliers from Gts.outliers are ommitted in the estimation and
    offsets given Gts.offsets_dates are estimated simultaneously

    """
    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    import copy
    outliers = copy.deepcopy(self.outliers)
    tmp_ts = self.remove_outliers()

    if periods:
        tmp_ts = tmp_ts.extract_periods(periods)
    if exclude_periods:
        tmp_ts = tmp_ts.exclude_periods(periods)

    detrended = tmp_ts.make_model(option='detrend_annual', method=method)

    vel = detrended.velocity
    offsets_values = detrended.offsets_values
    annual = detrended.annual

    new_gts = self.copy()
    new_gts.outliers = outliers
    new_gts.offsets_values = offsets_values
    new_gts.velocity = vel
    new_gts.annual = annual

    model = new_gts.mmodel()

    new_gts.data[:, 1:4] = new_gts.data[:, 1:4] - model.data[:, 1:4]

    if in_place:
        self.data = new_gts.data
    else:
        return (new_gts)
Esempio n. 3
0
def extract_ndates_before_date(self, date, n, verbose=False):
    ###################################################################
    """
    Extract n values before a given date
    If n values are not available, returns all available values before date
    .data is set to None if no value at all is available
    
    :param date: date in decimal year
    :param n: number of observations to be extracted
    
    :return: a new Gts
    
    """

    # import
    import inspect
    import numpy as np

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    # copy
    new_Gts = self.copy(data_xyz=None)
    new_Gts.data = None

    # extract data
    sel_data = np.copy(self.data[np.where(self.data[:, 0] < date)])
    if self.data_xyz is not None:
        sel_data_xyz = np.copy(self.data_xyz[np.where(self.data[:, 0] < date)])

    # extract data
    if sel_data.shape[0] > n:
        sel_data = sel_data[-n:, :]
        if self.data_xyz is not None:
            sel_data_xyz = sel_data_xyz[-n:, :]
    elif sel_data.shape[0] > 0:
        sel_data = sel_data[:, :]
        if self.data_xyz is not None:
            sel_data_xyz = sel_data_xyz[:, :]
    else:
        sel_data = None
        if verbose:
            print("-- time series ", self.code, " does not have data before ",
                  date)

    new_Gts.data = sel_data
    if self.data_xyz is not None:
        new_Gts.data_xyz = sel_data_xyz

    return (new_Gts)
Esempio n. 4
0
def remove_pole(self, pole, pole_type='euler', in_place=False, verbose=True):
    """
    remove velocity predicted by an Euler pole or a rotation rate vector from a time series
    pole is a 1D array with 3 values
    requires self.lon & self.lat attributes to have been filled before
    if in_place = True then replace the current time series
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    if (self.lon is None) or (self.lat is None):
        print(
            "!!! ERROR: lon & lat needs to be properly filled to use this method."
        )
        return ()

    from pyacs.lib.gmtpoint import GMT_Point

    M = GMT_Point(code=self.code,
                  lon=self.lon,
                  lat=self.lat,
                  Ve=0.,
                  Vn=0.,
                  SVe=0.,
                  SVn=0.)
    # N=M.substract_pole(pole,pole_type)

    N = M.pole(W=pole, SW=None, type_euler='euler', option='predict')

    vel_neu = np.array([N.Vn, N.Ve, 0.]) * 1E-3

    if verbose: print("-- Removing velocity (NEU)", vel_neu * 1.E3)

    new_Gts = self.remove_velocity(vel_neu)

    if in_place:
        self.data = new_Gts.data.copy()
    return (new_Gts)
Esempio n. 5
0
def rotate(self,angle,in_place=False):
###################################################################
    """
    rotates the axis by an angle

    :param angle: angle in decimal degrees clockwise
    
    if in_place = True then replace the current time series
    """

    # import 
    import inspect
    import numpy as np

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone
    
    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )

    # computes the rotates components
    angle_radian = np.radians( -angle )
    
    new_data=self.data.copy()
    
    new_x = new_data[:,2] * np.cos( angle_radian ) - new_data[:,1] * np.sin( angle_radian ) 
    new_y = new_data[:,2] * np.sin( angle_radian ) + new_data[:,1] * np.cos( angle_radian ) 
     
    new_data[:,1] = new_y
    new_data[:,2] = new_x

    new_data[:,4] = new_data[:,5] = 1.E-3
    new_data[:,7:] = 0.0

    new_Gts=self.copy(data=new_data)

    # .data_xyz set to None
    new_Gts.data_xyz = None
    
    
    if in_place:
        self.data=new_Gts.data.copy()
        return( self )
    else:
        return(new_Gts)
Esempio n. 6
0
def remove_velocity(self,vel_neu,in_place=False):
###################################################################
    """
    remove velocity from a time series
    vel_neu is a 1D array of any arbitrary length, but with the velocities (NEU) to be removed in the first 3 columns
    if in_place = True then replace the current time series
    """

    # import 
    import inspect
    import numpy as np

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone
    
    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )

    if self.t0 != None:
        ref_date=self.t0
    else:    
        ref_date=np.mean(self.data[0,0])
    
    v_neu= np.array( vel_neu[0:3] )
    
    
    new_data=self.data.copy()
     
    new_data[:,1:4]=new_data[:,1:4]-np.dot( (new_data[:,0]-ref_date).reshape(-1,1) , v_neu.reshape(1,3) )

    new_Gts=self.copy(data=new_data)
    
    # .data_xyz set to None
    new_Gts.data_xyz = None

    vel = vel_neu
    
    new_Gts.velocity = vel
    
    if in_place:
        self.data=new_Gts.data.copy()
        return( self )
    else:
        return(new_Gts)
Esempio n. 7
0
def frame(self, frame=None, in_place=False, verbose=False):
    """
    Rotates a time series according to an Euler pole
    Returns a new Gts instance
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    # Euler poles taken from pygvel_pole_info.py
    lEuler = {}
    lEuler['soam'] = [-132.21, -18.83, 0.121]
    lEuler['nas'] = [-97.52, 6.48, 0.359]
    lEuler['nazca'] = [-94.4, 61.0, 0.57]
    lEuler['nas_wrt_soam'] = [-83.40, 15.21, 0.287]
    lEuler['inca_wrt_soam'] = [-63.76, 22.47, 0.092]
    lEuler['eura'] = [
        -98.83483039304333, 54.22539546556553, 0.25678223107826376
    ]  # from Altamimi et al., 2012, eura_wrt_itrf2008

    euler_vector = np.array(lEuler[frame])

    new_Gts = self.remove_pole(euler_vector, verbose=verbose)
    if in_place:
        self.data = new_Gts.data.copy()
    return (new_Gts)
Esempio n. 8
0
def differentiate(self):
    ###################################################################
    """
    differentiate the current time series
    :return: the differentiated time series as a new Gts object
    :note : differentiation is made on .data. .data_xyz is set to None.
    """
    # import
    import inspect
    import numpy as np
    import pyacs.lib.astrotime

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    new_Gts = self.copy()
    data = self.data
    data_diff = np.diff(data, axis=0)

    # for dates
    data_mjd = pyacs.lib.astrotime.decyear2mjd(data[:, 0])
    new_data_mjd = (data_mjd[0:-1] + data_mjd[1:]) / 2.

    #    data_diff[:,0]=data[0:len(data[:,0])-1,0]+data_diff[:,0]

    data_diff[:, 0] = pyacs.lib.astrotime.mjd2decyear(new_data_mjd)

    new_Gts.data = data_diff.copy()

    # set .data_xyz to None

    new_Gts.data_xyz = None

    return (new_Gts)
Esempio n. 9
0
def decimate(self,time_step=30.,dates=[],method='median',verbose=False):
###################################################################
    """
    decimate a time series
    
    :param time_step: time step in days
    :param dates: list of dates where point are forced to be written regardless time_step
    :param method: method used to be used to calculated the position. choose among ['median','mean','exact']
    :param verbose: verbose mode
    
    :return : new Gts  
    """

    
    # import
    import inspect
    import numpy as np
    import pyacs.lib.astrotime as at

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone
    
    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )

    # start and end date
    start_decyear = self.data[0,0]
    end_decyear = self.data[-1,0]

    start_mjd = at.decyear2mjd(start_decyear)
    end_mjd = at.decyear2mjd(end_decyear)
    
    # new_gts to be filled
    new_gts=self.copy()
    
    new_gts.data=np.zeros((1,self.data.shape[1]))
    
    # loop on dates by time_step
    
    for date in np.arange(start_mjd ,end_mjd + time_step / 2. , time_step ):
        
        sub_ts=self.\
                    extract_periods( [at.mjd2decyear(date-time_step/2.),at.mjd2decyear(date+time_step/2.)] ,\
                                      verbose = verbose)
                
        if sub_ts.data is None:
            continue
        
        if method == 'median':
            new_obs = np.median(sub_ts.data,axis=0)
        if method == 'mean':
            new_obs = np.mean(sub_ts.data,axis=0)
        if method == 'exact':
            new_obs = sub_ts.data[int(sub_ts.data.shape[0])-1,:]

    
        new_gts.data = np.vstack( ( new_gts.data, new_obs.reshape(1,-1) ) )

    # case dates are provided
    
    for date in dates:
        sub_ts=self.extract_periods( [date,end_decyear] , verbose = verbose)
        
        if sub_ts.data is not None:
            new_obs = sub_ts.data[0,:]
            if verbose:
                print("-- adding observation at user requested date: %lf = %s = doy %d" % 
                      ( date, '-'.join(map(str, at.decyear2cal(date))), at.decyear2dayno(date)))
                
            if new_gts.data is not None:
                new_gts.data = np.vstack( ( new_gts.data, new_obs.reshape(1,-1) ) )
            else:
                new_gts.data = new_obs.new_obs.reshape(1,-1)

    # remove first obs
    
    if new_gts.data.shape[0] == 1:
        if verbose:
            print('!!! decimated Gts has no date')
        new_gts.data = None
        new_gts.data_xyz = None
        return(new_gts)
    
    else:
        
        new_gts.data = np.delete(new_gts.data,0,axis=0)
        new_gts.neu2xyz()
        
        # reorder
        new_gts.reorder(verbose=verbose)
        if verbose:
            print('-- decimated Gts has ',new_gts.data.shape[0],' entries')

        return(new_gts)
Esempio n. 10
0
def spline(self, smoothing=1, degree=5, date=None):
    """
    :param smoothing: Positive smoothing factor used to choose the number of knots. Number of knots will be increased
    until the smoothing condition is satisfied:
        sum((w[i] * (y[i]-spl(x[i])))**2, axis=0) <= s
    :param degree: Degree of the smoothing spline. Must be <= 5. Default is k=3, a cubic spline.
    :param date: 1D array of interpolation dates in decimal year, or 'day' for every day. defualt None will interpolate
    at data date only.
    :return: new gts instance
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    # import
    from scipy.interpolate import UnivariateSpline
    import numpy as np

    Spline_ts = self.copy()
    s_e = UnivariateSpline(self.data[:, 0],
                           self.data[:, 1],
                           s=smoothing * 1E-3,
                           k=degree)
    s_n = UnivariateSpline(self.data[:, 0],
                           self.data[:, 2],
                           s=smoothing * 1E-3,
                           k=degree)
    s_u = UnivariateSpline(self.data[:, 0],
                           self.data[:, 3],
                           s=smoothing * 1E-3,
                           k=degree)
    if date is None:
        Spline_ts.data[:, 1] = s_e(self.data[:, 0])
        Spline_ts.data[:, 2] = s_n(self.data[:, 0])
        Spline_ts.data[:, 3] = s_u(self.data[:, 0])
    if isinstance(date, np.ndarray):
        Spline_ts.data[:, 1] = s_e(date)
        Spline_ts.data[:, 2] = s_n(date)
        Spline_ts.data[:, 3] = s_u(date)
    if date == 'day':
        import pyacs.lib.astrotime as at
        np_date = at.mjd2decyear(
            np.arange(at.decyear2mjd(self.data[0, 0]),
                      at.decyear2mjd(self.data[-1, 0])))
        Spline_ts.data = np.zeros((np_date.shape[0], 10))
        Spline_ts.data[:, 0] = np_date
        Spline_ts.data[:, 1] = s_e(np_date)
        Spline_ts.data[:, 2] = s_n(np_date)
        Spline_ts.data[:, 3] = s_u(np_date)

    return (Spline_ts)
Esempio n. 11
0
def substract_ts_daily(self,ts,verbose=True):
###################################################################
    """
    substract the ts provided as argument to the current time series
    
    :param ts: time series to be substracted as a Gts instance
    :param verbose: verbose mode
    :return : new Gts
    
    :note: this method assumes daily time series
    """

    # import 
    import inspect
    import numpy as np
    import pyacs.lib.astrotime as at
    
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone
    
    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )

    # check data is not None
    
    try:
        if ts.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,ts)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )


    # find common dates

    np_mjd_1 = at.decyear2mjd( self.data[:,0] ).astype( int )
    np_mjd_2 = at.decyear2mjd( ts.data[:,0] ).astype( int )
    
    np_mjd_common_dates = np.intersect1d( np_mjd_1 ,  np_mjd_2 )

    if verbose:
        print('-- ', np_mjd_common_dates.shape[0] , ' common dates found.')

    # test whether there are common dates
    
    if np_mjd_common_dates.shape[0] == 0:
        print('! WARNING No common dates between ',self.code,' from ',self.ifile)
        print('!!! and ',ts.code, ' from ',ts.ifile)
        
        new_data = None

    else:
        # extract

        mask1 = np.isin( np_mjd_1, np_mjd_common_dates )
        data1 = self.data[ mask1 ]
        
        mask2 = np.isin( np_mjd_2, np_mjd_common_dates )
        data2 = ts.data[ mask2 ]

        
        if data1.shape != data2.shape:
            print("!!! ERROR. Extracted data have different shapes")
            new_data = None
        
        # ENU
        new_data = data1 - data2
        # dates
        new_data[:,0] = data1[:,0]
        # uncertainties
        new_data[:,4:8] = np.sqrt( data1[:,4:8]**2 + data2[:,4:8]**2 )
        new_data[:,8:] = 0.
                
    new_code=self.code+'_'+ts.code

    new_Gts=self.copy(data=new_data)
    new_Gts.code=new_code

    # .data_xyz set to None
    new_Gts.data_xyz = None


    return(new_Gts)
Esempio n. 12
0
def substract_ts(self, ts, tol=0.05, verbose=True):
    ###################################################################
    """
    substract the ts provided as argument to the current time series
    
    :param ts: time series to be substracted as a Gts instance
    :param tol: date tolerance to decide whether two dates are identical in both time series. default = 1/4 day
    :param verbose: verbose mode
    :return : new Gts
    
    """

    # import
    import inspect
    import numpy as np
    import pyacs.gts.Gts

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    # check data is not None

    try:
        if ts.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, ts)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    tol = tol / 365.25  # tolerance in decimal year

    # find common dates

    #common_dates=np.intersect1d(np.round(self.data[:,0],decimals=7),np.round(ts.data[:,0],decimals=7))

    lindex = pyacs.gts.Gts.get_index_from_dates(self.data[:, 0], ts.data, tol)

    if verbose:
        print('-- ', len(lindex), ' common dates found.')

    common_dates = self.data[lindex, 0]

    # test whether there are common dates

    if common_dates.shape[0] == 0:
        print('! WARNING No common dates between ', self.code, ' from ',
              self.ifile)
        print('!!! and ', ts.code, ' from ', ts.ifile)

        new_data = None

    else:
        # extract
        extracted_target = self.extract_dates(common_dates, tol=tol)
        extracted_ref = ts.extract_dates(common_dates, tol=tol)

        new_data = extracted_target.data - extracted_ref.data

        new_data[:, 0] = common_dates

        new_data[:, 4] = np.sqrt(extracted_target.data[:, 4]**2 +
                                 extracted_ref.data[:, 4]**2)
        new_data[:, 5] = np.sqrt(extracted_target.data[:, 5]**2 +
                                 extracted_ref.data[:, 5]**2)
        new_data[:, 6] = np.sqrt(extracted_target.data[:, 6]**2 +
                                 extracted_ref.data[:, 6]**2)

    new_code = self.code + '_' + ts.code

    new_Gts = self.copy(data=new_data)
    new_Gts.code = new_code
    # .data_xyz set to None
    new_Gts.data_xyz = None

    return (new_Gts)
Esempio n. 13
0
def plot(self,
         title=None,
         loffset=True,
         loutliers=True,
         verbose=False,
         date=[],
         yaxis=None,
         min_yaxis=None,
         yupaxis=None,
         xticks_minor_locator=1,
         lcomponent=['N', 'E', 'U'],
         error_scale=1.0,
         lperiod=[[]],
         lvline=[],
         save_dir_plots='.',
         save=None,
         show=True,
         unit='mm',
         date_unit='cal',
         date_ref=0.0,
         center=True,
         superimposed=None,
         lcolor=['r', 'g', 'c', 'm', 'y', 'k', 'b'],
         label=None,
         legend=False,
         set_zero_at_date=None,
         grid=True,
         plot_size=None,
         info=[],
         xlabel_fmt=None,
         **kwargs):
    ###############################################################################
    """
    Create a plot of a North-East-Up time series and related info (offsets, outliers) using Matplotlib

    Coordinates of the time series are assumed to be in meters
    default plots units will be mm; Use unit='m' to get meters instead

    :param title: string to be added to the site name as a plot title
    :param loffset: boolean
        print a dash vertical line at offset dates
    :param loutliers: boolean
        print outliers
    :param verbose: boolean
        verbose mode
    :param date: [sdate,edate]
        start and end date for plots
        sdate and edate in decimal years if date_unit is either 'decyear' or 'cal', or in days if date_unit is 'days'
    :param yaxis: [min_y,max_y]
        min and max value for the yaxis
        if not provided automatically adjusted
    :param yupaxis: same as yaxis but applies to the up component only
    :param xticks_minor_locator: where xticks_minor_locator will be placed. Float when date_unit is 'decyear' or 'days', a string '%Y','%m','%d' is date_unit is 'cal'.  
    :param lcomponent: list of components to be plotted (default =['N','E','U'])
    :param error_scale: scaling factor for error bars (default = 1.0, 0 means no error bar)
    :param lperiod: list of periods to be drawn in background (color=light salmon)
    :param lvline: list of dates where vertical lines will be drawn in background (color=green)
    :param save_dir_plots: directory used for saving the plots
    :param save: name, save the plot into name, if simply True an automatic name is given
    :param show: boolean, is True show the plot
    :param unit: 'm','cm','mm', default='mm'
    :param date_unit: 'decyear' or 'cal' or 'days', default='decyear'
    :param date_ref: reference date, default=0.0
    :param center: boolean, if True the y_axis is centered around the mean value for the plotted period
    :param superimposed: if a gts is provided, it is superimposed to the master, default=None
    :param lcolor: color list used for the superimposed time series, default=['r','g','c','m','y','k','b']
    :param label: label for superimposed time series to be displayed in legend, default=None
    :param legend: boolean. Set true to display label for superimposed time series, default=False
    :param set_zero_at_date: date at which the master and superimposed gts will be equal (default=None). date can also be a list with [date,offset_north,offset_east,offset_up]
    :param plot_size: plot size as a tuple. Default, best guess.
    :param grid: boolean
    :param info: title to appear in time series subplots
    :param **kwargs: any argument to be passed to  matplotlib.pyplot.errorbar

    :note: The list of kwargs are:
    
    {  'linewidth' : 0,\
       'marker' : marker_main_symbol ,\
       'markersize' : marker_main_size, \
       'markerfacecolor' : marker_main_color,\
       'markeredgecolor' : marker_main_color,\
       'markeredgewidth' : marker_main_colorlw,\
       'ecolor' : error_bar_color,\
       'elinewidth' : error_bar_linewidth,\
       'capsize' : error_bar_capsize }

    """

    ###########################################################################
    # import
    ###########################################################################

    # system
    import inspect
    import numpy as np
    import os.path

    # matplotlib
    import matplotlib.pyplot as plt
    import matplotlib.ticker as ticker
    from matplotlib.ticker import MultipleLocator
    import matplotlib.dates as mdates

    # pyacs
    from pyacs.gts.lib.errors import GtsInputDataNone
    import pyacs.gts.lib.plot.init_plot_settings
    import pyacs.lib.astrotime
    from pyacs.gts.Gts import Gts
    import pyacs.lib.utils
    import pyacs.gts.lib.plot.make_stitle
    import pyacs.gts.lib.plot.gts_to_ts

    ###########################################################################
    # lcolor
    ###########################################################################

    if (superimposed is not None) and (isinstance(
            superimposed, list)) and (len(superimposed) > 7):
        lcolor = np.random.rand(len(superimposed), 3)

    ###########################################################################
    # check data is not None
    ###########################################################################

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    ###########################################################################
    # ensure superimposed is either None or a list of gts
    ###########################################################################

    if superimposed is not None:
        if not isinstance(superimposed, list):
            superimposed = [superimposed]

        for agts in superimposed:
            if not isinstance(agts, Gts):
                raise TypeError

    ###########################################################################
    # ensure lperiod is a list of list
    ###########################################################################
    lperiod = pyacs.lib.utils.__ensure_list_of_list(lperiod)

    ###########################################################################
    # init default plot settings
    ###########################################################################

    H_plot_settings, H_kwargs_errorbar, H_kwargs_errorbar_superimposed = pyacs.gts.lib.plot.init_plot_settings.__init_kwargs(
    )

    ###########################################################################
    # init plot settings with user provided values
    ###########################################################################

    for k, v in kwargs.items():
        H_kwargs_errorbar[k] = v

    # turn show to off by default
    plt.ioff()

    # some drawing default parameters
    params = {'legend.fontsize': 5}
    plt.rcParams.update(params)

    # For figure caption
    txt_component = {}
    txt_component['N'] = 'North'
    txt_component['E'] = 'East'
    txt_component['U'] = 'Up'

    # plot size
    if plot_size is None:
        if len(lcomponent) == 1:
            plot_size = H_plot_settings['plot_size_1_component']
        if len(lcomponent) == 2:
            plot_size = H_plot_settings['plot_size_2_component']
        if len(lcomponent) == 3:
            plot_size = H_plot_settings['plot_size_3_component']

    lperiod_facecolor = 'r'
    lperiod_alpha = 0.4

    ###########################################################################
    # format for printing duration in subplot titles
    ###########################################################################

    if date != []: duration = date[-1] - date[0]
    else: duration = self.data[-1, 0] - self.data[0, 0]

    ###########################################################################
    # x-tick label
    ###########################################################################
    # adjust tickers for the decyear case
    if date_unit == 'decyear' or date_unit == 'days':
        if xlabel_fmt != None:
            fmt = ticker.FormatStrFormatter(xlabel_fmt)
        else:
            if duration >= 1.0: fmt = ticker.FormatStrFormatter('%4.0lf')
            if duration < 1.0: fmt = ticker.FormatStrFormatter('%6.2lf')
            if duration < 0.2: fmt = ticker.FormatStrFormatter('%6.3lf')
            if duration < 0.1: fmt = ticker.FormatStrFormatter('%6.4lf')

        plt.rcParams['axes.formatter.limits'] = (-7, 17)

    if date_unit == 'cal':
        if xlabel_fmt is not None:
            fmt = mdates.DateFormatter(xlabel_fmt)

    ###########################################################################
    # title and subtitle
    ###########################################################################

    if title is not None:
        stitle = title
    else:
        stitle = self.code

    ###########################################################################
    # info
    ###########################################################################

    if info == []:
        info = len(lcomponent) * ['']

    ###########################################################################
    # to_unit
    ###########################################################################

    if unit == 'cm':
        to_unit = 100.

    if unit == 'mm':
        to_unit = 1000.

    ###########################################################################
    # START PLOTTING
    ###########################################################################
    plt.ioff()
    f, ax = plt.subplots(len(lcomponent), sharex=True, figsize=plot_size)

    ###########################################################################
    # rotate xticks labels
    ###########################################################################
    f.autofmt_xdate(bottom=0.2, rotation=30, ha='right')

    # handle case where only one component and ax is not subscriptable
    if not isinstance(ax, np.ndarray):
        ax = np.array([ax])

    np_date , data = pyacs.gts.lib.plot.gts_to_ts.gts_to_ts( self , \
                                                             date=date, \
                                                             unit=unit , \
                                                             date_unit=date_unit , \
                                                             date_ref=date_ref, \
                                                             set_zero_at_date = set_zero_at_date, \
                                                             center = center )

    # master time series
    ###########################################################################
    idx_ax = 0

    for component in lcomponent:
        # idx_component
        if component == 'N':
            idx = 0
        if component == 'E':
            idx = 1
        if component == 'U':
            idx = 2

        # subplot title
        str_title = pyacs.gts.lib.plot.make_stitle.make_stitle(
            component, info=info[idx_ax])
        ax[idx_ax].set_title(str_title,
                             x=0,
                             horizontalalignment='left',
                             fontsize='11')

        # plot the data
        #        print( H_kwargs_errorbar )
        ax[idx_ax].errorbar(np_date,
                            data[:, idx],
                            yerr=data[:, idx + 3] * error_scale,
                            **H_kwargs_errorbar)

        # plot outliers
        if self.outliers != []:
            ax[idx_ax].plot(np_date[self.outliers],
                            data[self.outliers, idx],
                            'ro',
                            markersize=H_kwargs_errorbar['markersize'])

        # Y-label
        ax[idx_ax].set_ylabel(unit)

        # grid
        ax[idx_ax].grid(grid)

        # xticks
        if date_unit == 'decyear':
            ax[idx_ax].xaxis.set_major_formatter(fmt)

        if date_unit == 'cal' and xlabel_fmt is not None:
            ax[idx_ax].xaxis.set_major_formatter(fmt)

        idx_ax = idx_ax + 1

    # superimposed time series
    ###########################################################################

    if superimposed is None:
        wsuperimposed = []
    else:
        wsuperimposed = list(superimposed)

    # Get label

    if label is None:
        label = []
        for my_ts in wsuperimposed:
            label.append(my_ts.code)

    # test
    np_date = None
    data = None

    for i in np.arange(len(wsuperimposed)):

        if verbose:
            print('-- plotting superimposed time series: ', label[i])

        np_date , data = pyacs.gts.lib.plot.gts_to_ts.gts_to_ts( wsuperimposed[i] , \
                                                                 date=date, \
                                                                 unit=unit , \
                                                                 date_unit=date_unit , \
                                                                 date_ref=date_ref, \
                                                                 set_zero_at_date = set_zero_at_date, \
                                                                 center = center )

        idx_ax = 0

        for component in lcomponent:
            # idx_component
            if component == 'N':
                idx = 0
            if component == 'E':
                idx = 1
            if component == 'U':
                idx = 2

            # plot the data
            error_scale = 0.
            ax[idx_ax].errorbar(np_date,
                                data[:, idx],
                                yerr=data[:, idx + 3] * error_scale,
                                color=lcolor[i],
                                label=label[i])
            idx_ax = idx_ax + 1

    # plot offset_date of the master time series
    ###########################################################################
    if loffset:
        if date_unit == 'days':
            if (date_ref is None) or (date_ref == 0):
                # reference data is year.000
                date_ref = float(int(self.data[0, 0]))

            ldate_offsets_in_date_unit = pyacs.lib.astrotime.decyear2mjd(
                self.offsets_dates) - pyacs.lib.astrotime.decyear2mjd(date_ref)

        if date_unit == 'decyear':
            ldate_offsets_in_date_unit = np.array(
                self.offsets_dates) - date_ref

        if date_unit == 'cal':
            ldate_offsets_in_date_unit = pyacs.lib.astrotime.decyear2datetime(
                self.offsets_dates)

        idx_ax = 0
        for component in lcomponent:
            for odate in ldate_offsets_in_date_unit:
                ax[idx_ax].axvline(x=odate,
                                   linewidth=2,
                                   color='k',
                                   linestyle='--')
            idx_ax = idx_ax + 1

    # lperiod option: periods to be highlighted
    ###########################################################################

    if lperiod != [[]]:
        if date_unit == 'days':
            if (date_ref is None) or (date_ref == 0):
                # reference data is year.000
                date_ref = float(int(self.data[0, 0]))

            lperiod = pyacs.lib.astrotime.day_since_decyear(
                np.array(lperiod).flatten(), date_ref).reshape(-1, 2)

        if date_unit == 'decyear':
            lperiod = (np.array(lperiod).flatten() - date_ref).reshape(-1, 2)

        if date_unit == 'cal':
            lperiod = np.array(
                pyacs.lib.astrotime.decyear2datetime(
                    np.array(lperiod).flatten())).reshape(-1, 2)

        # plot color background for periods
        idx_ax = 0
        for component in lcomponent:
            for period in lperiod:
                (sdate, edate) = period
                ax[idx_ax].axvspan(sdate,
                                   edate,
                                   facecolor=lperiod_facecolor,
                                   alpha=lperiod_alpha)

            idx_ax = idx_ax + 1

    # vertical lines option
    ###########################################################################

    if lvline != []:

        if date_unit == 'decyear':
            lvline_in_date_unit = np.array(lvline) - date_ref

        if date_unit == 'days':
            lvline_in_date_unit = np.array(lvline) - date_ref

        if date_unit == 'cal':
            lvline_in_date_unit = pyacs.lib.astrotime.decyear2datetime(lvline)

        idx_ax = 0
        for component in lcomponent:
            for odate in lvline_in_date_unit:
                ax[idx_ax].axvline(x=odate,
                                   linewidth=2,
                                   color='g',
                                   linestyle='--')
            idx_ax = idx_ax + 1

    # title
    ###########################################################################
    plt.suptitle(stitle)

    # yaxis
    ###########################################################################

    # added JMN 13/01/2021 to set a minimum value for y-scale
    if (min_yaxis is not None) and (yaxis is None):

        idx_ax = 0
        for component in lcomponent:
            if component in ['N', 'E']:
                cyaxis = ax[idx_ax].get_ylim()
                ax[idx_ax].set_ylim(np.min([cyaxis[0], -min_yaxis]),
                                    np.max([cyaxis[1], min_yaxis]))
            if component == 'U':
                cyupaxis = ax[idx_ax].get_ylim()
                ax[idx_ax].set_ylim(np.min([cyupaxis[0], -min_yaxis]),
                                    np.max([cyupaxis[1], min_yaxis]))

            idx_ax = idx_ax + 1

    if yaxis is not None:
        idx_ax = 0
        for component in lcomponent:
            if component in ['N', 'E']:
                ax[idx_ax].set_ylim(yaxis[0], yaxis[1])
            if component == 'U' and yupaxis is not None:
                ax[idx_ax].set_ylim(yupaxis[0], yupaxis[1])

            idx_ax = idx_ax + 1

    # date
    ###########################################################################

    if date != []:

        # case 'days'
        if date_unit == 'days':
            if (date_ref is None) or (date_ref == 0):
                np_date_x = pyacs.lib.astrotime.decyear2mjd(
                    np.array(date)) - pyacs.lib.astrotime.decyear2mjd(date[0])
            else:
                np_date_x = pyacs.lib.astrotime.decyear2mjd(
                    np.array(date)) - pyacs.lib.astrotime.decyear2mjd(date_ref)

        # case 'decyear'
        if date_unit == 'decyear':
            if (date_ref is None) or (date_ref == 0):
                np_date_x = np.array(date)
            else:
                np_date_x = np.array(date) - date_ref

        # case 'cal'
        if date_unit == 'cal':
            np_date_x = pyacs.lib.astrotime.decyear2datetime(np.array(date))
        idx_ax = 0
        for component in lcomponent:
            if component in ['N', 'E']:
                ax[idx_ax].set_xlim(np_date_x[0], np_date_x[1])
            if component == 'U' and yupaxis is not None:
                ax[idx_ax].set_xlim(np_date_x[0], np_date_x[1])

            idx_ax = idx_ax + 1

    # X Label
    ###########################################################################

    if date_unit == 'decyear':
        if (date_ref is None) or (date_ref == 0.0):
            str_xlabel = 'year'
        else:
            str_xlabel = ("decimal year since %s" %
                          pyacs.lib.astrotime.decyear2datetime(date_ref))

    if date_unit == 'days':

        if (date_ref is None) or (date_ref == 0):
            # reference data is year.000
            date_ref = float(int(self.data[0, 0]))

        str_xlabel = ("days since %s" %
                      pyacs.lib.astrotime.decyear2datetime(date_ref))

    if date_unit == 'cal':
        str_xlabel = ("calendar date")

    ax[idx_ax - 1].set_xlabel(str_xlabel)

    # xtcicks minor locator
    ###########################################################################
    if date_unit == 'decyear':
        idx_ax = 0
        for component in lcomponent:
            ax[idx_ax].xaxis.set_minor_locator(
                MultipleLocator(float(xticks_minor_locator)))
            idx_ax = idx_ax + 1

    if date_unit != 'days':
        idx_ax = 0
        if duration > 100:
            xticks_minor_locator = 10
        if duration > 1000:
            xticks_minor_locator = 100
        if duration > 10000:
            xticks_minor_locator = 1000

        for component in lcomponent:

            ax[idx_ax].xaxis.set_minor_locator(
                MultipleLocator(float(xticks_minor_locator)))
            idx_ax = idx_ax + 1

    if date_unit == 'cal':
        # default
        if self.data[-1, 0] - self.data[0, 0] > 5.:
            locator = mdates.YearLocator()
        else:
            locator = mdates.MonthLocator()

        # user provided default
        if xticks_minor_locator == '%Y':
            locator = mdates.YearLocator()  # every year
        if xticks_minor_locator == '%m':
            locator = mdates.MonthLocator()  # every month
        if xticks_minor_locator == '%d':
            locator = mdates.DayLocator()  # every day

        idx_ax = 0
        for component in lcomponent:
            ax[idx_ax].xaxis.set_minor_locator(locator)
            idx_ax = idx_ax + 1

    # legend
    ###########################################################################

    if legend:
        idx_ax = 0
        for component in lcomponent:
            ax[idx_ax].legend()
            idx_ax = idx_ax + 1

    # tight_layout
    ###########################################################################

    plt.subplots_adjust(left=None,
                        bottom=None,
                        right=None,
                        top=None,
                        wspace=None,
                        hspace=H_plot_settings['hspace'])

    # end of subplots
    ###########################################################################

    # save file as png if save option is set
    ###########################################################################

    if save is not None:

        # case save is a string

        if isinstance(save, str):

            # check whether save includes a path or simply a file name

            if os.path.sep in save:
                # save includes a path information
                fname = save
            else:
                # else
                fname = os.path.normpath(save_dir_plots + '/' + save)

        elif save:
            # save is simply set to True for automatic output file naming
            fname = os.path.normpath(save_dir_plots + '/' + self.code + '.png')

        # saving output file

        if verbose:
            print("-- Saving file to ", fname)

        # creates the directory of it does not exist

        if os.path.sep in fname:
            os.makedirs(os.path.dirname(fname), exist_ok=True)

#        plt.savefig(fname, dpi=150, facecolor='w', edgecolor='w', orientation='portrait', papertype='a4', format='png',transparent=False, pad_inches=0.1)
# change 05/04/2021 papertype appears to be decommissioned for matplotlib 3.3
        plt.savefig(fname,
                    dpi=150,
                    facecolor='w',
                    edgecolor='w',
                    orientation='portrait',
                    format='png',
                    transparent=False,
                    pad_inches=0.1)

    # show
    ###########################################################################
    if show:
        # do not block program execution when displaying figures
        plt.ion()
        plt.show()
    else:
        plt.close(f)

    # returns the Gts for pyacs convention compatibility
    new_Gts = self.copy()

    return (new_Gts)
Esempio n. 14
0
def get_coseismic(self,
                  eq_date,
                  window_days=5,
                  sample_after=1,
                  method='median',
                  in_place=False):
    ###################################################################
    """
    Get coseismic displacement at a given date.
    Coseismic displacement is estimated as the position difference between the median of window_days before 
    the earthquake date and the median of sample_after samples after the earthquake date. 
    
    note: only median method implemented
    
    """

    # import
    import inspect
    import numpy as np
    import pyacs.lib.astrotime
    from datetime import timedelta

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    # eq date as datetime
    eq_datetime = pyacs.lib.astrotime.decyear2datetime(eq_date)
    # get the eq day at 00:00:00 and then go backward by window_days
    wdatetime = eq_datetime.replace(
        hour=0, minute=0, second=0,
        microsecond=0) - timedelta(days=window_days)
    # convert back to decimal year
    wdecyear = pyacs.lib.astrotime.datetime2decyear(wdatetime)
    # make extraction between eq - window_days and eq_date
    lindex = np.where((self.data[:, 0] > wdecyear)
                      & (self.data[:, 0] < eq_date))[0]
    data_before_eq = self.data[lindex, 1:4]
    # take sample_after values after eq_date
    lindex = np.where(self.data[:, 0] > eq_date)[0][0]
    data_after_eq = self.data[lindex:lindex + sample_after, 1:4]
    # get offset values
    disp = np.median(data_after_eq, axis=0) - np.median(data_before_eq, axis=0)
    # calculates std before eq
    std_sdate = np.std(data_before_eq, axis=0)
    # calculates std after eq
    std_edate = np.std(data_after_eq, axis=0)

    # if std cannot be calculated or is 0.
    if np.max(std_sdate) == 0.0:
        lindex = np.where((self.data[:, 0] > wdecyear)
                          & (self.data[:, 0] < eq_date))[0]
        std_sdate = np.mean(self.data[lindex, 4:7], axis=0)

    if np.max(std_edate) == 0.0:
        lindex = np.where(self.data[:, 0] > eq_date)[0][0]
        std_sdate = np.mean(self.data[lindex, 4:7], axis=0)

    std_disp = np.sqrt(std_edate**2 + std_sdate**2)

    new_Gts = self.copy()

    # modify the output time series
    new_Gts.data_xyz = None
    new_Gts.data[:, 1:4] = new_Gts.data[:, 1:4] - np.median(data_before_eq,
                                                            axis=0)

    if in_place:
        self.offsets_values = np.array([eq_date] + disp.tolist() +
                                       std_disp.tolist()).reshape(1, 7)
        return (self)
        del new_Gts
    else:
        new_Gts.offsets_values = np.array([eq_date] + disp.tolist() +
                                          std_disp.tolist()).reshape(1, 7)
        return (new_Gts)
Esempio n. 15
0
def detrend_median(self,
                   delta_day=None,
                   in_place=False,
                   periods=[],
                   exclude_periods=[],
                   verbose=False,
                   auto=False):
    ###############################################################################
    """
    Calculates a velocity using the median of pair of displacements exactly separated by one year, inspired from MIDAS
    If the time series has less than a year of data, then the time series is kept untouched.
    :param delta_day: if None, it is one year, if 0 then it is the relax mode for campaign data,
        any integer is the time delta (in days) used to compute velocity.
    :param in_place: boolean, if True, in_place, if False, returns a new Gts instance (default)
    :param periods: periods (list of lists) to be included for trend calculation
    :param exclude_periods: periods (list of lists) to be excluded for trend calculation
    :param verbose: verbose mode
    :param auto: if True, then start will delta_day=None, if it fails or found less than 100 pairs then use delta_day=0,
        if fails then use regular detrend
    :note: returns None if time series is shorter than 1 year
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    ###########################################################################
    # 1-yr threshold
    ###########################################################################

    if (self.data[-1, 0] - self.data[0, 0]) < 1.:
        if verbose:
            print("!!! WARNING: time series shorter than 1 year for side: %s" %
                  self.code)
        return (None)

    ###########################################################################
    # run the appropriate estimator using autoreference if auto is True
    ###########################################################################

    if auto:

        tts = self.detrend_median(delta_day=None, in_place=in_place, \
                                  periods=periods, exclude_periods=exclude_periods, \
                                  verbose=verbose, auto=False)

        if tts is None:
            tts = self.detrend_median(delta_day=0, in_place=in_place, \
                                      periods=periods, exclude_periods=exclude_periods, \
                                      verbose=verbose, auto=False)

        if tts is None:
            tts = self.detrend(in_place=in_place, \
                               periods=periods, exclude_periods=exclude_periods, \
                               verbose=verbose)

        return (tts)

    ###########################################################################
    # start main detrend_median
    ###########################################################################

    import pyacs.lib.astrotime

    tmp_ts = self.remove_outliers()

    if periods != []:
        tmp_ts = tmp_ts.extract_periods(periods)
    if exclude_periods != []:
        tmp_ts = tmp_ts.exclude_periods(periods)

    # minimum number of pair velocity estimates to consider the result

    min_vel_estimate = 100

    ###########################################################################
    # MIDAS-like method, using 1-year pair data for velocity estimate
    ###########################################################################

    if delta_day is None:

        duration_in_year = tmp_ts.data[-1, 0] - tmp_ts.data[0, 0]

        if duration_in_year >= 1.:

            H_year = {}

            # creates H_year arrays

            for year in np.arange(int(tmp_ts.data[0, 0]),
                                  int(tmp_ts.data[-1, 0]) + 1):
                H_year[year] = np.zeros((365, 3))
                H_year[year][:, :] = np.nan

            # deal with dates

            np_mjd = pyacs.lib.astrotime.decyear2mjd(tmp_ts.data[:, 0])
            (np_doy, np_year, _np_ut) = pyacs.lib.astrotime.mjd2dayno(np_mjd)

            np_doy = np_doy.astype(int)
            np_year = np_year.astype(int)

            # fill H_year arrays

            for i in np.arange(np_doy.shape[0]):
                if np_doy[i] != 366:
                    H_year[np_year[i]][np_doy[i] - 1, :] = tmp_ts.data[i, 1:4]

            # stack the velocities

            np_vel = np.zeros((365 * (len(H_year) - 1), 3))
            np_vel[:, :] = np.nan

            i = 0
            for year in sorted(H_year.keys())[0:-1]:
                np_vel[i * 365:(i + 1) * 365] = H_year[year + 1] - H_year[year]
                i = i + 1

            # test whether there are at least 3 non-Nan numbers

            if np.count_nonzero(~np.isnan(np_vel)) < min_vel_estimate:
                return (None)

            # calculates the median velocity

            med_vel = np.nanmedian(np_vel, axis=0)

            [med_vel_north, med_vel_east, med_vel_up] = med_vel

            # calculate uncertainty and refined value of vel using step 2 from Blewitt et al. (2016) p. 2057
            # remove Nan

            np_vel_north = np_vel[:, 0][np.logical_not(np.isnan(np_vel[:, 0]))]
            np_vel_east = np_vel[:, 1][np.logical_not(np.isnan(np_vel[:, 1]))]
            np_vel_up = np_vel[:, 2][np.logical_not(np.isnan(np_vel[:, 2]))]

            # calculates sigma

            fabs_vn = np.fabs(np_vel_north - med_vel_north)
            fabs_ve = np.fabs(np_vel_east - med_vel_east)
            fabs_vu = np.fabs(np_vel_up - med_vel_up)

            sigma_vn = 1.4826 * np.median(fabs_vn)
            sigma_ve = 1.4826 * np.median(fabs_ve)
            sigma_vu = 1.4826 * np.median(fabs_vu)

            # removes all vel > 1.4826 * med_vel

            np_vel_north_cln = np_vel_north[np.where(fabs_vn <= 2 * sigma_vn)]
            np_vel_east_cln = np_vel_east[np.where(fabs_ve <= 2 * sigma_ve)]
            np_vel_up_cln = np_vel_up[np.where(fabs_vu <= 2 * sigma_vu)]

            # get the new vel estimates

            med_vn = np.median(np_vel_north_cln)
            med_ve = np.median(np_vel_east_cln)
            med_vu = np.median(np_vel_up_cln)

            # get the new sigma

            med_sigma_vn = 1.4826 * np.median(
                np.fabs(np_vel_north_cln - med_vn))
            med_sigma_ve = 1.4826 * np.median(
                np.fabs(np_vel_east_cln - med_ve))
            med_sigma_vu = 1.4826 * np.median(np.fabs(np_vel_up_cln - med_vu))

            # empirical factor for correlated noise
            ef = 3.

            sigma_vn = 1.2533 * med_sigma_vn / np.sqrt(fabs_vn.shape[0]) * ef
            sigma_ve = 1.2533 * med_sigma_ve / np.sqrt(fabs_ve.shape[0]) * ef
            sigma_vu = 1.2533 * med_sigma_vu / np.sqrt(fabs_vu.shape[0]) * ef

            # final med_vel

            med_vel = np.array(
                [med_vn, med_ve, med_vu, sigma_vn, sigma_ve, sigma_vu])

        else:
            # time series has less than a year of data
            # velocity is set to 0.
            med_vel = np.array([0., 0., 0.])

    # end case 1-yr

    elif (isinstance(delta_day, int) and delta_day == 0):

        ###########################################################################
        # case campaign, close to relaxed method in MIDAS
        ###########################################################################

        H_year = {}
        lvel = []

        # creates H_year arrays

        for year in np.arange(int(tmp_ts.data[0, 0]),
                              int(tmp_ts.data[-1, 0]) + 1):
            lindex = np.where(tmp_ts.data.astype(int)[:, 0] == year)

            #            tt = tmp_ts.extract_periods([float(year),float(year)+0.999999])
            #            if tt.data is not None:
            #            H_year[year] = tt.data[:,:4]
            H_year[year] = tmp_ts.data[lindex[0], :4]

        # removes years with no available data
        # H_year = {key:val for key, val in H_year.items() if val is not None}
        # calculates velocity values for all data pairs separated by more than one year
        #        while H_year != {}:

        for year_start in sorted(list(H_year.keys())):
            #            np_start = H_year[year_start]

            for year_end in sorted(list(H_year.keys())):

                ok = False

                for i in np.arange(H_year[year_end].shape[0]):
                    for j in np.arange(H_year[year_start].shape[0]):

                        # check wether the pair date includes a given offset date

                        include_offset_date = False

                        for odate in self.offsets_dates:

                            if (odate >= H_year[year_start][j, 0]) and (
                                    odate <= H_year[year_end][i, 0]):
                                include_offset_date = True

                        if not include_offset_date:

                            # displacement
                            v = (H_year[year_end][i] -
                                 H_year[year_start][j])[1:]
                            # delta_year
                            delta_year = H_year[year_end][
                                i, 0] - H_year[year_start][j, 0]
                            # append to lvel
                            if delta_year > 0.90:
                                lvel.append(v / delta_year)
                                ok = True
                                if verbose:
                                    print("-- adding %.5lf - %.5lf " %
                                          (H_year[year_start][j, 0],
                                           H_year[year_end][i, 0]))
                                    print(i, j, v / delta_year)
                                    print(H_year[year_end][i],
                                          H_year[year_start][j])
                # if some pairs have already been found, stop here to mitigate the effect of offsets
                # if ok:
                #    break

            del H_year[year_start]

        # calculates the median velocity

        np_vel = np.array(lvel)

        np_vel_north = np_vel[:, 0]
        np_vel_east = np_vel[:, 1]
        np_vel_up = np_vel[:, 2]

        med_vel = np.median(np_vel, axis=0)

        [med_vel_north, med_vel_east, med_vel_up] = med_vel

        # calculates sigma

        fabs_vn = np.fabs(np_vel_north - med_vel_north)
        fabs_ve = np.fabs(np_vel_east - med_vel_east)
        fabs_vu = np.fabs(np_vel_up - med_vel_up)

        sigma_vn = 1.4826 * np.median(fabs_vn)
        sigma_ve = 1.4826 * np.median(fabs_ve)
        sigma_vu = 1.4826 * np.median(fabs_vu)

        # removes all vel > 1.4826 * med_vel

        np_vel_north_cln = np_vel_north[np.where(fabs_vn <= 2 * sigma_vn)]
        np_vel_east_cln = np_vel_east[np.where(fabs_ve <= 2 * sigma_ve)]
        np_vel_up_cln = np_vel_up[np.where(fabs_vu <= 2 * sigma_vu)]

        # get the new vel estimates

        med_vn = np.median(np_vel_north_cln)
        med_ve = np.median(np_vel_east_cln)
        med_vu = np.median(np_vel_up_cln)

        # get the new sigma

        med_sigma_vn = 1.4826 * np.median(np.fabs(np_vel_north_cln - med_vn))
        med_sigma_ve = 1.4826 * np.median(np.fabs(np_vel_east_cln - med_ve))
        med_sigma_vu = 1.4826 * np.median(np.fabs(np_vel_up_cln - med_vu))

        # empirical factor for correlated noise
        ef = 3.

        sigma_vn = 1.2533 * med_sigma_vn / np.sqrt(fabs_vn.shape[0]) * ef
        sigma_ve = 1.2533 * med_sigma_ve / np.sqrt(fabs_ve.shape[0]) * ef
        sigma_vu = 1.2533 * med_sigma_vu / np.sqrt(fabs_vu.shape[0]) * ef

        # final med_vel

        med_vel = np.array(
            [med_vn, med_ve, med_vu, sigma_vn, sigma_ve, sigma_vu])

    else:

        ###########################################################################
        # case delta_day with integer value
        ###########################################################################

        def delta(n):
            """
            Simple delta function for integer
            """
            if not n == 0:
                return (1)
            else:
                return (0)

        # first form the day vector

        np_mjd_data = list(
            map(int, pyacs.lib.astrotime.decyear2mjd(tmp_ts.data[:, 0])))
        # so the index are
        i_np_mjd_data = np_mjd_data - np.min(np_mjd_data)

        # the void array filled with np.nan

        void = np.zeros(
            (np.max(np_mjd_data) - np.min(np_mjd_data) + 1, 3)) * np.nan

        # I fill void with the time series at existing dates

        void[i_np_mjd_data] = tmp_ts.data[:, 1:4]

        # now reshape the vector for easy pair differentiation

        # if TS = void[ : , (0,1,2) ] easy diff would be achieved by working on a array W = TS.reshape(-1,delta_day)
        # however, this requires to complete the number of lines of TS with np.nan to be able to reshape it

        CTS = np.zeros((delta_day - np.mod(void.shape[0], delta_day)) *
                       delta(np.mod(void.shape[0], delta_day))) * np.nan

        # init med_vel

        med_vel = np.array([0., 0., 0.])

        to_year = 365.25 / float(delta_day)

        for i in [0, 1, 2]:
            med_vel[i] = np.nanmedian(
                np.diff(np.append(void[:, i], CTS).reshape(-1, delta_day).T,
                        axis=1)) * to_year

    ###########################################################################
    # return detrended time series
    ###########################################################################

    new_gts = self.remove_velocity(med_vel)
    new_gts.outliers = self.outliers
    new_gts.offsets_values = self.offsets_values
    new_gts.velocity = med_vel

    #    if in_place:
    #            self.velocity = new_gts.velocity
    #            return( self )
    #    else:
    #        return( new_gts )

    return (self.remove_velocity(med_vel, in_place=in_place))
Esempio n. 16
0
def plot(self,\
         title=None,\
         loffset=True,\
         loutliers=True,\
         verbose=False,\
         date=[],\
         yaxis=None, \
         yupaxis=None, \
         lcomponent=['N','E','U'],\
         error_scale=1.0, \
         lperiod=[[]],\
         lvline=[],\
         save_dir_plots='.', \
         save=None,\
         show=True,\
         unit='mm',\
         date_unit='decyear', \
         date_ref=0.0, center=True,\
         superimposed=None, \
         superimposed_equal_date=None, \
         plot_size=None, \
         info = [], \
         **kwargs):
###############################################################################
    """
    Create a plot of a North-East-Up time series and related info (offsets, outliers) using Matplotlib
    Coordinates of the time series are assumed to be in meters
    default plots units will be mm; Use unit='m' to get meters instead
    
    :param title: string to be added to the site name as a plot title
    :param loffset: boolean
                     print a dash vertical line at offset dates
    :param loutliers: boolean
                     print outliers
    :param verbose: boolean
                     verbose mode
    :param date: [sdate,edate]
                     start and end date for plots
                     sdate and edate in decimal years if date_unit is either 'decyear' or 'cal', or in days if date_unit is 'days'
    :param yaxis: [min_y,max_y]
                     min and max value for the yaxis
                     if not provided automatically adjusted
    :param yupaxis: same as yaxis but applies to the up component only
    :param lcomponent: list of components to be plotted (default =['N','E','U'])
    :param error_scale: scaling factor for error bars (default = 1.0, 0 means no error bar)
    :param lperiod: list of periods to be drawn in background (color=light salmon)
    :param lvline: list of dates where vertical lines will be drawn in background (color=green)
    :param save_dir_plots: directory used for saving the plots
    :param save: name, save the plot into name, if simply True an automatic name is given
    :param show: boolean, is True show the plot
    :param unit: 'm','cm','mm', default='mm'
    :param date_unit: 'decyear' or 'cal' or 'days', default='decyear'
    :param date_ref: reference date, default=0.0
    :param center: boolean, if True the y_axis is centered around the mean value for the plotted period
    :param superimposed: if a gts is provided, it is superimposed to the master, default=None
    :param superimposed_equal_date: date at which the master and superimposed gts will be equal (default=None). date can also be a list with [date,offset_north,offset_east,offset_up]
    :param plot_size: plot size as a tuple. Default, best guess.
    :param info: info to appear in time series subtitles. A list of keywords among: 'wrms','bias','vel','period'
    :param **kwargs: any argument to be passed to plot_date (unit_date='cal') or errorbar (unit_date='decyear' or 'days')

    :note: The list of kwargs are:
      H_kwargs_plot_date={\\
                         'marker' : marker_main_symbol,\\
                         'markersize' : marker_main_size, \\
                         'markerfacecolor' : marker_main_color,\\
                         'markeredgecolor' : marker_main_color,\\
                         'markeredgewidth' : marker_main_colorlw \\
                         }
     
    H_kwargs_plot_date_superimposed={ \\
                        'color' : line_2_color,\\
                        'linewidth' : line_2_width,\\
                        'linestyle' : line_2_style,\\
                        'marker' : marker_2_symbol,\\
                        'markersize' : marker_2_size, \\
                        'markerfacecolor' : marker_2_color,\\
                        'markeredgecolor' : marker_2_color,\\
                        'markeredgewidth' : marker_2_colorlw \\
                        }
    
    
    H_kwargs_errorbar={'linewidth' : 0,\
                       'marker' : marker_main_symbol ,\
                       'markersize' : marker_main_size, \
                       'markerfacecolor' : marker_main_color,\
                       'markeredgecolor' : marker_main_color,\
                       'markeredgewidth' : marker_main_colorlw,\
                       'ecolor' : error_bar_color,\
                       'elinewidth' : error_bar_linewidth,\
                       'capsize' : error_bar_capsize }
    
    H_kwargs_errorbar_superimposed={ \
                        'color' : line_2_color,\
                        'linewidth' : line_2_width,\
                        'linestyle' : line_2_style,\
                        'marker' : marker_2_symbol,\
                        'markersize' : marker_2_size, \
                        'markerfacecolor' : marker_2_color,\
                        'markeredgecolor' : marker_2_color,\
                        'markeredgewidth' : marker_2_colorlw, \
                        'ecolor' : error_bar_color,\
                        'elinewidth' : error_bar_linewidth,\
                        'capsize' : error_bar_capsize }


    """

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone
    
    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3],__name__,self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print( error )
        return( self )
    
    
    # cdata
    
    #if not self.cdata(data=True):
    #    print '! Cannot make plot. Problem with .data attribute.'
    #    return(self)

    # deal with **kwargs for plot settings
    
    __init_kwargs()
    
    if date_unit == 'cal':
        # **kwarg for matplotlib plot_date
        for key,value in list(kwargs.items()):
            H_kwargs_plot_date[key]=value

    if (date_unit == 'days') or (date_unit == 'decyear'):
        # **kwarg for matplotlib errorbar
        for key,value in list(kwargs.items()):
            H_kwargs_errorbar[key]=value

    # we usually want the plot in mm

    if unit=='mm':to_mm=1000.0
    if unit=='cm':to_mm=100.0
    if unit=='m':to_mm=1.0

    
    # import new modules
    import matplotlib.pyplot as plt
    import matplotlib.ticker as ticker
    import pyacs.lib.astrotime
    
    # turn show to off by default
    plt.ioff()
    
    # some drawing default parameters
    params = {'legend.fontsize': 4}
    plt.rcParams.update(params)

    # For figure caption
    txt_component={}
    txt_component['N']='North'
    txt_component['E']='East'
    txt_component['U']='Up'

    # format for printing duration in subplot titles

    if date != []:duration=date[-1]-date[0]
    else:duration=self.data[-1,0]-self.data[0,0]
    
    # adjust tickers for the decila years case
    if date_unit=='decyear':        
        fmt=ticker.FormatStrFormatter('%6.1lf')
        if duration < 1.0:fmt=ticker.FormatStrFormatter('%6.2lf')
        if duration < 0.2:fmt=ticker.FormatStrFormatter('%6.3lf')
        if duration < 0.1:fmt=ticker.FormatStrFormatter('%6.4lf')
        
        plt.rcParams['axes.formatter.limits']=(-7,17)
    
    # ensure superimposed is either None or a list of gts
    
    if superimposed is not None:
        if not isinstance(superimposed,list):
            superimposed=[superimposed] 

        for agts in superimposed:
            if not isinstance(agts,Gts):
                raise TypeError
    
    #for subplot title information
    if self.code:stitle=self.code
    else:stitle=''

    # list of color for superimposed ts
    lcolor = ['r','g','c','m','y','k','b']


    if superimposed is not None:
        i=0
        for agts in superimposed:
            stitle+=' / '
            stitle+=agts.code+("-%s" % lcolor[i])
            i = i + 1
            
    if title is not None:
        stitle = stitle + ' ' + title

    # ensure lperiod is a list of list

    lperiod = __ensure_list_of_list(lperiod)

    # plot size

    if plot_size is None:
        if len(lcomponent)==1:plot_size=plot_size_1_component
        if len(lcomponent)==2:plot_size=plot_size_2_component
        if len(lcomponent)==3:plot_size=plot_size_3_component
    
    plt.figure(num=None, figsize=plot_size)

    # a small routine to select the data to be plotted depending on the component
    
    def __data_4_plot(gts, component, unit='mm'):
        if component=='N':data=gts.data[:,(0,1,4)]
        if component=='E':data=gts.data[:,(0,2,5)]
        if component=='U':data=gts.data[:,(0,3,6)]

        data[:,1:]=data[:,1:]*to_mm
        return(data)

    # handle superimposed_equal_date option
    
    if superimposed_equal_date is not None:

        center = False

        wgts=self.set_zero_at_date(superimposed_equal_date,offset=0.0)
        
        for i in np.arange( len(superimposed)):
            
            superimposed[i] = superimposed[i].set_zero_at_date(superimposed_equal_date,offset=0.0)
        
        wsuperimposed=superimposed
        
        
    else:
        wgts=self
        wsuperimposed=superimposed
        
    # Create frames
    
    
    for component in lcomponent:
        if component == 'N' and len(lcomponent)==3:
            nsubplot=311
        if component == 'E' and len(lcomponent)==3:
            nsubplot=312
        if component == 'U' and len(lcomponent)==3:
            nsubplot=313

        if component == 'N' and len(lcomponent)==2:
            nsubplot=211
        if component == 'E' and len(lcomponent)==2:
            nsubplot=212

        if len(lcomponent)==1:
            nsubplot=111
        
        # setup_save current subplot
        plt.subplot(nsubplot)

#        if date_unit=='decyear':        
#            plt.subplot(nsubplot).xaxis.set_major_formatter(fmt)

        if wgts.velocity is None:
            vel=None
        else:
            if component == 'N':vel=wgts.velocity[0]*to_mm
            if component == 'E':vel=wgts.velocity[1]*to_mm
            if component == 'U':vel=wgts.velocity[2]*to_mm

        str_title=__make_stitle(component,vel,__data_4_plot(wgts,component),unit, info=info)

        
        # plot the data

        if date_unit == 'cal':
                (xmin_subplot,xmax_subplot) = __plot_ts(plt,__data_4_plot(wgts,component),\
                        loutliers=wgts.outliers,\
                        date=date,\
                        date_unit=date_unit,\
                        ref_date=date_ref,\
                        yaxis=yaxis,\
                        center=center,\
                        superimposed=None,\
                        verbose=verbose,\
                        error_scale=error_scale,
                        **H_kwargs_plot_date)
    
        if (date_unit == 'days') or (date_unit == 'decyear'):
                (xmin_subplot,xmax_subplot) = __plot_ts(plt,__data_4_plot(wgts,component),\
                        loutliers=wgts.outliers,\
                        date=date,\
                        date_unit=date_unit,\
                        ref_date=date_ref,\
                        yaxis=yaxis,\
                        center=center,\
                        superimposed=None,\
                        verbose=verbose,\
                        error_scale=error_scale,
                        **H_kwargs_errorbar)

        # plot offset dates as vertical lines
    
        if loffset:

            if date_unit == 'days':
                if (date_ref is None) or (date_ref == 0):
                    # reference data is year.000
                    date_ref=float(int(wgts.data[0,0]))
                
                ldate_offsets_in_date_unit=pyacs.lib.astrotime.day_since_decyear(wgts.offsets_dates,date_ref)

            if date_unit == 'decyear':
                ldate_offsets_in_date_unit=np.array(wgts.offsets_dates)-date_ref
            
            if date_unit == 'cal':
                ldate_offsets_in_date_unit = __decyear2num(wgts.offsets_dates)


            for odate in ldate_offsets_in_date_unit:
                if  odate < xmax_subplot and  odate > xmin_subplot:
                    plt.axvline(x= odate ,linewidth=2, color='g', linestyle='--')

     
        
        # subplot title
        plt.title(str_title, x=0, horizontalalignment='left', fontsize= '11')
        
        # superimposed option

        if superimposed is not None:

            
            for i in np.arange(len(wsuperimposed)):

                agts = wsuperimposed[i]
                # color for agts

                H_kwargs_plot_date_superimposed['color'] = lcolor[i]
                H_kwargs_errorbar_superimposed['color'] = lcolor[i]
                

                # calendar date
            
                if date_unit == 'cal':
                        (xmin_subplot,xmax_subplot) = __plot_ts(plt,__data_4_plot( agts , component),\
                                loutliers = agts.outliers,\
                                date=date,\
                                date_unit=date_unit,\
                                ref_date=date_ref,\
                                yaxis=yaxis,\
                                center=center,\
                                superimposed=None,\
                                verbose=verbose,\
                                error_scale=error_scale,
                                **H_kwargs_plot_date_superimposed)

                # date_init is 'days' or 'decyear'
                
                if (date_unit == 'days') or (date_unit == 'decyear'):
                        (xmin_subplot,xmax_subplot) = __plot_ts(plt,__data_4_plot( agts ,component),\
                                loutliers = agts.outliers,\
                                date=date,\
                                date_unit=date_unit,\
                                ref_date=date_ref,\
                                yaxis=yaxis,\
                                center=center,\
                                superimposed=None,\
                                verbose=verbose,\
                                error_scale=error_scale,
                                **H_kwargs_errorbar_superimposed)

        # lperiod option: periods to be highlighted 
        
        if lperiod != [[]]:
            if date_unit == 'days':
                if (date_ref is None) or (date_ref == 0):
                    # reference data is year.000
                    date_ref=float(int(wgts.data[0,0]))

            __plot_lperiod(plt,lperiod,date_unit,date_ref)

        # vertical lines option
        if lvline != []:

            if date_unit == 'days':
                if (date_ref is None) or (date_ref == 0):
                    # reference data is year.000
                    date_ref=float(int(wgts.data[0,0]))
                
                ldate_vline_in_date_unit=pyacs.lib.astrotime.day_since_decyear(lvline,date_ref)

            if date_unit == 'decyear':
                ldate_vline_in_date_unit=np.array(lvline)-date_ref
            
            if date_unit == 'cal':
                ldate_vline_in_date_unit = __decyear2num(lvline)


            for odate in ldate_vline_in_date_unit:
                if  odate < xmax_subplot and  odate > xmin_subplot:
                    plt.axvline(x= odate ,linewidth=1, color='k', linestyle='-')

        
        # Y-label    
        plt.ylabel(unit)

        # Xticks
        if date_unit == 'decyear':
            plt.gca().xaxis.set_major_formatter(fmt)


    # X Label
    
    if date_unit=='decyear':
        if (date_ref is None) or (date_ref == 0.0):
            str_xlabel='year'
        else:
            str_xlabel=("decimal year since %s" %pyacs.lib.astrotime.decyear2datetime(date_ref))
    

    if date_unit=='days':
        
        if (date_ref is None) or (date_ref == 0):
            # reference data is year.000
            date_ref=float(int(wgts.data[0,0]))
        
        str_xlabel=("days since %s" %pyacs.lib.astrotime.decyear2datetime(date_ref))

    if date_unit=='cal':
        str_xlabel=("calendar date")

    
    plt.xlabel(str_xlabel)
    plt.suptitle(stitle)

    
    # tight_layout

    plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=hspace)
    #plt.tight_layout()
    
    # end of subplots

    
    # save file as png if save option is set
    
    if save is not None:

        # import
                
        import os
        import os.path
        
        # case save is a string
        
        if isinstance(save, str):
            
            # check whether save includes a path or simply a file name
            
            if os.path.sep in save:
                # save includes a path information
                fname = save
            else:
                # else
                fname = os.path.normpath(save_dir_plots+'/'+save)

        elif save:
            # save is simply set to True for automatic output file naming
                fname = os.path.normpath( save_dir_plots + '/' + self.code+'.png' )
        
        # saving output file
        
        if verbose:
            print("-- Saving file to ",fname)
        
        # creates the directory of it does not exist
        
        if os.path.sep in fname:
            os.makedirs(os.path.dirname(fname), exist_ok=True)
        
        plt.savefig(fname, dpi=150, facecolor='w', edgecolor='w', orientation='portrait', papertype='a4', format='png',transparent=False, pad_inches=0.1)
    
    # show
    if show: 
        # do not block program execution when displaying figures
        plt.ion()
        plt.show()

    # returns the Gts for pyacs convention compatibility        
    new_Gts=self.copy()
    
    return(new_Gts)
Esempio n. 17
0
def extract_dates(self, dates, tol=0.05, in_place=False, verbose=True):
    ###################################################################
    """
    Returns a time series extracted for a given list of dates
    
    :param dates: dates either as a list or  1D numpy array of decimal dates
    :param tol: date tolerance in days to assert that two dates are equal (default 0.05 day)
    :param in_place: if True, will make change in place, if False, return s a new time series
    :param verbose: boolean, verbose mode

    """

    # import
    import inspect
    import numpy as np
    import pyacs.gts

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    # working gts
    new_gts = self.copy()

    # case .data_xyz is None

    if new_gts.data_xyz is None:
        new_gts.neu2xyz(corr=True)

    else:
        # check data/data_xyz consistency
        try:
            if not new_gts.cdata(data=True):
                # raise exception
                from pyacs.gts.lib.errors import GtsCDataError
                raise GtsCDataError(inspect.stack()[0][3], __name__, self)
        except GtsCDataError as error:
            print(error)
            return (self)

    new_data = None

    # extract dates

    index = np.array(
        pyacs.gts.Gts.get_index_from_dates(dates, self.data, tol=tol))

    if verbose:
        print('-- Extracting ', index.shape[0], ' entries from Gts or code: ',
              self.code)

    if index.shape[0] > 0:
        new_data_xyz = self.data_xyz[index, :]
        new_sigma = self.data[index, 4:]
    else:
        new_data = None
        if verbose:
            print("-- time series ", self.code,
                  " does not have dates at the requested dates ")

    # handles outliers

    if new_data is not None:
        ldate_outliers = self.data[:, 0][self.outliers]
        lupdated_outliers = pyacs.gts.Gts.get_index_from_dates(ldate_outliers,
                                                               new_data,
                                                               tol=tol)
    else:
        lupdated_outliers = []

    if verbose:
        print('-- Transmitting ', len(lupdated_outliers),
              ' outliers to the extracted Gts ')

    # case observations

    new_gts.data_xyz = new_data_xyz

    # handle outliers

    ldate_outliers = self.data[:, 0][self.outliers]
    lupdated_outliers = pyacs.gts.Gts.get_index_from_dates(ldate_outliers,
                                                           new_data_xyz,
                                                           tol=0.05)

    # handles offsets_date

    upd_offsets = []
    for offset_date in self.offsets_dates:
        if offset_date >= new_data_xyz[0,
                                       0] and offset_date <= new_data_xyz[-1,
                                                                          0]:
            upd_offsets.append(offset_date)

    # handles X0,Y0,Z0

    new_gts.X0 = new_data_xyz[0, 1]
    new_gts.Y0 = new_data_xyz[0, 2]
    new_gts.Z0 = new_data_xyz[0, 3]

    # re-generate NEU time series
    new_gts.xyz2neu(corr=False)

    # re-populate the uncertainties columns
    new_gts.data[:, 4:] = new_sigma

    # offsets & outliers

    new_gts.offsets_dates = upd_offsets
    new_gts.outliers = lupdated_outliers

    if in_place:
        self = new_gts
        return (self)
    else:
        return (new_gts)
Esempio n. 18
0
def make_model(self,
               option='detrend',
               method='L2',
               loutlier=None,
               in_place=False):
    """
        Estimate linear model parameters using least squares
        input: data: Gts format
        option are: 'detrend'/'detrend_annual'/'detrend_seasonal'
        output: new Gts object: time series is now the residuals wrt to the model and its associated values (vel, annual, semi-annual etc)
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    import pyacs.lib.glinalg as glinalg
    import pyacs.lib.robustestimators as RobEst

    #    from gts_estimators import least_square

    data = np.copy(self.data)

    ### REMOVE OUTLIERS FOR LINEAR ESTIMATION
    if loutlier: data = np.delete(data, loutlier, axis=0)

    ### REMOVE OFFSET DATES OUTSIDE THE TIME SPAN OF THE TIME SERIES

    if self.offsets_dates is not None and len(self.offsets_dates) > 0:
        # keep offsets_dates only within the time series
        sel_offsets_dates = \
            [self.offsets_dates[i] for i in range(len(self.offsets_dates)) if
             (self.offsets_dates[i] > self.data[0, 0] and self.offsets_dates[i] < self.data[-1, 0])]
        noffset = len(sel_offsets_dates)

        ### offsets_values = [time_offsets offsets_NEU s_offsets_NEU]
        offsets_values = np.zeros((noffset, 7))
        offsets_values[:, 0] = self.offsets_dates
    else:
        noffset = 0
        offsets_values = None

    # REF DATES

    t_ref = self.data[0, 0]
    t_ref_seasonal = 2010.0

    # INDEX
    if option == 'detrend_seasonal':
        del_index = []
        n_default_unknown = 6
    elif option == 'detrend_annual':
        del_index = [4, 5]
        n_default_unknown = 4
    elif option == 'detrend':
        del_index = [2, 3, 4, 5]
        n_default_unknown = 2
    else:
        print(
            '    ERROR!!! check the option of estimation: detrend/detrend_seasonal/detrend_annual'
        )

    # INIT VEL, ANNUAL, SEMI_ANNUAL, RESIDUALS ARRAYS
    ### vel = [vel_N vel_E vel_U svel_N s_vel_E svel_U]
    vel = np.zeros(6)
    ### annual = [amplitude_NEU phase_NEU]
    annual = []
    ### semi_annual = [amplitude_NEU phase_NEU]
    semi_annual = []

    residuals = np.zeros(data.shape)
    residuals[:, 0] = data[:, 0]

    ndate = len(data[:, 0])

    # BUILD LINEAR SYSTEM

    for k in range(1, 4):

        ## write matrix A in general case
        A = np.zeros([ndate, (6 + noffset)], float)
        for i in range(ndate):
            ti = data[i, 0]
            A[i, 0], A[i, 1], A[i, 2], A[i, 3], A[i, 4], A[i, 5] = 1., (ti - t_ref), \
                                                                   np.cos(2. * np.pi * (ti - t_ref_seasonal)), np.sin(
                2. * np.pi * (ti - t_ref_seasonal)), \
                                                                   np.cos(4. * np.pi * (ti - t_ref_seasonal)), np.sin(
                4. * np.pi * (ti - t_ref_seasonal))
            ## for offsets
            for j in range(noffset):
                if ti > self.offsets_dates[j]: A[i, (6 + j)] = 1.

        ### take the design matrix
        A = np.delete(A, del_index, axis=1)

        # solve

        (X, COV, V) = glinalg.lsw_full(A, data[:, k], data[:, k + 3])

        if method == 'L1':
            (X, V) = RobEst.Dikin(A, data[:, k], data[:, k + 3], eps=1.0E-4)

        s_X = np.sqrt(np.diag(COV))

        ## calculate residuals, predicted mb_files
        residuals[:, k] = V
        residuals[:, k + 3] = data[:, k + 3]

        ## velocity
        vel[k - 1] = X[1]
        vel[k + 2] = s_X[1]

        ## calculate the offset amplitudes
        if noffset > 0:
            offsets_values[:, k] = X[n_default_unknown:(n_default_unknown +
                                                        noffset)]
            offsets_values[:,
                           k + 3] = s_X[n_default_unknown:(n_default_unknown +
                                                           noffset)]

        if option == 'detrend_annual':
            ## calculate the annual motion: amplitude & phase
            annual.append((X[2], X[3]))

        if option == 'detrend_seasonal':
            ## calculate the annual motion: amplitude & phase
            annual.append((X[2], X[3]))
            ## calculate the annual motion: amplitude & phase
            semi_annual.append((X[4], X[5]))

    if len(annual) > 0:
        annual = np.hstack(annual)
    else:
        annual = None
    if len(semi_annual) > 0:
        semi_annual = np.hstack(semi_annual)
    else:
        semi_annual = None

    new_Gts = self.copy()

    new_Gts.offsets_values = offsets_values
    new_Gts.annual = annual
    new_Gts.semi_annual = semi_annual
    new_Gts.velocity = vel

    new_Gts.data = residuals

    if in_place:
        self = new_Gts.copy()
        del new_Gts
        return (self)
    else:
        return (new_Gts)
Esempio n. 19
0
def detrend_seasonal_median(self, wl=11, in_place=False, verbose=False):
    ###############################################################################
    """
    Calculates a velocity using the median of pair of displacements exactly separated by one year, inspired from MIDAS and then removes repeating yearly signal
    If the time series has less than three years of data, then the time series is kept untouched.

    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    import pyacs.lib.astrotime

    duration_in_year = self.data[-1, 0] - self.data[0, 0]

    if duration_in_year >= 3.:

        H_year = {}

        # creates H_year arrays

        for year in np.arange(int(self.data[0, 0]), int(self.data[-1, 0]) + 1):
            H_year[year] = np.zeros((365, 3))
            H_year[year][:, :] = np.nan

        # deal with dates

        np_mjd = pyacs.lib.astrotime.decyear2mjd(self.data[:, 0])
        (np_doy, np_year, _np_ut) = pyacs.lib.astrotime.mjd2dayno(np_mjd)

        np_doy = np_doy.astype(int)
        np_year = np_year.astype(int)

        # fill H_year arrays

        for i in np.arange(np_doy.shape[0]):
            if np_doy[i] != 366:
                H_year[np_year[i]][np_doy[i] - 1, :] = self.data[i, 1:4]

        # stack the velocities

        np_vel = np.zeros((365 * (len(H_year) - 1), 3))
        np_vel[:, :] = np.nan

        i = 0
        for year in sorted(H_year.keys())[0:-1]:
            np_vel[i * 365:(i + 1) * 365] = H_year[year + 1] - H_year[year]
            i = i + 1
        # calculates the median velocity

        med_vel = np.nanmedian(np_vel, axis=0)

        # return detrended time series

        detrended = self.remove_velocity(med_vel)

        H_year = {}

        # creates H_year arrays

        for year in np.arange(int(detrended.data[0, 0]),
                              int(detrended.data[-1, 0]) + 1):
            H_year[year] = np.zeros((365, 3))
            H_year[year][:, :] = np.nan

        # deal with dates

        np_mjd = pyacs.lib.astrotime.decyear2mjd(detrended.data[:, 0])
        (np_doy, np_year, _np_ut) = pyacs.lib.astrotime.mjd2dayno(np_mjd)

        np_doy = np_doy.astype(int)
        np_year = np_year.astype(int)

        # fill H_year arrays

        for i in np.arange(np_doy.shape[0]):
            if np_doy[i] != 366:
                H_year[np_year[i]][np_doy[i] - 1, :] = detrended.data[i, 1:4]

        # center all H_year arrays

        for year in sorted(H_year.keys()):
            H_year[year] = H_year[year] - np.nanmedian(H_year[year], axis=0)
        #            plt.plot(H_year[year][:,1])
        # create the median daily signal

        A = np.array(list(H_year.values()))

        np_doy_median_signal = np.nanmedian(A[:, :, :], axis=0)

        #        plt.plot(np_doy_median_signal[:,1],'ro')

        # run a median filter on it

        np_doy_median_signal_3 = np.vstack(
            (np_doy_median_signal, np_doy_median_signal, np_doy_median_signal))

        import scipy.signal
        np_doy_median_signal[:, 0] = scipy.signal.medfilt(
            np_doy_median_signal_3[:, 0], wl)[365:2 * 365]
        np_doy_median_signal[:, 1] = scipy.signal.medfilt(
            np_doy_median_signal_3[:, 1], wl)[365:2 * 365]
        np_doy_median_signal[:, 2] = scipy.signal.medfilt(
            np_doy_median_signal_3[:, 2], wl)[365:2 * 365]

        #        plt.plot(np_doy_median_signal[:,1],'bo')

        # remove it from the detrended time series

        detrended_seasonal = detrended.copy()

        # loop on np_doy

        for i in np.arange(detrended_seasonal.data.shape[0]):
            if np_doy[i] != 366:
                detrended_seasonal.data[i, 1:4] = detrended_seasonal.data[
                    i, 1:4] - np_doy_median_signal[np_doy[i] - 1, :]

    else:
        # time series is shorter than minimum

        detrended_seasonal = self.copy()

    return (detrended_seasonal)
Esempio n. 20
0
def cdata(self, data=False, data_xyz=False, tol=0.001, verbose=False):
    ###############################################################################
    """
    Check data/data_xyz attributes

    :param data: boolean, if True, data attribute will be checked
    :param data_xyz: boolean, if True, data_xyz attribute will be checked
    :param tol: tolerance in days for two dates to be considered as the same (default 0.001 of day)
    :param verbose: boolean, verbose mode
    
    :return : boolean, True if everything is OK, False otherwise
    
    :note : in future, this routine should also whether .data and .data_xyz value are consistent
    """

    # import
    import inspect
    import numpy as np
    from pyacs.gts.lib.errors import GtsInputDataNone, GtsInputData_xyzNone, GtsInputData_allNone
    from pyacs.gts.lib.errors import GtsInputDataTypeError, GtsInputDataBadDim, GtsInputDataBadNcolumns, GtsInputDataBadNrows
    from pyacs.gts.lib.errors import GtsInputData_xyzTypeError, GtsInputData_xyzBadDim, GtsInputData_xyzBadNcolumns, GtsInputData_xyzBadNrows
    from pyacs.gts.lib.errors import GtsInputDataDiffShape, GtsInputDataDiffDate

    # CASE EITHER data OR data_xyz where asked to be checked

    # is there the required data
    try:
        if (self.data is None) and (data):
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (False)

    # is there the required data_xyz
    try:
        if (self.data_xyz is None) and (data_xyz):
            # raise exception
            raise GtsInputData_xyzNone(inspect.stack()[0][3], __name__, self)
    except GtsInputData_xyzNone as error:
        # print PYACS WARNING
        print(error)
        return (False)

    # GENERAL CASE

    # is there some data?
    try:
        if (self.data is None) and (self.data_xyz is None):
            # raise exception
            raise GtsInputData_allNone(inspect.stack()[0][3], __name__, self)
    except GtsInputData_allNone as error:
        # print PYACS WARNING
        print(error)
        return (False)

    # .data case
    if self.data is not None:

        # .data numpy array?
        try:
            if not isinstance(self.data, np.ndarray):
                # raise exception
                raise GtsInputDataTypeError(inspect.stack()[0][3], __name__,
                                            self)
        except GtsInputDataTypeError as error:
            # print PYACS WARNING
            print(error)
            return (False)

        # .data with right dimensions?
        try:
            if self.data.ndim != 2:
                # raise exception
                raise GtsInputDataBadDim(inspect.stack()[0][3], __name__, self)
        except GtsInputDataBadDim as error:
            # print PYACS WARNING
            print(error)
            return (False)
        # .data with the right shape?
        try:
            if self.data.shape[1] not in [7, 10]:
                # raise exception
                raise GtsInputDataBadNcolumns(inspect.stack()[0][3], __name__,
                                              self)
        except GtsInputDataBadNcolumns as error:
            # print PYACS WARNING
            print(error)
            return (False)

        # .data with at least one observation?
        try:
            if self.data.shape[0] < 1:
                # raise exception
                raise GtsInputDataBadNrows(inspect.stack()[0][3], __name__,
                                           self)
        except GtsInputDataBadNrows as error:
            # print PYACS WARNING
            print(error)
            return (False)

    # .data_xyz case
    if self.data_xyz is not None:

        # .data numpy array?
        try:
            if not isinstance(self.data_xyz, np.ndarray):
                # raise exception
                raise GtsInputData_xyzTypeError(inspect.stack()[0][3],
                                                __name__, self)
        except GtsInputData_xyzTypeError as error:
            # print PYACS WARNING
            print(error)
            return (False)

        # .data with right dimensions?
        try:
            if self.data_xyz.ndim != 2:
                # raise exception
                raise GtsInputData_xyzBadDim(inspect.stack()[0][3], __name__,
                                             self)
        except GtsInputData_xyzBadDim as error:
            # print PYACS WARNING
            print(error)
            return (False)
        try:
            if self.data_xyz.shape[1] not in [7, 10]:
                # raise exception
                raise GtsInputData_xyzBadNcolumns(inspect.stack()[0][3],
                                                  __name__, self)
        except GtsInputData_xyzBadNcolumns as error:
            # print PYACS WARNING
            print(error)
            return (False)

        try:
            if self.data_xyz.shape[0] < 1:
                # raise exception
                raise GtsInputData_xyzBadNrows(inspect.stack()[0][3], __name__,
                                               self)
        except GtsInputData_xyzBadNrows as error:
            # print PYACS WARNING
            print(error)
            return (False)

    # check .data and .data_xyz consistency

    if (self.data is not None) and (self.data_xyz is not None):
        # check both have the same length
        try:
            if self.data.shape[0] != self.data_xyz.shape[0]:
                raise GtsInputDataDiffShape(inspect.stack()[0][3], __name__,
                                            self)
        except GtsInputDataDiffShape as error:
            # print PYACS WARNING
            print(error)
            return (False)

        # check both have the same dates

        try:
            if np.max(
                (self.data[:, 0] - self.data_xyz[:, 0])**2) > tol / 365.25:
                raise GtsInputDataDiffDate(inspect.stack()[0][3], __name__,
                                           self)
        except GtsInputDataDiffDate as error:
            # print PYACS WARNING
            print(error)
            return (False)

    return (True)
Esempio n. 21
0
def set_zero_at_date(self, date, offset=None, in_place=False):
    ###################################################################
    """
    make a translation of a time series, setting to 0 at a given date
    if the provided date does not exist, uses the next date available
    
    :param date: date in decimal year
    :param offset: an offset (in mm) to be added. Could be a float, a list or 1D numpy array with 3 elements 
    
    """

    # import
    import inspect
    import numpy as np

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    if offset is None:
        [cn, ce, cu] = [0.0, 0.0, 0.0]
    else:
        if isinstance(offset, float):
            [cn, ce, cu] = [offset / 1000., offset / 1000., offset / 1000.]
        elif isinstance(offset, list):
            [cn, ce,
             cu] = [offset[0] / 1000., offset[1] / 1000., offset[2] / 1000.]
        elif isinstance(offset, np.ndarray):
            [cn, ce,
             cu] = [offset[0] / 1000., offset[1] / 1000., offset[2] / 1000.]

    new_data = self.data.copy()

    lindex = np.where(new_data[:, 0] >= date)

    try:
        index = lindex[0][0]
    except:
        print("!!! bad date provided")
        return ()

    print("-- Removing ", new_data[index, 1], new_data[index, 2],
          new_data[index, 3])

    new_data[:, 1] = new_data[:, 1] - new_data[index, 1] + cn
    new_data[:, 2] = new_data[:, 2] - new_data[index, 2] + ce
    new_data[:, 3] = new_data[:, 3] - new_data[index, 3] + cu

    new_Gts = self.copy(data=new_data)

    # .data_xyz set to None
    new_Gts.data_xyz = None

    # origin XYZ would need to be changed

    if in_place:
        self.data = new_Gts.data.copy()
    return (new_Gts)
Esempio n. 22
0
def detrend(self, method='L2', in_place=False, periods=[], exclude_periods=[]):
    ###################################################################
    """
    detrends a time series and save velocity estimates in velocity attribute

    :param periods         : periods used to estimate the velocity
    :param exclude_periods : periods to be excluded for the velocity estimate
    :param in_place        : if True then replace the current time series
    :return                : the detrended time series
    :note                  : outliers from Gts.outliers are omitted in the estimation and
    offsets given Gts.offsets_dates are estimated simultaneously

    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    # after this method .data  and .data_xyz are not consistent so .data_xyz is set to None
    self.data_xyz = None

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)
    ###########################################################################

    import copy
    outliers = copy.deepcopy(self.outliers)
    tmp_ts = self.remove_outliers()

    if periods != []:
        tmp_ts = tmp_ts.extract_periods(periods)
    if exclude_periods != []:
        tmp_ts = tmp_ts.exclude_periods(periods)

    detrended = tmp_ts.make_model(option='detrend', method=method)

    vel = detrended.velocity
    offsets_values = detrended.offsets_values

    new_gts = self.copy()
    new_gts.outliers = outliers
    new_gts.offsets_values = offsets_values
    new_gts.velocity = vel

    model = new_gts.mmodel()

    new_gts.data[:, 1:4] = new_gts.data[:, 1:4] - model.data[:, 1:4]

    if in_place:
        self.data = new_gts.data
        return (self)
    else:
        return (new_gts)
Esempio n. 23
0
def smooth(self,
           window_len=11,
           window='hanning',
           in_place=False,
           verbose=False,
           component='NEU'):
    """
    smooth a time series
    """

    import numpy as np
    from pyacs.gts.Gts import Gts
    import inspect

    ###########################################################################
    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return (self)

    ###########################################################################

    ###################################################################
    ## smoothing routines from http://wiki.scipy.org/Cookbook/SignalSmooth
    # changes numpy to np # JMN 18/07/2014
    ###################################################################

    def smooth_scipy(x, window_len=11, window='hanning'):
        """smooth the data using a window with requested size.

        This method is based on the convolution of a scaled window with the signal.
        The signal is prepared by introducing reflected copies of the signal
        (with the window size) in both ends so that transient parts are minimized
        in the begining and end part of the output signal.

        input:
            x: the input signal
            window_len: the dimension of the smoothing window; should be an odd integer
            window: the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
                flat window will produce a moving average smoothing.

        output:
            the smoothed signal

        example:

        t=linspace(-2,2,0.1)
        x=sin(t)+randn(len(t))*0.1
        y=smooth(x)

        see also:

        numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
        scipy.signal.lfilter

        TODO: the window parameter could be the window itself if an array instead of a string
        NOTE: length(output) != length(input), to correct this: return y[(window_len/2-1):-(window_len/2)] instead of just y.
        """

        if x.ndim != 1:
            raise ValueError("smooth only accepts 1 dimension arrays.")

        if x.size < window_len:
            raise ValueError(
                "Input vector needs to be bigger than window size.")

        if window_len < 3:
            return x

        if not window in [
                'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
        ]:
            raise ValueError(
                "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"
            )

        s = np.r_[x[window_len - 1:0:-1], x, x[-1:-window_len:-1]]
        # print(len(s))
        if window == 'flat':  # moving average
            w = np.ones(window_len, 'd')
        else:
            w = eval('np.' + window + '(window_len)')

        y = np.convolve(w / w.sum(), s, mode='valid')
        return y

    new_east = smooth_scipy(self.data[:, 1],
                            window_len=window_len,
                            window=window)
    new_north = smooth_scipy(self.data[:, 2],
                             window_len=window_len,
                             window=window)
    new_up = smooth_scipy(self.data[:, 3],
                          window_len=window_len,
                          window=window)

    new_Gts = self.copy()

    if in_place:
        return (self)
        del new_Gts
    else:
        new_Gts.data[:, 1] = new_east[window_len // 2 -
                                      1:new_Gts.data[:, 1].shape[0] +
                                      window_len // 2 - 1]
        new_Gts.data[:, 2] = new_north[window_len // 2 -
                                       1:new_Gts.data[:, 1].shape[0] +
                                       window_len // 2 - 1]
        new_Gts.data[:, 3] = new_up[window_len // 2 -
                                    1:new_Gts.data[:, 1].shape[0] +
                                    window_len // 2 - 1]
        return (new_Gts)
Esempio n. 24
0
def displacement(self,
                 sdate=None,
                 edate=None,
                 window=None,
                 method='median',
                 speriod=[],
                 eperiod=[],
                 rounding='day',
                 verbose=True):
    ###################################################################
    """
    Calculates displacements between two dates or two periods

    :param sdate: start date in decimal year
    :param edate: start date in decimal year
    :param window: time window in days for searching available dates
    :param method: method to calculate the position. 'median' or 'mean'. default is 'median'.
    :param speriod: period for calculating the start position
    :param eperiod: period for calculating the end position
    :param rounding: rounding for dates. Choose among 'day','hour','minute' or 'second'. default is 'day'.
    :param verbose: verbose mode
    :return: displacement as np.array([dn,de,du,sdn,sde,sdu])
    """

    # import
    import inspect
    import numpy as np
    import pyacs.lib.astrotime as at
    from colors import red

    # check consistency of passed arguments
    if (sdate is not None) and (speriod != []):
        print(red("[ERROR] provide sdate or speriod not both"))
    if (edate is not None) and (eperiod != []):
        print(red("[ERROR] provide edate or eperiod not both"))

    # check data is not None
    from pyacs.gts.lib.errors import GtsInputDataNone

    try:
        if self.data is None:
            # raise exception
            raise GtsInputDataNone(inspect.stack()[0][3], __name__, self)
    except GtsInputDataNone as error:
        # print PYACS WARNING
        print(error)
        return ()

    # convert dates to seconds
    np_seconds = at.decyear2seconds(self.data[:, 0], rounding=rounding)

    # convert window to seconds
    if window is not None:
        window_s = int(window * 86400.)
    else:
        window_s = 1

    # fills speriod and eperiod

    if speriod == []:
        speriod = [
            at.decyear2seconds(sdate, rounding=rounding) - window_s,
            at.decyear2seconds(sdate, rounding=rounding) + window_s
        ]
    else:
        speriod = [
            at.decyear2seconds(speriod[0], rounding=rounding) - window_s,
            at.decyear2seconds(speriod[1], rounding=rounding) + window_s
        ]

    if eperiod == []:
        eperiod = [
            at.decyear2seconds(edate, rounding=rounding) - window_s,
            at.decyear2seconds(edate, rounding=rounding) + window_s
        ]
    else:
        eperiod = [
            at.decyear2seconds(eperiod[0], rounding=rounding) - window_s,
            at.decyear2seconds(eperiod[1], rounding=rounding) + window_s
        ]

    # get values
    lindex = np.argwhere((np_seconds >= speriod[0])
                         & (np_seconds <= speriod[1]))
    np_start = self.data[lindex, 1:7].reshape(-1, 6)

    lindex = np.argwhere((np_seconds >= eperiod[0])
                         & (np_seconds <= eperiod[1]))
    np_end = self.data[lindex, 1:7].reshape(-1, 6)

    if method == 'median':
        pos_sdate = np.median(np_start, axis=0)
        pos_edate = np.median(np_end, axis=0)
    else:
        pos_sdate = np.mean(np_start, axis=0)
        pos_edate = np.mean(np_end, axis=0)

    disp = pos_edate[:3] - pos_sdate[:3]
    std_disp = np.sqrt(pos_sdate**2 + pos_edate**2)[3:7]

    displacement = [
        disp[0], disp[1], disp[2], std_disp[0], std_disp[1], std_disp[2]
    ]

    return (np.array(displacement))