예제 #1
0
def print_residuals(NetworkCode, StationCode, residuals, lat, lon, components=('N', 'E', 'U')):

    # check if sending NEU or XYZ
    if components[0] == 'X':
        cresiduals = ct2lg(residuals[0], residuals[1], residuals[2], lat, lon)
        ccomponent = ('N', 'E', 'U')
    else:
        cresiduals = lg2ct(residuals[0], residuals[1], residuals[2], lat, lon)
        ccomponent = ('X', 'Y', 'Z')

    r = ''
    for i, c in enumerate(components):
        r = r + '    %s: ' % c + ' '.join(['%8.4f' % np.multiply(k, 1000) for k in residuals[i]]) + \
            ' %s: ' % ccomponent[i] + ' '.join(['%8.4f' % np.multiply(k, 1000) for k in cresiduals[i]]) + '\n'

    tqdm.write(' -- %s.%s\n' % (NetworkCode, StationCode) + r)
예제 #2
0
    def parse_summary(self):

        self.summary = ''.join(self.out)

        self.ppp_version = re.findall(r'.*Version\s+(\d.\d+)\/', self.summary)

        if len(self.ppp_version) == 0:
            self.ppp_version = re.findall(r'.*CSRS-PPP ver.\s+(\d.\d+)\/', self.summary)[0]
        else:
            self.ppp_version = self.ppp_version[0]

        self.file_summary = self.get_text(self.summary, 'SECTION 1.', 'SECTION 2.')
        self.proc_parameters = self.get_text(self.summary, 'SECTION 2. ', ' SECTION 3. ')
        self.observation_session = self.get_text(self.summary,
                                                 '3.2 Observation Session', '3.3 Coordinate estimates')
        self.coordinate_estimate = self.get_text(self.summary,
                                                 '3.3 Coordinate estimates', '3.4 Coordinate differences ITRF')
        self.clock_estimates = self.get_text(self.summary,
                                             '3.5 Receiver clock estimates', '3.6 Observation rejection table')

        if self.strict and not self.check_phase_center(self.proc_parameters):
            raise pyRunPPPException(
                'Error while running PPP: could not find the antenna and radome in antex file. '
                'Check RINEX header for formatting issues in the ANT # / TYPE field. RINEX header follows:\n' + ''.join(
                    self.rinex.get_header()))

        if self.strict and not self.check_otl(self.proc_parameters):
            raise pyRunPPPException(
                'Error while running PPP: could not find the OTL coefficients. '
                'Check RINEX header for formatting issues in the APPROX ANT POSITION field. If APR is too far from OTL '
                'coordinates (declared in the HARPOS or BLQ format) NRCAN will reject the coefficients. '
                'OTL coefficients record follows:\n' + self.otl_coeff)

        if not self.check_eop(self.file_summary):
            raise pyRunPPPExceptionEOPError('EOP returned NaN in Pole XYZ.')

        # parse rejected and accepted observations
        self.processed_obs, self.rejected_obs = self.get_pr_observations(self.observation_session, self.kinematic)

        if self.processed_obs == 0:
            raise pyRunPPPExceptionZeroProcEpochs('PPP returned zero processed epochs')

        # if self.strict and (self.processed_obs == 0 or self.rejected_obs > 0.95 * self.processed_obs):
        #    raise pyRunPPPExceptionTooFewAcceptedObs('The processed observations (' + str(self.processed_obs) +
        #                                             ') is zero or more than 95% of the observations were rejected (' +
        #                                             str(self.rejected_obs) + ')')

        # FRAME now comes from the startup process, where the function Utils.determine_frame is called
        # self.frame = self.get_frame(self.coordinate_estimate)

        self.x, self.y, self.z = self.get_xyz(self.coordinate_estimate)
        self.lat, self.lon, self.h = ecef2lla([self.x, self.y, self.z])

        self.sigmax, self.sigmay, self.sigmaz, \
            self.sigmaxy, self.sigmaxz, self.sigmayz = self.get_sigmas(self.coordinate_estimate, self.kinematic)

        self.clock_phase, self.clock_phase_sigma, \
            self.phase_drift, self.phase_drift_sigma, \
            self.clock_rms, self.clock_rms_number = self.get_clock(self.clock_estimates, self.kinematic)

        # not implemented in PPP: apply NE offset if is NOT zero
        if self.rinex.antOffsetN != 0.0 or self.rinex.antOffsetE != 0.0:
            dx, dy, dz = lg2ct(numpy.array(self.rinex.antOffsetN), numpy.array(self.rinex.antOffsetE),
                               numpy.array([0]), self.lat, self.lon)
            # reduce coordinates
            self.x -= dx[0]
            self.y -= dy[0]
            self.z -= dz[0]
            self.lat, self.lon, self.h = ecef2lla([self.x, self.y, self.z])
