コード例 #1
0
ファイル: test_utils.py プロジェクト: kerfoot/GUTILS
 def test_interpolate_gps(self):
     est_lat, est_lon = interpolate_gps(timestamps=masked_epoch(self.df.t),
                                        latitude=self.df.y,
                                        longitude=self.df.x)
     assert len(est_lat) == len(est_lon)
     assert len(est_lat) == self.df.y.size
     assert len(est_lon) == self.df.x.size
コード例 #2
0
ファイル: test_utils.py プロジェクト: kerfoot/GUTILS
    def test_density(self):
        sr = SlocumReader(ctd_filepath)
        df = sr.standardize()

        salinity = calculate_practical_salinity(
            sr.data.sci_water_cond,
            sr.data.sci_water_temp,
            sr.data.sci_water_pressure,
        )
        assert sr.data.sci_m_present_time.size == salinity.size

        est_lat, est_lon = interpolate_gps(timestamps=masked_epoch(df.t),
                                           latitude=df.y,
                                           longitude=df.x)

        density = calculate_density(sr.data.sci_water_temp,
                                    sr.data.sci_water_pressure, salinity,
                                    est_lat, est_lon)
        assert sr.data.sci_m_present_time.size == density.size
コード例 #3
0
    def standardize(self, gps_prefix=None):

        df = self.data.copy()

        # Convert NMEA coordinates to decimal degrees
        for col in df.columns:
            # Ignore if the m_gps_lat and/or m_gps_lon value is the default masterdata value
            if col.endswith('_lat'):
                df[col] = df[col].map(lambda x: get_decimal_degrees(x)
                                      if x <= 9000 else np.nan)
            elif col.endswith('_lon'):
                df[col] = df[col].map(lambda x: get_decimal_degrees(x)
                                      if x < 18000 else np.nan)

        # Standardize 'time' to the 't' column
        for t in self.TIMESTAMP_SENSORS:
            if t in df.columns:
                df['t'] = pd.to_datetime(df[t], unit='s')
                break

        # Interpolate GPS coordinates
        if 'm_gps_lat' in df.columns and 'm_gps_lon' in df.columns:

            df['drv_m_gps_lat'] = df.m_gps_lat.copy()
            df['drv_m_gps_lon'] = df.m_gps_lon.copy()

            # Fill in data will nulls where value is the default masterdata value
            masterdatas = (df.drv_m_gps_lon >= 18000) | (df.drv_m_gps_lat >
                                                         9000)
            df.loc[masterdatas, 'drv_m_gps_lat'] = np.nan
            df.loc[masterdatas, 'drv_m_gps_lon'] = np.nan

            try:
                # Interpolate the filled in 'x' and 'y'
                y_interp, x_interp = interpolate_gps(masked_epoch(df.t),
                                                     df.drv_m_gps_lat,
                                                     df.drv_m_gps_lon)
            except (ValueError, IndexError):
                L.warning("Raw GPS values not found!")
                y_interp = np.empty(df.drv_m_gps_lat.size) * np.nan
                x_interp = np.empty(df.drv_m_gps_lon.size) * np.nan

            df['y'] = y_interp
            df['x'] = x_interp
        """
        ---- Option 1: Always calculate Z from pressure ----
        It's really a matter of data provider preference and varies from one provider to another.
        That being said, typically the sci_water_pressure or m_water_pressure variables, if present
        in the raw data files, will typically have more non-NaN values than m_depth.  For example,
        all MARACOOS gliders typically have both m_depth and sci_water_pressure contained in them.
        However, m_depth is typically heavily decimated while sci_water_pressure contains a more
        complete pressure record.  So, while we transmit both m_depth and sci_water_pressure, I
        calculate depth from pressure & (interpolated) latitude and use that as my NetCDF depth
        variable. - Kerfoot
        """
        # Search for a 'pressure' column
        for p in self.PRESSURE_SENSORS:
            if p in df.columns:
                # Convert bar to dbar here
                df['pressure'] = df[p].copy() * 10
                # Calculate depth from pressure and latitude
                # Negate the results so that increasing values note increasing depths
                df['z'] = -z_from_p(df.pressure, df.y)
                break

        if 'z' not in df and 'pressure' not in df:
            # Search for a 'z' column
            for p in self.DEPTH_SENSORS:
                if p in df.columns:
                    df['z'] = df[p].copy()
                    # Calculate pressure from depth and latitude
                    # Negate the results so that increasing values note increasing depth
                    df['pressure'] = -p_from_z(df.z, df.y)
                    break
        # End Option 1
        """
        ---- Option 2: Use raw pressure/depth data that was sent across ----
        # Standardize to the 'pressure' column
        for p in self.PRESSURE_SENSORS:
            if p in df.columns:
                # Convert bar to dbar here
                df['pressure'] = df[p].copy() * 10
                break

        # Standardize to the 'z' column
        for p in self.DEPTH_SENSORS:
            if p in df.columns:
                df['z'] = df[p].copy()
                break

        # Don't calculate Z from pressure if a metered depth column exists already
        if 'pressure' in df and 'z' not in df:
            # Calculate depth from pressure and latitude
            # Negate the results so that increasing values note increasing depths
            df['z'] = -z_from_p(df.pressure, df.y)

        if 'z' in df and 'pressure' not in df:
            # Calculate pressure from depth and latitude
            # Negate the results so that increasing values note increasing depth
            df['pressure'] = -p_from_z(df.z, df.y)
        # End Option 2
        """

        rename_columns = {
            'm_water_vx': 'u_orig',
            'm_water_vy': 'v_orig',
        }

        # These need to be standardize so we can compute salinity and density!
        for vname in self.TEMPERATURE_SENSORS:
            if vname in df.columns:
                rename_columns[vname] = 'temperature'
                break
        for vname in self.CONDUCTIVITY_SENSORS:
            if vname in df.columns:
                rename_columns[vname] = 'conductivity'
                break

        # Standardize columns
        df = df.rename(columns=rename_columns)

        # Compute additional columns
        df = self.compute(df)

        return df