예제 #3
0
    def remove_common_modes(self, target_periods=None, use_stations=None):

        if target_periods is None:
            tqdm.write(' >> Removing periodic common modes...')

            # load all the periodic terms
            etm_objects = self.cnn.query_float('SELECT etmsv2."NetworkCode", etmsv2."StationCode", stations.lat, '
                                               'stations.lon, '
                                               'frequencies as freq, params FROM etmsv2 '
                                               'LEFT JOIN stations ON '
                                               'etmsv2."NetworkCode" = stations."NetworkCode" AND '
                                               'etmsv2."StationCode" = stations."StationCode" '
                                               'WHERE "object" = \'periodic\' AND soln = \'gamit\' '
                                               'AND frequencies <> \'{}\' '
                                               'ORDER BY etmsv2."NetworkCode", etmsv2."StationCode"', as_dict=True)
        else:
            tqdm.write(' >> Inheriting periodic components...')

            # load the periodic terms of the stations that will produce the inheritance
            etm_objects = self.cnn.query_float('SELECT etmsv2."NetworkCode", etmsv2."StationCode", stations.lat, '
                                               'stations.lon, '
                                               'frequencies as freq, params FROM etmsv2 '
                                               'LEFT JOIN stations ON '
                                               'etmsv2."NetworkCode" = stations."NetworkCode" AND '
                                               'etmsv2."StationCode" = stations."StationCode" '
                                               'WHERE "object" = \'periodic\' AND soln = \'gamit\' '
                                               'AND frequencies <> \'{}\' AND etmsv2."NetworkCode" || \'.\' || '
                                               'etmsv2."StationCode" IN (\'%s\') '
                                               'ORDER BY etmsv2."NetworkCode", etmsv2."StationCode"'
                                               % '\', \''.join(use_stations), as_dict=True)

        # load the frequencies to subtract
        frequencies = self.cnn.query_float('SELECT frequencies FROM etmsv2 WHERE soln = \'gamit\' AND '
                                           'object = \'periodic\' '
                                           'AND frequencies <> \'{}\' GROUP BY frequencies', as_dict=True)

        # get the unique list of frequencies
        f_vector = []

        for freq in frequencies:
            f_vector += [f for f in freq['frequencies']]

        f_vector = np.array(list(set(f_vector)))

        # initialize the vectors
        ox = np.zeros((len(f_vector), len(etm_objects), 2))
        oy = np.zeros((len(f_vector), len(etm_objects), 2))
        oz = np.zeros((len(f_vector), len(etm_objects), 2))

        for s, p in enumerate(etm_objects):

            tqdm.write(' -- Periodic parameters for %s.%s' % (p['NetworkCode'], p['StationCode']))

            if target_periods:
                n = []
                e = []
                u = []
                # inheritance invoked! we want to remove the difference between current periodic terms and target
                # terms from the parent frame
                for i in (0, 1):
                    # i is a var to select the sin and cos terms from the target_periods structure
                    for f in p['freq']:
                        t = target_periods[p['StationCode']]['%.3f' % (1 / f)]
                        n.append(t['n'][i])
                        e.append(t['e'][i])
                        u.append(t['u'][i])

                params = np.array(p['params']) - np.array([n, e, u]).flatten()
            else:
                # no inheritance: make a vector of current periodic terms to be removed as common modes
                params = np.array(p['params'])

            params = params.reshape((3, params.shape[0] / 3))
            param_count = params.shape[1] / 2

            # convert from NEU to XYZ
            for j in range(params.shape[1]):
                params[:, j] = np.array(lg2ct(params[0, j], params[1, j], params[2, j],
                                              p['lat'], p['lon'])).flatten()

            for i, f in enumerate(p['freq']):
                ox[f_vector == f, s] = params[0, i:i + param_count + 1:param_count]
                oy[f_vector == f, s] = params[1, i:i + param_count + 1:param_count]
                oz[f_vector == f, s] = params[2, i:i + param_count + 1:param_count]

        # build the design matrix using the stations involved in inheritance or all stations if no inheritance
        sql_where = ','.join(["'" + stn['NetworkCode'] + '.' + stn['StationCode'] + "'" for stn in etm_objects])

        x = self.cnn.query_float('SELECT 0, -auto_z*1e-9, auto_y*1e-9, 1, 0, 0 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)

        y = self.cnn.query_float('SELECT auto_z*1e-9, 0, -auto_x*1e-9, 0, 1, 0 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)

        z = self.cnn.query_float('SELECT -auto_y*1e-9, auto_x*1e-9, 0, 0, 0, 1 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)
        Ax = np.array(x)
        Ay = np.array(y)
        Az = np.array(z)

        A = np.row_stack((Ax, Ay, Az))

        # loop through the frequencies
        for freq in f_vector:
            for i, cs in enumerate((np.sin, np.cos)):
                L = np.row_stack((ox[f_vector == freq, :, i].flatten(),
                                  oy[f_vector == freq, :, i].flatten(),
                                  oz[f_vector == freq, :, i].flatten())).flatten()

                c = np.linalg.lstsq(A, L, rcond=-1)[0]

                # loop through all the polyhedrons
                for poly in tqdm(self, ncols=160, desc=' -- Applying transformation -> %s(2 * pi * 1/%.2f)' %
                                                       (cs.__name__, np.divide(1., freq))):

                    # subtract the inverted common modes
                    poly.vertices['x'] = poly.vertices['x'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.Ax, c)
                    poly.vertices['y'] = poly.vertices['y'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.Ay, c)
                    poly.vertices['z'] = poly.vertices['z'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.Az, c)

        tqdm.write(' -- Done!')
예제 #4
0
    def align_spaces(self, target_dict):

        # get the list of stations to use during the alignment
        use_stations = target_dict.keys()

        # reference date used to align the stack
        # epochs SHOULD all be the same. Get first item and then the epoch
        ref_date = Date(fyear=target_dict.values()[0]['epoch'])

        # convert the target dict to a list
        target_list = []
        stack_list = []

        tqdm.write(' >> Aligning coordinate space...')
        for stn in use_stations:
            if not np.isnan(target_dict[stn]['x']):
                target_list.append((stn, target_dict[stn]['x'], target_dict[stn]['y'], target_dict[stn]['z'],
                                    ref_date.year, ref_date.doy, ref_date.fyear))
                # get the ETM coordinate for this station
                net = stn.split('.')[0]
                ssn = stn.split('.')[1]

                ts = pyETM.GamitSoln(self.cnn, self.get_station(net, ssn), net, ssn, self.name)
                etm = pyETM.GamitETM(self.cnn, net, ssn, gamit_soln=ts)
                stack_list += etm.get_etm_soln_list()

        c_array = np.array(stack_list, dtype=[('stn', 'S8'), ('x', 'float64'), ('y', 'float64'),
                                              ('z', 'float64'), ('yr', 'i4'), ('dd', 'i4'),
                                              ('fy', 'float64')])
        comb = Polyhedron(c_array, 'etm', ref_date)

        # build a target polyhedron from the target_list
        vertices = np.array(target_list, dtype=[('stn', 'S8'), ('x', 'float64'), ('y', 'float64'),
                                                ('z', 'float64'), ('yr', 'i4'), ('dd', 'i4'),
                                                ('fy', 'float64')])

        target = Polyhedron(vertices, 'target_frame', ref_date)

        # start aligning the coordinates
        tqdm.write(' -- Aligning polyhedron at %.3f (%s)' % (ref_date.fyear, ref_date.yyyyddd()))

        scale = False
        # align the polyhedron to the target
        r_before, r_after, a_stn = comb.align(target, scale=scale, verbose=True)
        # extract the Helmert parameters to apply to the rest of the polyhedrons
        # remove the scale factor
        helmert = comb.helmert

        tqdm.write(' -- Reporting coordinate space residuals (in mm) before and after frame alignment\n'
                   '         Before   After |     Before   After  ')
        # format r_before and r_after to satisfy the required print_residuals format
        r_before = r_before.reshape(3, r_before.shape[0] / 3).transpose()
        r_after = r_after.reshape(3, r_after.shape[0] / 3).transpose()

        residuals = np.stack((r_before, r_after), axis=2)

        stn_lla = []
        for i, stn in enumerate(a_stn):
            n = stn.split('.')[0]
            s = stn.split('.')[1]
            # get the lat lon of the station to report back in the json
            lla = self.cnn.query_float('SELECT lat, lon FROM stations WHERE "NetworkCode" = \'%s\' '
                                       'AND "StationCode" = \'%s\'' % (n, s))[0]
            stn_lla.append([lla[0], lla[1]])
            # print residuals to screen
            print_residuals(n, s, residuals[i], lla[0], lla[1], ['X', 'Y', 'Z'])

        # save the position space residuals
        self.position_space = {'stations': {'codes': a_stn.tolist(), 'latlon': stn_lla},
                               'residuals_before_alignment': r_before.tolist(),
                               'residuals_after_alignment': r_after.tolist(),
                               'reference_date': ref_date,
                               'helmert_transformation': comb.helmert.tolist(),
                               'comments': 'No scale factor estimated.'}

        for poly in tqdm(self, ncols=160, desc=' -- Applying coordinate space transformation'):
            if poly.date != ref_date:
                poly.align(helmert=helmert, scale=scale)

        tqdm.write(' >> Aligning velocity space...')

        # choose the stations that have a velocity
        use_stn = []
        for stn in use_stations:
            if not np.isnan(target_dict[stn]['vx']):
                use_stn.append(stn)

        # load the polynomial terms of the stations
        etm_objects = self.cnn.query_float('SELECT etms."NetworkCode", etms."StationCode", stations.lat, '
                                           'stations.lon, params FROM etms '
                                           'LEFT JOIN stations ON '
                                           'etms."NetworkCode" = stations."NetworkCode" AND '
                                           'etms."StationCode" = stations."StationCode" '
                                           'WHERE "object" = \'polynomial\' AND soln = \'gamit\' AND stack = \'%s\' '
                                           'AND etms."NetworkCode" || \'.\' || etms."StationCode" IN (\'%s\') '
                                           'ORDER BY etms."NetworkCode", etms."StationCode"'
                                           % (self.name, '\', \''.join(use_stn)), as_dict=True)

        # first, align the velocity space by finding a Helmert transformation that takes vx, vy, and vz of the stack at
        # each station and makes it equal to vx, vy, and vz of the ITRF structure

        dvx = np.zeros(len(etm_objects))
        dvy = np.zeros(len(etm_objects))
        dvz = np.zeros(len(etm_objects))

        for s, p in enumerate(etm_objects):
            stn_ts = self.get_station(p['NetworkCode'], p['StationCode'])

            self.cnn.query('DELETE FROM etms WHERE "soln" = \'gamit\' AND "NetworkCode" = \'%s\' AND '
                           '"StationCode" = \'%s\' AND stack = \'%s\' '
                           % (p['NetworkCode'], p['StationCode'], self.name))
            # save the time series
            ts = pyETM.GamitSoln(self.cnn, stn_ts, p['NetworkCode'], p['StationCode'], self.name)
            # create the ETM object
            pyETM.GamitETM(self.cnn, p['NetworkCode'], p['StationCode'], False, False, ts)

            q = self.cnn.query_float('SELECT params FROM etms '
                                     'WHERE "object" = \'polynomial\' AND soln = \'gamit\' '
                                     'AND "NetworkCode" = \'%s\' AND "StationCode" = \'%s\' AND stack = \'%s\' '
                                     % (p['NetworkCode'], p['StationCode'], self.name), as_dict=True)[0]

            params = np.array(q['params'])
            params = params.reshape((3, params.shape[0] / 3))
            # first item, i.e. params[:][0] in array is position
            # second item is velocity, which is what we are interested in
            v = np.array(lg2ct(params[0, 1], params[1, 1], params[2, 1], p['lat'], p['lon'])).flatten()
            # put the residuals in an array
            td = target_dict['%s.%s' % (p['NetworkCode'], p['StationCode'])]
            dvx[s] = v[0] - np.array(td['vx'])
            dvy[s] = v[1] - np.array(td['vy'])
            dvz[s] = v[2] - np.array(td['vz'])

        scale = False
        A = self.build_design(etm_objects, scale=scale)

        # loop through the frequencies
        L = np.row_stack((dvx.flatten(), dvy.flatten(), dvz.flatten())).flatten()

        c, _, _, _, wrms, _, it = adjust_lsq(A, L)

        tqdm.write(' -- Velocity space transformation:   ' + ' '.join(['%7.4f' % cc for cc in c]) +
                   ' wrms: %.3f it: %i' % (wrms * 1000, it))

        # loop through all the polyhedrons
        for poly in tqdm(self, ncols=160, desc=' -- Applying velocity space transformation'):
            t = np.repeat(poly.date.fyear - ref_date.fyear, poly.Ax.shape[0])

            poly.vertices['x'] = poly.vertices['x'] - t * np.dot(poly.ax(scale=scale), c)
            poly.vertices['y'] = poly.vertices['y'] - t * np.dot(poly.ay(scale=scale), c)
            poly.vertices['z'] = poly.vertices['z'] - t * np.dot(poly.az(scale=scale), c)

        tqdm.write(' -- Reporting velocity space residuals (in mm/yr) before and after frame alignment\n'
                   '         Before   After |     Before   After  ')

        dvxa = np.zeros(len(etm_objects))
        dvya = np.zeros(len(etm_objects))
        dvza = np.zeros(len(etm_objects))
        for s, p in enumerate(etm_objects):
            # redo the etm for this station
            stn_ts = self.get_station(p['NetworkCode'], p['StationCode'])

            self.cnn.query('DELETE FROM etms WHERE "soln" = \'gamit\' AND "NetworkCode" = \'%s\' AND '
                           '"StationCode" = \'%s\' AND stack = \'%s\''
                           % (p['NetworkCode'], p['StationCode'], self.name))
            # save the time series
            ts = pyETM.GamitSoln(self.cnn, stn_ts, p['NetworkCode'], p['StationCode'], self.name)
            # create the ETM object
            pyETM.GamitETM(self.cnn, p['NetworkCode'], p['StationCode'], False, False, ts)

            q = self.cnn.query_float('SELECT params FROM etms '
                                     'WHERE "object" = \'polynomial\' AND soln = \'gamit\' '
                                     'AND "NetworkCode" = \'%s\' AND "StationCode" = \'%s\' AND stack = \'%s\''
                                     % (p['NetworkCode'], p['StationCode'], self.name), as_dict=True)[0]

            params = np.array(q['params'])
            params = params.reshape((3, params.shape[0] / 3))
            # first item, i.e. params[:][0] in array is position
            # second item is velocity, which is what we are interested in
            v = np.array(lg2ct(params[0, 1], params[1, 1], params[2, 1], p['lat'], p['lon'])).flatten()
            # put the residuals in an array
            td = target_dict['%s.%s' % (p['NetworkCode'], p['StationCode'])]
            dvxa[s] = v[0] - np.array(td['vx'])
            dvya[s] = v[1] - np.array(td['vy'])
            dvza[s] = v[2] - np.array(td['vz'])

            lla = self.cnn.query_float('SELECT lat, lon FROM stations WHERE "NetworkCode" = \'%s\' '
                                       'AND "StationCode" = \'%s\'' % (p['NetworkCode'], p['StationCode']))[0]

            print_residuals(p['NetworkCode'], p['StationCode'],
                            np.array([[dvx[s], dvxa[s]], [dvy[s], dvya[s]], [dvz[s], dvza[s]]]), lla[0], lla[1],
                            ['X', 'Y', 'Z'])

        # save the position space residuals
        self.velocity_space = {'stations': {'codes': [p['NetworkCode'] + '.' + p['StationCode'] for p in etm_objects],
                                            'latlon': [[p['lat'], p['lon']] for p in etm_objects]},
                               'residuals_before_alignment':
                                   np.column_stack((dvx.flatten(), dvy.flatten(), dvz.flatten())).tolist(),
                               'residuals_after_alignment':
                                   np.column_stack((dvxa.flatten(), dvya.flatten(), dvza.flatten())).tolist(),
                               'reference_date': ref_date,
                               'helmert_transformation': c.tolist(),
                               'comments': 'Velocity space transformation.'}

        tqdm.write(' -- Done!')
예제 #5
0
    def remove_common_modes(self, target_periods=None):

        if target_periods is None:
            tqdm.write(' >> Removing periodic common modes...')

            # load all the periodic terms
            etm_objects = self.cnn.query_float('SELECT etms."NetworkCode", etms."StationCode", stations.lat, '
                                               'stations.lon, '
                                               'frequencies as freq, params FROM etms '
                                               'LEFT JOIN stations ON '
                                               'etms."NetworkCode" = stations."NetworkCode" AND '
                                               'etms."StationCode" = stations."StationCode" '
                                               'WHERE "object" = \'periodic\' AND soln = \'gamit\' AND stack = \'%s\' '
                                               'AND frequencies <> \'{}\' '
                                               'ORDER BY etms."NetworkCode", etms."StationCode"'
                                               % self.name, as_dict=True)
        else:
            use_stations = []
            for s in target_periods.keys():
                # check that the stations have not one or both periods with NaNs
                if not np.isnan(target_periods[s]['365.250']['n'][0]) and \
                        not np.isnan(target_periods[s]['182.625']['n'][0]):
                    use_stations.append(s)

            tqdm.write(' >> Inheriting periodic components...')

            # load the periodic terms of the stations that will produce the inheritance
            etm_objects = self.cnn.query_float('SELECT etms."NetworkCode", etms."StationCode", stations.lat, '
                                               'stations.lon, '
                                               'frequencies as freq, params FROM etms '
                                               'LEFT JOIN stations ON '
                                               'etms."NetworkCode" = stations."NetworkCode" AND '
                                               'etms."StationCode" = stations."StationCode" '
                                               'WHERE "object" = \'periodic\' AND soln = \'gamit\' AND stack = \'%s\' '
                                               'AND frequencies <> \'{}\' AND etms."NetworkCode" || \'.\' || '
                                               'etms."StationCode" IN (\'%s\') '
                                               'ORDER BY etms."NetworkCode", etms."StationCode"'
                                               % (self.name, '\', \''.join(use_stations)), as_dict=True)

        # load the frequencies to subtract
        frequencies = self.cnn.query_float('SELECT frequencies FROM etms WHERE soln = \'gamit\' AND '
                                           'object = \'periodic\' AND frequencies <> \'{}\' AND stack = \'%s\' '
                                           'GROUP BY frequencies' % self.name, as_dict=True)

        # get the unique list of frequencies
        f_vector = []

        for freq in frequencies:
            f_vector += [f for f in freq['frequencies']]

        f_vector = np.array(list(set(f_vector)))

        # initialize the vectors
        ox = np.zeros((len(f_vector), len(etm_objects), 2))
        oy = np.zeros((len(f_vector), len(etm_objects), 2))
        oz = np.zeros((len(f_vector), len(etm_objects), 2))

        # vector for residuals after alignment
        rx = np.zeros((len(f_vector), len(etm_objects), 2))
        ry = np.zeros((len(f_vector), len(etm_objects), 2))
        rz = np.zeros((len(f_vector), len(etm_objects), 2))

        tqdm.write(' -- Reporting periodic residuals (in mm) before %s'
                   % ('inheritance' if target_periods else 'common mode removal'))

        for s, p in enumerate(etm_objects):

            # DDG: should only activate this portion of the code if for any reason ETMs stored in database made with
            # a stack different to what is being used here
            # stn_ts = self.get_station(p['NetworkCode'], p['StationCode'])

            # self.cnn.query('DELETE FROM etms WHERE "soln" = \'gamit\' AND "NetworkCode" = \'%s\' AND '
            #                '"StationCode" = \'%s\'' % (p['NetworkCode'], p['StationCode']))
            # save the time series
            # ts = pyETM.GamitSoln(self.cnn, stn_ts, p['NetworkCode'], p['StationCode'], self.project)
            # create the ETM object
            # pyETM.GamitETM(self.cnn, p['NetworkCode'], p['StationCode'], False, False, ts)
            # REDUNDANT CALL, but leave anyways
            q = self.cnn.query_float('SELECT frequencies as freq, * FROM etms '
                                     'WHERE "object" = \'periodic\' AND soln = \'gamit\' '
                                     'AND "NetworkCode" = \'%s\' AND '
                                     '"StationCode" = \'%s\' AND stack = \'%s\''
                                     % (p['NetworkCode'], p['StationCode'], self.name), as_dict=True)[0]

            if target_periods:
                n = []
                e = []
                u = []
                # inheritance invoked! we want to remove the difference between current periodic terms and target
                # terms from the parent frame
                for k in range(2):
                    for f in q['freq']:
                        t = target_periods['%s.%s' % (p['NetworkCode'], p['StationCode'])]['%.3f' % (1 / f)]
                        n += [t['n'][k]]
                        e += [t['e'][k]]
                        u += [t['u'][k]]

                params = np.array(q['params']) - np.array([n, e, u]).flatten()
            else:
                # no inheritance: make a vector of current periodic terms to be removed as common modes
                params = np.array(q['params'])

            params = params.reshape((3, params.shape[0] / 3))
            param_count = params.shape[1] / 2

            print_residuals(p['NetworkCode'], p['StationCode'], params, p['lat'], p['lon'])

            # convert from NEU to XYZ
            for j in range(params.shape[1]):
                params[:, j] = np.array(lg2ct(params[0, j], params[1, j], params[2, j],
                                              p['lat'], p['lon'])).flatten()

            for i, f in enumerate(p['freq']):
                ox[f_vector == f, s] = params[0, i:i + param_count + 1:param_count]
                oy[f_vector == f, s] = params[1, i:i + param_count + 1:param_count]
                oz[f_vector == f, s] = params[2, i:i + param_count + 1:param_count]

        # build the design matrix using the stations involved in inheritance or all stations if no inheritance
        sql_where = ','.join(["'" + stn['NetworkCode'] + '.' + stn['StationCode'] + "'" for stn in etm_objects])

        x = self.cnn.query_float('SELECT 0, -auto_z*1e-9, auto_y*1e-9, 1, 0, 0, auto_x*1e-9 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)

        y = self.cnn.query_float('SELECT auto_z*1e-9, 0, -auto_x*1e-9, 0, 1, 0, auto_y*1e-9 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)

        z = self.cnn.query_float('SELECT -auto_y*1e-9, auto_x*1e-9, 0, 0, 0, 1, auto_z*1e-9 FROM stations WHERE '
                                 '"NetworkCode" || \'.\' || "StationCode" '
                                 'IN (%s) ORDER BY "NetworkCode", "StationCode"' % sql_where)
        Ax = np.array(x)
        Ay = np.array(y)
        Az = np.array(z)

        A = np.row_stack((Ax, Ay, Az))

        solution_vector = []

        # vector to display down-weighted stations
        st = dict()
        st['stn'] = [s['NetworkCode'] + '.' + s['StationCode'] for s in etm_objects]
        xyzstn = ['X-%s' % ss for ss in st['stn']] + ['Y-%s' % ss for ss in st['stn']] + \
                 ['Z-%s' % ss for ss in st['stn']]

        # loop through the frequencies
        for freq in f_vector:
            for i, cs in enumerate((np.sin, np.cos)):
                L = np.row_stack((ox[f_vector == freq, :, i].flatten(),
                                  oy[f_vector == freq, :, i].flatten(),
                                  oz[f_vector == freq, :, i].flatten())).flatten()

                c, _, index, _, wrms, _, it = adjust_lsq(A, L)
                # c = np.linalg.lstsq(A, L, rcond=-1)[0]

                tqdm.write(' -- Transformation for %s(2 * pi * 1/%.2f) : %s'
                           % (cs.__name__, np.divide(1., freq), ' '.join(['%7.4f' % cc for cc in c])) +
                           ' wrms: %.3f it: %i\n' % (wrms * 1000, it) +
                           '    Down-weighted station components: %s'
                           % ' '.join(['%s' % ss for ss in np.array(xyzstn)[np.logical_not(index)]]))

                # save the transformation parameters to output to json file
                solution_vector.append(['%s(2 * pi * 1/%.2f)' % (cs.__name__, np.divide(1., freq)), c.tolist()])

                # loop through all the polyhedrons
                for poly in tqdm(self, ncols=160, desc=' -- Applying transformation -> %s(2 * pi * 1/%.2f)' %
                                                       (cs.__name__, np.divide(1., freq))):

                    # subtract the inverted common modes
                    poly.vertices['x'] = poly.vertices['x'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.ax(scale=True), c)
                    poly.vertices['y'] = poly.vertices['y'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.ay(scale=True), c)
                    poly.vertices['z'] = poly.vertices['z'] - cs(2 * pi * freq * 365.25 * poly.date.fyear) * \
                                         np.dot(poly.az(scale=True), c)

        tqdm.write(' -- Reporting periodic residuals (in mm) after %s\n'
                   '       365.25  182.62  365.25  182.62  \n'
                   '       sin     sin     cos     cos       '
                   % ('inheritance' if target_periods else 'common mode removal'))

        for s, p in enumerate(etm_objects):
            # redo the etm for this station
            # DDG: etms need to be redone because we changed the stack!
            stn_ts = self.get_station(p['NetworkCode'], p['StationCode'])

            self.cnn.query('DELETE FROM etms WHERE "soln" = \'gamit\' AND "NetworkCode" = \'%s\' AND '
                           '"StationCode" = \'%s\' AND stack = \'%s\''
                           % (p['NetworkCode'], p['StationCode'], self.name))
            # save the time series
            ts = pyETM.GamitSoln(self.cnn, stn_ts, p['NetworkCode'], p['StationCode'], self.name)
            # create the ETM object
            pyETM.GamitETM(self.cnn, p['NetworkCode'], p['StationCode'], False, False, ts)

            # obtain the updated parameters
            # they should exist for sure!
            q = self.cnn.query_float('SELECT frequencies as freq, * FROM etms '
                                     'WHERE "object" = \'periodic\' AND soln = \'gamit\' '
                                     'AND "NetworkCode" = \'%s\' AND '
                                     '"StationCode" = \'%s\' AND stack = \'%s\''
                                     % (p['NetworkCode'], p['StationCode'], self.name), as_dict=True)[0]

            if target_periods:
                n = []
                e = []
                u = []
                # inheritance invoked! we want to remove the difference between current periodic terms and target
                # terms from the parent frame
                for k in range(2):
                    for f in q['freq']:
                        t = target_periods['%s.%s' % (p['NetworkCode'], p['StationCode'])]['%.3f' % (1 / f)]
                        n += [t['n'][k]]
                        e += [t['e'][k]]
                        u += [t['u'][k]]

                residuals = (np.array(q['params']) - np.array([n, e, u]).flatten())
            else:
                # residuals are the minimized frequencies
                residuals = np.array(q['params'])

            # reshape the array to NEU
            residuals = residuals.reshape((3, residuals.shape[0] / 3))
            param_count = residuals.shape[1] / 2

            print_residuals(p['NetworkCode'], p['StationCode'], residuals, p['lat'], p['lon'])

            # convert from NEU to XYZ
            for j in range(residuals.shape[1]):
                residuals[:, j] = np.array(lg2ct(residuals[0, j], residuals[1, j], residuals[2, j],
                                           p['lat'], p['lon'])).flatten()

            for i, f in enumerate(p['freq']):
                rx[f_vector == f, s] = residuals[0, i:i + param_count + 1:param_count]
                ry[f_vector == f, s] = residuals[1, i:i + param_count + 1:param_count]
                rz[f_vector == f, s] = residuals[2, i:i + param_count + 1:param_count]

        # save the position space residuals
        self.periodic_space = {'stations': {'codes': [p['NetworkCode'] + '.' + p['StationCode'] for p in etm_objects],
                                            'latlon': [[p['lat'], p['lon']] for p in etm_objects]},
                               'frequencies': f_vector.tolist(),
                               'components': ['sin', 'cos'],
                               'residuals_before_alignment': np.array([ox, oy, oz]).tolist(),
                               'residuals_after_alignment': np.array([rx, ry, rz]).tolist(),
                               'helmert_transformations': solution_vector,
                               'comments': 'Periodic space transformation. Each residual component (X, Y, Z) '
                                           'stored as X[freq, station, component]. Frequencies, stations, and '
                                           'components ordered as in respective elements.'}

        tqdm.write(' -- Done!')
예제 #6
0
    def remove_common_modes(self, cnn):

        tqdm.write(' >> Removing periodic common modes...')

        # load all the periodic terms
        etm_objects = cnn.query_float(
            'SELECT etmsv2."NetworkCode", etmsv2."StationCode", stations.lat, stations.lon, '
            'frequencies as freq, params FROM etmsv2 '
            'LEFT JOIN stations ON '
            'etmsv2."NetworkCode" = stations."NetworkCode" AND '
            'etmsv2."StationCode" = stations."StationCode" '
            'WHERE "object" = \'periodic\' AND soln = \'gamit\' '
            'AND frequencies <> \'{}\' '
            'ORDER BY etmsv2."NetworkCode", etmsv2."StationCode"',
            as_dict=True)

        # load the frequencies to subtract
        frequencies = cnn.query_float(
            'SELECT frequencies FROM etmsv2 WHERE soln = \'gamit\' AND object = \'periodic\' '
            'AND frequencies <> \'{}\' GROUP BY frequencies',
            as_dict=True)

        # get the unique list of frequencies
        f_vector = []

        for freq in frequencies:
            f_vector += [f for f in freq['frequencies']]

        f_vector = numpy.array(list(set(f_vector)))

        ox = numpy.zeros((len(f_vector), len(etm_objects), 2))
        oy = numpy.zeros((len(f_vector), len(etm_objects), 2))
        oz = numpy.zeros((len(f_vector), len(etm_objects), 2))

        for s, p in enumerate(etm_objects):
            params = numpy.array(p['params'])
            params = params.reshape((3, params.shape[0] / 3))
            param_count = params.shape[1] / 2

            # convert from NEU to XYZ
            for j in range(params.shape[1]):
                params[:, j] = numpy.array(
                    lg2ct(params[0, j], params[1, j], params[2, j], p['lat'],
                          p['lon'])).flatten()

            for i, f in enumerate(p['freq']):
                ox[f_vector == f,
                   s] = params[0, i:i + param_count + 1:param_count]
                oy[f_vector == f,
                   s] = params[1, i:i + param_count + 1:param_count]
                oz[f_vector == f,
                   s] = params[2, i:i + param_count + 1:param_count]

        # build the design matrix
        sql_where = ','.join([
            "'" + stn['NetworkCode'] + '.' + stn['StationCode'] + "'"
            for stn in etm_objects
        ])

        x = cnn.query_float(
            'SELECT 0, -auto_z, auto_y, 1, 0, 0 FROM stations WHERE "NetworkCode" || \'.\' || '
            '"StationCode" IN (%s) ORDER BY "NetworkCode", "StationCode"' %
            sql_where)

        y = cnn.query_float(
            'SELECT auto_z, 0, -auto_x, 0, 1, 0 FROM stations WHERE "NetworkCode" || \'.\' || '
            '"StationCode" IN (%s) ORDER BY "NetworkCode", "StationCode"' %
            sql_where)

        z = cnn.query_float(
            'SELECT -auto_y, auto_x, 0, 0, 0, 1 FROM stations WHERE "NetworkCode" || \'.\' || '
            '"StationCode" IN (%s) ORDER BY "NetworkCode", "StationCode"' %
            sql_where)
        Ax = numpy.array(x)
        Ay = numpy.array(y)
        Az = numpy.array(z)

        A = numpy.row_stack((Ax, Ay, Az))

        # select everybody (not just the stations with ETMs)
        x = cnn.query_float(
            'SELECT 0, -"Z", "Y", 1, 0, 0 FROM stacks WHERE "Project" = \'%s\' '
            'ORDER BY "NetworkCode", "StationCode", "FYear"' % self.name)

        y = cnn.query_float(
            'SELECT "Z", 0, -"X", 0, 1, 0 FROM stacks WHERE "Project" = \'%s\' '
            'ORDER BY "NetworkCode", "StationCode", "FYear"' % self.name)

        z = cnn.query_float(
            'SELECT -"Y", "X", 0, 0, 0, 1 FROM stacks WHERE "Project" = \'%s\' '
            'ORDER BY "NetworkCode", "StationCode", "FYear"' % self.name)

        t = cnn.query_float(
            'SELECT "FYear", "X", "Y", "Z" FROM stacks WHERE "Project" = \'%s\' '
            'ORDER BY "NetworkCode", "StationCode", "FYear"' % self.name)

        metadata = cnn.query(
            'SELECT "NetworkCode", "StationCode", "Year", "DOY" FROM stacks '
            'WHERE "Project" = \'%s\' ORDER BY "NetworkCode", "StationCode", "FYear"'
            % self.name)

        metadata = metadata.dictresult()
        AX = numpy.array(x)
        AY = numpy.array(y)
        AZ = numpy.array(z)

        t = numpy.array(t)

        for freq in f_vector:
            for i, cs in enumerate((numpy.sin, numpy.cos)):
                L = numpy.row_stack(
                    (ox[f_vector == freq, :,
                        i].flatten(), oy[f_vector == freq, :, i].flatten(),
                     oz[f_vector == freq, :, i].flatten())).flatten()

                c = numpy.linalg.lstsq(A, L, rcond=-1)[0]

                # subtract the inverted common modes
                t[:, 1] = t[:, 1] - cs(
                    2 * pi * freq * 365.25 * t[:, 0]) * numpy.dot(AX, c)
                t[:, 2] = t[:, 2] - cs(
                    2 * pi * freq * 365.25 * t[:, 0]) * numpy.dot(AY, c)
                t[:, 3] = t[:, 3] - cs(
                    2 * pi * freq * 365.25 * t[:, 0]) * numpy.dot(AZ, c)

        polyhedron = []

        for i, stn in enumerate(metadata):
            polyhedron += [{
                'NetworkCode': stn['NetworkCode'],
                'StationCode': stn['StationCode'],
                'X': t[i][1],
                'Y': t[i][2],
                'Z': t[i][3],
                'Year': stn['Year'],
                'DOY': stn['DOY'],
                'FYear': t[i][0]
            }]

        return polyhedron