Ejemplo n.º 1
0
    def _check_date_time_is_valid(self, date_time):
        """ Check that the given date time lies within the range covered by the input data

        Parameters
        ----------
        date_time : Datetime
            Datetime object to check

        Returns
        --------
         : bool
            Flag confirming whether the given date time is valid or not
        """
        ds0 = self.dataset_reader.read_dataset(self.data_file_names[0])
        data_datetime_0 = num2pydate(ds0.variables[self._time_var_name][0], units=ds0.variables[self._time_var_name].units)
        ds0.close()

        ds1 = self.dataset_reader.read_dataset(self.data_file_names[-1])
        data_datetime_1 = num2pydate(ds1.variables[self._time_var_name][-1], units=ds1.variables[self._time_var_name].units)
        ds1.close()

        if data_datetime_0 <= date_time < data_datetime_1:
            return True

        return False
Ejemplo n.º 2
0
    def get_datetime(self, dataset, time_index=None):
        """ Get FVCOM dates/times for the given dataset

        The time variable in FVCOM has the lowest precision. Instead,
        we construct the time array from the Itime and Itime2 vars,
        before then constructing datetime objects.

        Parameters
        ----------
        dataset : Dataset
            Dataset object for an FVCOM data file.

        Returns
        -------
         : list[datetime]
             If `time_index` is None, return a full list of datetime objects.

         : Datetime
        """
        time_raw = dataset.variables['Itime'][:] + dataset.variables['Itime2'][:] / 1000. / 60. / 60. / 24.
        units = dataset.variables['Itime'].units

        # Apply rounding
        # TODO - Confirm this is necessary when using Itime and Itime2?
        rounding_interval = self.config.getint("OCEAN_CIRCULATION_MODEL", "rounding_interval")

        if time_index is not None:
            datetime_raw = num2pydate(time_raw[time_index], units=units)
            return round_time([datetime_raw], rounding_interval)[0]
        else:
            datetime_raw = num2pydate(time_raw[:], units=units)
            return round_time(datetime_raw, rounding_interval)
Ejemplo n.º 3
0
def ncGetTimes(ncobj, name='time'):
    """
    Get the time data from a netcdf file.

    :param  ncobj: :class:`netCDF4.Dataset` or :class:`netCDF4.Group` instance.
    :param str name: Name of the time variable.

    :return times: Array of time dimension values as true Python :class:`datetime` objects.
    :rtype: :class:`numpy.ndarray` of :class:`datetime` objects

    """

    from datetime import datetime
    from cftime import num2pydate

    if hasattr(ncobj, 'Convention'):
        if getattr(ncobj, 'Convention') == "COARDS":
            # COARDS Compliant file - makes examining the data easier.
            times = ncobj.variables['time']
    elif name in ncobj.dimensions:
        times = ncobj.variables[name]
    else:
        logger.debug(f"Unknown time variable name {name}")

    if hasattr(times, 'units'):
        units = times.units
    if hasattr(times, 'calendar'):
        calendar = times.calendar
    else:
        calendar = 'standard'

    dates = num2pydate(times[:].data, units, calendar)

    return np.array(dates, dtype=datetime)
Ejemplo n.º 4
0
    def _parse(self):
        from cftime import num2pydate

        content = ReadNC(self.filename)

        for attribute_name in content.attributes:
            self.attribute_list.append(attribute_name)
            self.info.set_attribute(attribute_name,
                                    getattr(content, attribute_name))

        for parameter_name in content.parameters:
            self.parameter_list.append(parameter_name)
            setattr(self, parameter_name, getattr(content, parameter_name))

        self._n_records = len(self.longitude)

        # Get timestamp (can be either time or timestamp in l2i files)
        if hasattr(self, "time"):
            time = self.time
            time_parameter_name = "time"
        else:
            time = self.time
            time_parameter_name = "timestamp"
        self._time_parameter_name = time_parameter_name
        dt = num2pydate(time, self.time_def.units, self.time_def.calendar)
        setattr(self, "time", dt)
        self.time = self.time
Ejemplo n.º 5
0
    def __init__(self,ncfilelist,**kwargs):
        
        self.__dict__.update(kwargs)
        self.ncfilelist = ncfilelist
        self.nfiles = len(self.ncfilelist)
        print('Retrieving the time information from files...')
        
        self._timelookup = {}
        timeall = []
        #self.time = np.zeros((0,))
        
        for f in self.ncfilelist:
            print(f)
            nc = Dataset(f)
            t = nc.variables[self.timevar]
            time = num2pydate(t[:].ravel(),t.units)#.tolist()
            nc.close()
            
            #self.timelookup.update({f:time})
            timeall.append(time)

            # Create a dictionary of time and file
            for ii,tt in enumerate(time):
                tstr = datetime.strftime(tt,self.tformat)
                if tstr in self._timelookup:
                    # Overwrite the old key
                    self._timelookup[tstr]=(f,ii)
                else:
                    self._timelookup.update({tstr:(f,ii)})

        #self.time = np.asarray(self.time)
        timeall = np.array(timeall)
        self.time = np.unique(timeall)
Ejemplo n.º 6
0
def prev_year_december_data(fname, year):
    with tempfile.TemporaryDirectory() as tmpdir:
        str1 = f".{year}"
        str2 = f".{year-1}"
        fname1 = Path(fname).name.replace(str1, str2)
        fc_path = download(fname1, tmpdir)
        dec_idx = []
        dec_timestamp = []
        with netCDF4.Dataset(fc_path) as ds:
            for its, ts in enumerate(ds["time"]):
                date = cftime.num2pydate(ts, ds["time"].units)
                if date.month - 1 == 11:
                    dec_idx.append(its)
                    dec_timestamp.append(date)

            pv = np.asarray(ds["phot_veg"][dec_idx, ...], dtype=np.float32)
            npv = np.asarray(ds["nphot_veg"][dec_idx, ...], dtype=np.float32)
            soil = np.asarray(ds["bare_soil"][dec_idx, ...], dtype=np.float32)

            data = np.empty((len(dec_idx), 3, pv.shape[1], pv.shape[2]),
                            dtype=pv.dtype)
            data[:, 0, :, :] = pv
            data[:, 1, :, :] = npv
            data[:, 2, :, :] = soil
            return data, dec_timestamp
Ejemplo n.º 7
0
    def _set_time_orbit_data_group(self):
        """
        Transfer the time orbit parameter from the netcdf to l1 data object
        :return: None
        """

        # Transfer the timestamp
        # NOTE: Here it is critical that the xarray does not automatically decodes time since it is
        #       difficult to work with the numpy datetime64 date format. Better to compute datetimes using
        #       a know num2pydate conversion
        tai_datetime = num2pydate(self.nc.time_20_ku.values,
                                  units=self.nc.time_20_ku.units)
        converter = UTCTAIConverter()
        utc_timestamp = converter.tai2utc(tai_datetime, check_all=False)
        self.l1.time_orbit.timestamp = utc_timestamp

        # Set the geolocation
        self.l1.time_orbit.set_position(self.nc.lon_20_ku.values,
                                        self.nc.lat_20_ku.values,
                                        self.nc.alt_20_ku.values,
                                        self.nc.orb_alt_rate_20_ku.values)

        # Set antenna attitude
        self.l1.time_orbit.set_antenna_attitude(
            self.nc.off_nadir_pitch_angle_str_20_ku.values,
            self.nc.off_nadir_roll_angle_str_20_ku.values,
            self.nc.off_nadir_yaw_angle_str_20_ku.values)
    def load(self, dst_folder, **kwargs):
        """
        Load map diagnostic and determine map type.
        """
        # get file name without extension
        base_name = os.path.splitext(os.path.basename(self.path))[0]
        map_type = self.cube.attributes['map_type']
        map_handler = type_handling.function_mapper(map_type)
        if map_handler is None:
            raise exceptions.InvalidMapTypeException(map_type)

        unit_text = f"{format_units(self.cube.units)}"
        time_coord = self.cube.coord('time')
        time_bounds = time_coord.bounds[0]
        dates = cftime.num2pydate(time_bounds, time_coord.units.name)
        plot_title = format_title(self.cube.long_name)
        date_title = f"{dates[0].strftime('%Y')} - {dates[-1].strftime('%Y')}"
        fig = map_handler(
            self.cube,
            title=plot_title,
            dates=date_title,
            units=unit_text,
            **kwargs,
        )
        dst_file = f"./{base_name}.png"
        with ChangeDirectory(dst_folder):
            fig.savefig(dst_file, bbox_inches="tight")
            plt.close(fig)

        image_dict = {
            'title': self.cube.attributes['title'],
            'path': dst_file,
            'comment': self.cube.attributes['comment'],
        }
        return image_dict
Ejemplo n.º 9
0
    def read_content(self):

        # Open the file
        try:
            f = Dataset(self.filename)
            f.set_auto_scale(self.autoscale)
        except RuntimeError:
            msg = "Cannot read netCDF file: %s" % self.filename
            self.error.add_error("nc-runtime-error", msg)
            self.error.raise_on_error()

        # Try to update the time units
        # NOTE: This has become necessary with the use of
        #       variable epochs
        try:
            time_units = f.variables["time"].units
            self.time_def.units = time_units
        except (KeyError, AttributeError):
            pass

        # Get the global attributes
        for attribute_name in f.ncattrs():

            self.attributes.append(attribute_name)
            attribute_value = getattr(f, attribute_name)

            # Convert timestamps back to datetime objects
            # TODO: This needs to be handled better
            if attribute_name in ["start_time", "stop_time"]:
                attribute_value = num2pydate(attribute_value,
                                             self.time_def.units,
                                             calendar=self.time_def.calendar)
            setattr(self, attribute_name, attribute_value)

        # Get the variables
        if not self.global_attrs_only:
            for key in f.variables.keys():

                try:
                    variable = f.variables[key][:]
                except ValueError:
                    continue

                try:
                    is_float = variable.dtype in ["float32", "float64"]
                    has_mask = hasattr(variable, "mask")
                except:
                    is_float, has_mask = False, False

                if self.nan_fill_value and has_mask and is_float:
                    is_fill_value = np.where(variable.mask)
                    variable[is_fill_value] = np.nan

                setattr(self, key, variable)
                self.keys.append(key)
                self.parameters.append(key)
                if self.verbose:
                    print(key)
            self.parameters = f.variables.keys()
        f.close()
Ejemplo n.º 10
0
    def _set_time_orbit_data_group(self):
        """
        Transfer the time orbit parameter from the netcdf to l1 data object
        :return: None
        """

        # Transfer the timestamp
        # NOTE: Here it is critical that the xarray does not automatically decodes time since it is
        #       difficult to work with the numpy datetime64 date format. Better to compute datetimes using
        #       a know num2pydate conversion
        utc_timestamp = num2pydate(self.nc.time_20_ku.values,
                                   units=self.nc.time_20_ku.units)
        self.l1.time_orbit.timestamp = utc_timestamp

        # Set the geolocation
        self.l1.time_orbit.set_position(self.nc.lon_20_ku.values,
                                        self.nc.lat_20_ku.values,
                                        self.nc.alt_20_ku.values,
                                        self.nc.orb_alt_rate_20_ku.values)

        # Set antenna attitude
        # NOTE: This are only available in 1Hz and need to be interpolated
        time_01, time_20 = self.nc.time_01.values, self.nc.time_20_ku.values
        pitch_angle_20, stat = self.interp_1Hz_to_20Hz(
            self.nc.off_nadir_pitch_angle_pf_01.values, time_01, time_20)
        roll_angle_20, stat = self.interp_1Hz_to_20Hz(
            self.nc.off_nadir_roll_angle_pf_01.values, time_01, time_20)
        yaw_angle_20, stat = self.interp_1Hz_to_20Hz(
            self.nc.off_nadir_yaw_angle_pf_01.values, time_01, time_20)
        self.l1.time_orbit.set_antenna_attitude(pitch_angle_20, roll_angle_20,
                                                yaw_angle_20)
Ejemplo n.º 11
0
 def get_month(self, time_coord):
     """
     Returns the month of [0] in time_coord.points as a string
     """
     dt_object = cftime.num2pydate(time_coord.points[0],
                                   time_coord.units.name)
     return dt_object.strftime('%B')
Ejemplo n.º 12
0
def get_masked_datetime_array(t, tvar, mask_nan=True):
    # If we are passed in a scalar... return a scalar
    if isinstance(t, np.ma.core.MaskedConstant):
        return t
    elif np.isscalar(t):
        return num2date(t, tvar.units, getattr(tvar, 'calendar', 'standard'))

    if mask_nan is True:
        t = np.ma.masked_invalid(t)

    t_cal = getattr(tvar, 'calendar', 'standard')

    # Get the min value we can have and mask anything else
    # This is limited by **python** datetime objects and not
    # nc4 objects. The min nc4 datetime object is
    # min_date = nc4.netcdftime.datetime(-4713, 1, 1, 12, 0, 0, 40)
    # There is no max date for nc4.
    min_nums = date2num([datetime.min, datetime.max], tvar.units, t_cal)
    t = np.ma.masked_outside(t, *min_nums)

    dts = num2pydate(t, tvar.units, t_cal)
    if isinstance(dts, (datetime, cfdt)):
        dts = np.array([dts.isoformat()], dtype='datetime64')

    return dts
Ejemplo n.º 13
0
def get_band_info_for_date(target_date: dt.date) -> tuple[int, str]:
    """Return the band index and a descriptive text for the layer title."""

    def _get_data_fp_from_cache(year: int) -> Path:
        filepath = (
            FETCH_DATASETS_DIR
            / f'seaice_age.{year}'
            / f'iceage_nh_12.5km_{year}0101_{year}1231_v4.1.nc'
        )

        if not filepath.is_file():
            raise FileNotFoundError(f'Expected file {filepath} does not exist.')

        return filepath

    data_filepath = _get_data_fp_from_cache(target_date.year)
    ds = Dataset(data_filepath)
    time = ds.variables['time']

    band_dates = [real_date.date() for real_date in num2pydate(time[:], units=time.units)]

    for band_idx, start_date in enumerate(band_dates, start=1):
        end_date = start_date + dt.timedelta(days=6)

        if start_date <= target_date and target_date <= end_date:
            if start_date.month == end_date.month:
                week_str = f'{start_date:%B} {start_date:%-d}-{end_date:%-d}'
            else:
                week_str = f'{start_date:%B} {start_date:%-d}-{end_date:%B}{end_date:%-d}'

            return band_idx, week_str

    raise RuntimeError('Failed to find data matching target_date.')
Ejemplo n.º 14
0
def estimate_alpha_zhang2020(radar, band, scan_idx,
                   min_z=10, max_z=50, min_zdr=-4, max_zdr=4, min_rhohv=0.98,
                   min_r=20, max_r=120,
                   refl_field='reflectivity', zdr_field='corrected_differential_reflectivity', rhohv_field='corrected_cross_correlation_ratio',
                   isom_field='height_over_isom', temp_field='temperature', verbose=False,
                   z_offset=0, zdr_offset=0):
    
    """
    WHAT: Estimate alpha by accumulating Z - ZDR pairs across scans until the pair threshold has been reaches,
            and then fitting a slope to these pairs using _find_z_zdr_slope.
    INPUT:
        radar: pyart radar object
        alpha_dict: dictionary containing Z and ZDR pairs and alpha ts
        min_z: minimum reflectivity for pairs (float, dB)
        max_z: maximum reflectivity for pairs (float, dB)
        max_zdr: minimum differential reflectivity for pairs (float, dB)
        min_zdr: maximum differential reflectivity for pairs (float, dB)
        min_rhohv: minimum cross correlation for pairs (float)
        min_r: minimum range (km)
        max_r: maximum range (km)
        
    OUTPUT:
        alpha: alpha value (float)
    """
    
    #get radar time
    radar_starttime = cftime.num2pydate(radar.time['data'][0], radar.time['units'])
    #extract data
    t_data = radar.get_field(scan_idx, temp_field)
    z_data = radar.get_field(scan_idx, refl_field).filled() + z_offset
    zdr_data = radar.get_field(scan_idx, zdr_field).filled() + zdr_offset
    rhohv_data = radar.get_field(scan_idx, rhohv_field).filled()
    isom_data = radar.get_field(scan_idx, isom_field)
    range_vec = radar.range['data']/1000
    azi_vec = radar.get_azimuth(scan_idx)
    range_data, _ = np.meshgrid(range_vec, azi_vec)
    
    #build masks
    z_mask = np.logical_and(z_data>=min_z, z_data<=max_z)
    zdr_mask = np.logical_and(zdr_data>=min_zdr, zdr_data<=max_zdr)
    nan_mask = np.logical_and(~np.isnan(z_data), ~np.isnan(zdr_data))
    rhv_mask = rhohv_data>min_rhohv
    h_mask = isom_data==0 #below melting level
    r_mask = np.logical_and(range_data>=min_r, range_data<=max_r)
    final_mask = z_mask & zdr_mask & rhv_mask & h_mask & r_mask & nan_mask
    
    #get mean temperature of first tilt
    try:
        t_mean = np.nanmean(t_data[final_mask]) #this will crash if no valid areas
    except:
        t_mean = np.nanmean(t_data)
    

    #find alpha
    alpha, alpha_method = _find_alpha_zhang2020(z_data[final_mask], zdr_data[final_mask], band, t_mean, verbose=verbose)
    if verbose:
        print('alpha value', alpha)
                           
    return alpha, alpha_method
Ejemplo n.º 15
0
    def get_particle_data(self):
        """ Get particle data

        Particle data is read in from a NetCDF file that has been created
        using an object of type RestartFileCreator.
        """
        logger = logging.getLogger(__name__)
        logger.info('Using restart file {}'.format(self._restart_file_name))

        # Open the file for reading
        try:
            restart = Dataset(self._restart_file_name, 'r')
            logger.info('Opened data file {} for reading.'.format(
                self._restart_file_name))
        except Exception:
            logger.error('Failed to open restart file {}.'.format(
                self._restart_file_name))
            raise

        # Check time
        datetime_start_str = self._config.get("SIMULATION", "start_datetime")
        datetime_start = datetime.datetime.strptime(datetime_start_str,
                                                    "%Y-%m-%d %H:%M:%S")
        datetime_restart = num2pydate(
            restart.variables['time'][0],
            units=restart.variables['time'].units,
            calendar=restart.variables['time'].calendar)

        if datetime_start != datetime_restart:
            datetime_restart_str = datetime_restart.strftime(
                "%Y-%m-%d %H:%M:%S")
            logger.error(
                "The specified start time `{}' and restart time `{}' do not match"
                .format(datetime_start_str, datetime_restart_str))
            raise ValueError(
                "When restarting the model, the specified start time should match that given in the restart file."
            )

        # Extract particle data
        n_particles = restart.dimensions['particles'].size
        group_ids = restart.variables['group_id'][0, :]

        x1_var_name = variable_library.get_coordinate_variable_name(
            self.coordinate_system, 'x1')
        x1_positions = restart.variables[x1_var_name][0, :]

        x2_var_name = variable_library.get_coordinate_variable_name(
            self.coordinate_system, 'x2')
        x2_positions = restart.variables[x2_var_name][0, :]

        x3_var_name = variable_library.get_coordinate_variable_name(
            self.coordinate_system, 'x3')
        x3_positions = restart.variables[x3_var_name][0, :]

        restart.close()

        return n_particles, group_ids, x1_positions, x2_positions, x3_positions
Ejemplo n.º 16
0
def extract_clutter(infile, clutter_mask, refl_name="total_power"):
    """
    Extract the clutter and compute the RCA value.

    Parameters:
    -----------
    infile: str
        Input radar file.
    clutter_mask: numpy.array(float)
        Clutter mask (360 deg x 20 km)
    refl_name: str
        Uncorrected reflectivity field name.

    Returns:
    --------
    dtime: np.datetime64
        Datetime of infile
    rca: float
        95th percentile of the clutter reflectivity.
    """
    # Radar data.
    radar = _read_radar(infile, refl_name)

    dtime = cftime.num2pydate(radar.time["data"][0], radar.time["units"])

    sl = radar.get_slice(0)
    r = radar.range["data"]
    azi = radar.azimuth["data"][sl]
    try:
        refl = radar.fields[refl_name]["data"][sl][:, r < 20e3].filled(np.NaN)
    except AttributeError:
        refl = radar.fields[refl_name]["data"][sl][:, r < 20e3]
    zclutter = np.zeros_like(refl) + np.NaN

    r = r[r < 20e3]
    R, A = np.meshgrid(r, azi)
    R = (R // 1000).astype(int)
    A = (np.round(A) % 360).astype(int)

    # Mask.
    RC, AC = np.meshgrid(np.arange(20), np.arange(360))

    npos = np.where(clutter_mask)
    for ir, ia in zip(RC[npos], AC[npos]):
        pos = (R == ir) & (A == ia)
        zclutter[pos] = refl[pos]

    try:
        zclutter = zclutter[~np.isnan(zclutter)]
        rca = np.percentile(zclutter, 95)
    except IndexError:
        # Empty array full of NaN.
        raise ValueError("All clutter is NaN.")

    del radar
    return dtime, rca
Ejemplo n.º 17
0
def get_time_from_filename(filename, date):
    '''
    GET_TIME_FROM_FILENAME
    Capture the time string inside the filename and returns it.

    Parameters:
    ===========
        filename: str
            String to parse for date.
        date: str
            Date (format YYYYMMDD) to look for in files.

    Returns:
    ========
        date_time: datetime
            Datetime corresponding to given filename.
    '''
    # Looking for date followed by underscore (or not) and 6 (or 4) consecutives
    # number (i.e. the time)
    # There is maybe an optionnal character (like _) between date and time

    try:
        dtstr = re.findall(date + '.[0-9]{6}', filename)
        dtime = datetime.datetime.strptime(dtstr[0], '%Y%m%d.%H%M%S')
        return dtime
    except Exception:
        pass

    if filename[-2:] == "nc" or filename[-2:] == "NC":
        ds = xr.open_dataset(filename)
        # I wish it was simpler in python but it's not.
        dates = pd.DatetimeIndex([ds.time.values[0]])
        return dates.to_pydatetime()[0]

    if filename[-2:] == "gz" or '.RAW' in filename:
        # SIGMET file date convention.
        radar = pyart.io.read(filename)
        dtime = cftime.num2pydate(radar.time['data'][0], radar.time['units'])
        return dtime
    else:
        strlist = re.findall(date + ".?[0-9]{6}", filename)
        if len(strlist) == 0:
            strlist = re.findall(date + ".?[0-9]{4}", filename)

    try:
        date_time = parser.parse(strlist[0], fuzzy=True)
    except ValueError:
        date_time = datetime.datetime.strptime(strlist[0], "%Y%m%d")
    except IndexError:
        date_time = None

    return date_time  # Type: str
Ejemplo n.º 18
0
    def get_datetime(self, dataset, time_index=None):
        """ Get dates/times for the given dataset

        This function searches for the basic variable `time`.
        If a given source of data uses a different variable
        name or approach to saving time points, support for
        them can be added through subclassing (as with
        FVCOM) DateTimeReader.

        Parameters
        ----------
        dataset : Dataset
            Dataset object for an FVCOM data file.

        time_index : int, optional
            The time index at which to extract data. Default behaviour is to return
            the full time array as datetime objects.

        Returns
        -------
         : list[datetime]
             If `time_index` is None, return a full list of datetime objects.

         : Datetime
             If `time_index` is not None, a single datetime object.
        """
        time_raw = dataset.variables[self._time_var_name]
        units = dataset.variables[self._time_var_name].units

        # Apply rounding
        rounding_interval = self.config.getint("OCEAN_CIRCULATION_MODEL", "rounding_interval")

        if time_index is not None:
            datetime_raw = num2pydate(time_raw[time_index], units=units)
            return round_time([datetime_raw], rounding_interval)[0]
        else:
            datetime_raw = num2pydate(time_raw[:], units=units)
            return round_time(datetime_raw, rounding_interval)
Ejemplo n.º 19
0
def darwin_disdro_to_radar_moments(file_list, scatterer):

    #init lists
    DBZ_list = []
    ZDR_list = []
    KDP_list = []
    ATTEN_list = []
    RAIN_list = []
    TIME_list = []

    #read DSD data
    for infile in file_list:
        print('processing', infile)
        with netCDF4.Dataset(infile, 'r') as ncid:
            time = cftime.num2pydate(ncid['time'][:], ncid['time'].units)
            mean_diam_drop_class = ncid['mean_diam_drop_class'][:]
            num_drop = ncid['num_drop'][:]
            ndensity = ncid['nd'][:]
            liq_water = ncid['liq_water'][:]
            Z = ncid['Z'][:]
            nclambda = ncid['lambda'][:]
            n_0 = ncid['n_0'][:]
            rain = ncid['rain_rate'][:]

    #fir each sample, use number density
    print('running scattering calcs')
    cnt = 0
    for nd in ndensity:
        if np.sum(nd) == 0:
            continue
        cnt += 1

        #calc radar moments
        dbz, zdr, kdp, atten_spec = common.scatter_off_2dvd_packed(
            mean_diam_drop_class, nd, scatterer)
        DBZ_list.append(dbz)
        ZDR_list.append(zdr)
        KDP_list.append(kdp)
        ATTEN_list.append(atten_spec)
        TIME_list.append(time[cnt].date())
        RAIN_list.append(rain[cnt])

    dbz_array = np.array(DBZ_list)
    zdr_array = np.array(ZDR_list)
    kdp_array = np.array(KDP_list)
    att_array = np.array(ATTEN_list)
    rain_array = np.array(RAIN_list)
    time_array = np.array(TIME_list)

    return dbz_array, zdr_array, kdp_array, att_array, time_array, rain_array
Ejemplo n.º 20
0
def make_coord(fss, z, accum_dim):
    # a)
    accum = []
    logger.debug("accumulate coords array %s", accum_dim)
    times = False
    for fs in fss:
        zz = zarr.open_array(fs.get_mapper(accum_dim))

        try:
            import cftime
            if not isinstance(zz, cftime.real_datetime):

                # Try and get the calendar attribute from "calendar" attribute
                # If it doesn't exist, assume a standard calendar
                if zz.attrs.get("calendar") is not None:
                    calendar = zz.attrs.get("calendar", "standard")
                else:
                    calendar = 'standard'

                    # Update attrs in z[accum_dim]
                    zattr = dict(z[accum_dim].attrs)
                    zattr['calendar'] = 'standard'
                    z[accum_dim].attrs.put(zattr)            
                
                zz = cftime.num2pydate(zz[...], units=zz.attrs["units"],
                                       calendar=calendar)
                times = True
                logger.debug("converted times")
                accum.append(zz)
            else:
                accum.append(zz)
        except Exception as e:
            ex = e
            accum.append(zz[...].copy())
    attr = dict(z[accum_dim].attrs)
    if times:
        accum = [np.array(a, dtype="M8") for a in accum]
        attr.pop('units', None)
    
    attr.pop('calendar', None)

    acc = np.concatenate([np.atleast_1d(a) for a in accum]).squeeze()

    logger.debug("write coords array")
    arr = z.create_dataset(name=accum_dim,
                           data=acc,
                           overwrite=True)
    arr.attrs.update(attr)
    return len(acc)
Ejemplo n.º 21
0
    def date(self):
        """ Date array
        """
        if self._date is not None:
            return self._date

        for key, var in list(self._ds.variables.items()):
            if key in ['time', 'time_centered', 'time_ref']:
                self._date = num2pydate(var[:], units=var.units, calendar=var.calendar)

                if self._time_rounding is not None:
                    self._date = round_time(self._date, self._time_rounding)

                return self._date
        raise KeyError('Time variable not found')
    def load(self, dst_folder, **kwargs):
        """
        Load map diagnostic and determine map type.
        """
        # get file name without extension
        base_name = os.path.splitext(os.path.basename(self.path))[0]
        map_type = self.cube.attributes['map_type']
        map_handler = type_handling.function_mapper(map_type)
        if map_handler is None:
            raise exceptions.InvalidMapTypeException(map_type)

        png_dir = f"{base_name}_frames"
        number_of_time_steps = len(self.cube.coord('time').points)
        with ChangeDirectory(dst_folder):
            if not os.path.isdir(png_dir):
                os.mkdir(png_dir)
            number_of_pngs = len(os.listdir(png_dir))

        unit_text = f"{format_units(self.cube.units)}"
        dst_file = f"./{base_name}.gif"
        with ChangeDirectory(f"{dst_folder}/{png_dir}"):
            for time_step in range(number_of_pngs, number_of_time_steps):
                time_coord = self.cube.coord('time')
                time_bounds = time_coord.bounds[time_step]
                dates = cftime.num2pydate(time_bounds, time_coord.units.name)
                date_title = f"{dates[0].strftime('%Y')}"
                plot_title = format_title(self.cube.long_name)
                fig = map_handler(
                    self.cube[time_step],
                    title=plot_title,
                    dates=date_title,
                    units=unit_text,
                    **kwargs,
                )
                fig.savefig(f"./{base_name}-{time_step:03}.png",
                            bbox_inches="tight")
                plt.close(fig)
            images = []
            for file_name in sorted(os.listdir(".")):
                images.append(imageio.imread(file_name))
            imageio.mimsave(f'.{dst_file}', images, fps=2)

        image_dict = {
            'title': self.cube.attributes['title'],
            'path': dst_file,
            'comment': self.cube.attributes['comment'],
        }
        return image_dict
    def load(self, dst_folder, **kwargs):
        """
        Load time series diagnostic and call plot creator.
        """
        # get file name without extension
        base_name = os.path.splitext(os.path.basename(self.path))[0]
        dst_file = f"./{base_name}.png"

        x_coord = self.cube.coords()[0]
        if "second since" in x_coord.units.name or "hour since" in x_coord.units.name:
            dates = cftime.num2pydate(x_coord.points, x_coord.units.name)
            coord_points = format_dates(dates)
        else:
            coord_points = x_coord.points

        fig = plt.figure(figsize=(6, 4), dpi=150)
        ax = fig.add_subplot(1, 1, 1)
        ax.plot(coord_points, self.cube.data, marker='o')
        if "second since" in x_coord.units.name or "hour since" in x_coord.units.name:
            fig.autofmt_xdate()

        minor_step, major_step = self._determine_intervals(len(coord_points))
        ax.set_xticks(coord_points[minor_step - 1::major_step])
        ax.set_xticks(coord_points[minor_step - 1::minor_step], minor=True)
        ax.set_xticklabels(coord_points[minor_step - 1::major_step])

        ax.ticklabel_format(axis='y',
                            style='sci',
                            scilimits=(-3, 6),
                            useOffset=False,
                            useMathText=True)
        ax.set_ylim(kwargs.get('value_range', [None, None]))

        ax.set_title(format_title(self.cube.long_name))
        ax.set_xlabel(format_title(x_coord.name()))
        ax.set_ylabel(format_title(self.cube.long_name, self.cube.units))

        plt.tight_layout()
        with ChangeDirectory(dst_folder):
            fig.savefig(dst_file, bbox_inches="tight")
            plt.close(fig)

        image_dict = {
            'title': self.cube.attributes['title'],
            'path': dst_file,
            'comment': self.cube.attributes['comment'],
        }
        return image_dict
Ejemplo n.º 24
0
    def get_time_bounds(self, time_coord):
        """
        Get contiguous time bounds for sea ice maps

        Creates new time bounds [
            [01-01-current year, 01-01-next year],
        ]
        """
        dt_object = cftime.num2pydate(time_coord.points[0],
                                      time_coord.units.name)
        start = datetime.datetime(dt_object.year, 1, 1)
        end = datetime.datetime(start.year + 1, 1, 1)
        start_seconds = cftime.date2num(start, time_coord.units.name)
        end_seconds = cftime.date2num(end, time_coord.units.name)
        new_bounds = np.array([[start_seconds, end_seconds]])
        return new_bounds
Ejemplo n.º 25
0
def update_metadata(radar) -> dict:
    """
    Update metadata of the gridded products.

    Parameter:
    ==========
    radar: pyart.core.Grid
        Radar data.

    Returns:
    ========
    metadata: dict
        Output metadata dictionnary.
    """
    today = datetime.datetime.utcnow()
    dtime = cftime.num2pydate(radar.time["data"], radar.time["units"])

    longitude, latitude = radar.get_point_longitude_latitude(0)
    maxlon = longitude.max()
    minlon = longitude.min()
    maxlat = latitude.max()
    minlat = latitude.min()

    metadata = {
        "comment": "Gridded radar volume using Barnes et al. ROI",
        "field_names": ", ".join([k for k in radar.fields.keys()]),
        "geospatial_bounds":
        f"POLYGON(({minlon:0.6} {minlat:0.6},{minlon:0.6} {maxlat:0.6},{maxlon:0.6} {maxlat:0.6},{maxlon:0.6} {minlat:0.6},{minlon:0.6} {minlat:0.6}))",
        "geospatial_lat_max": f"{maxlat:0.6}",
        "geospatial_lat_min": f"{minlat:0.6}",
        "geospatial_lat_units": "degrees_north",
        "geospatial_lon_max": f"{maxlon:0.6}",
        "geospatial_lon_min": f"{minlon:0.6}",
        "geospatial_lon_units": "degrees_east",
        "geospatial_vertical_min": radar.origin_altitude["data"][0],
        "geospatial_vertical_max": 20000,
        "geospatial_vertical_positive": "up",
        "history":
        f"created by Joshua Soderholm on gadi.nci.org.au at {today.isoformat()} using Py-ART",
        "processing_level": "b2",
        "time_coverage_start": dtime[0].isoformat(),
        "time_coverage_end": dtime[-1].isoformat(),
        "uuid": str(uuid.uuid4()),
    }

    return metadata
Ejemplo n.º 26
0
    def retrieve_data(self, name, path, date, save_coords=False):
        # date should be datetime.datetime object

        fh = Dataset(path, mode='r')

        # Get index of day for requested day
        times = fh.variables['time'][:].data
        times = cft.num2pydate(times,
                               fh.variables['time'].units,
                               calendar='standard')

        data_index = np.argwhere(times == date)[0, 0]

        if save_coords:
            self.lons = fh.variables['lon'][:].data
            self.lats = fh.variables['lat'][:].data

        return fh.variables[name][data_index].data
Ejemplo n.º 27
0
def temperature_profile(radar):
    """
    Compute the signal-to-noise ratio as well as interpolating the radiosounding
    temperature on to the radar grid. The function looks for the radiosoundings
    that happened at the closest time from the radar. There is no time
    difference limit.
    Parameters:
    ===========
    radar:
        Py-ART radar object.
    Returns:
    ========
    z_dict: dict
        Altitude in m, interpolated at each radar gates.
    temp_info_dict: dict
        Temperature in Celsius, interpolated at each radar gates.
    """
    grlat = radar.latitude["data"][0]
    grlon = radar.longitude["data"][0]
    dtime = pd.Timestamp(
        cftime.num2pydate(radar.time["data"][0], radar.time["units"]))

    geopot_profile, temp_profile = read_era5_temperature(dtime, grlon, grlat)

    # append surface data using lowest level
    geopot_profile = np.append(geopot_profile, [0])
    temp_profile = np.append(temp_profile, temp_profile[-1])

    z_dict, temp_dict = pyart.retrieve.map_profile_to_gates(
        temp_profile, geopot_profile, radar)
    temp_dict["data"] = temp_dict["data"].astype(np.float32)

    temp_info_dict = {
        "data": temp_dict["data"],  # Switch to celsius.
        "long_name": "Sounding temperature at gate",
        "standard_name": "temperature",
        "valid_min": -100,
        "valid_max": 100,
        "units": "degrees Celsius",
        "_Least_significant_digit": 1,
        "comment": "ERA5 data date: %s" % (dtime.strftime("%Y/%m/%d")),
    }

    return z_dict, temp_info_dict
Ejemplo n.º 28
0
def _read_with_netcdf(infile, dbz_name, zdr_name, rhohv_name):
    with netCDF4.Dataset(infile, "r") as ncid:
        # Extract datetime
        volume_date = cftime.num2pydate(ncid['time'][0], ncid['time'].units)
        # Get first sweep
        sweep = ncid["sweep_start_ray_index"][:]
        stsw = sweep[0]
        edsw = sweep[1] - 1

        # Extract range and azimuth
        azi = ncid["azimuth"][stsw:edsw]
        r = ncid["range"][:]

        # Get reflectivity and ZDR.
        try:
            refl = ncid[dbz_name][stsw:edsw, :].filled(np.NaN)
            if zdr_name is not None:
                zdr = ncid[zdr_name][stsw:edsw, :].filled(np.NaN)
            else:
                zdr = None
        except KeyError:
            print(
                "Wrong RHOHV/DBZ field names provided. The field names in radar files are:"
            )
            print(radar.fields.keys())
            raise KeyError("Wrong field name provided")

        # Extract RHOHV
        try:
            rhohv = ncid[rhohv_name][stsw:edsw, :]
        except Exception:
            traceback.print_exc()
            print(
                "Problem with cross-correlation ratio field. Maybe missing? Continuing without it."
            )
            rhohv = None

        try:  # In case rhohv is a MaskedArray
            rhohv = rhohv.filled(np.NaN)
        except AttributeError:
            pass

    return volume_date, r, azi, refl, zdr, rhohv
Ejemplo n.º 29
0
    def _transfer_timeorbit(self):
        """ Extracts the time/orbit data group from the SGDR data """

        # Transfer the orbit position
        self.l1.time_orbit.set_position(self.sgdr.lon_20, self.sgdr.lat_20, self.sgdr.alt_20)

        # Transfer the timestamp
        sgdr_timestamp = self.sgdr.time_20
        units = self.cfg.sgdr_timestamp_units
        calendar = self.cfg.sgdr_timestamp_calendar
        timestamp = num2pydate(sgdr_timestamp, units, calendar)
        self.l1.time_orbit.timestamp = timestamp

        # Mandatory antenna pointing parameter (but not available for ERS)
        dummy_angle = np.full(timestamp.shape, 0.0)
        self.l1.time_orbit.set_antenna_attitude(dummy_angle, dummy_angle, dummy_angle)

        # Update meta data container
        self.l1.update_data_limit_attributes()
Ejemplo n.º 30
0
def temperature_profile_access(radar):
    """
    Return the 0C and -20C levels for MESH calculatations using access-g dataset on NCI for temperature information
    Parameters:
    ===========
    radar:
        Py-ART radar object.
    """
    grlat = radar.latitude['data'][0]
    grlon = radar.longitude['data'][0]
    dtime = pd.Timestamp(cftime.num2pydate(radar.time['data'][0], radar.time['units']))

    #build paths
    request_date = datetime.strftime(dtime, '%Y%m%d')
    request_time = str(round(dtime.hour/6)*6).zfill(2) + '00'
    if request_time == '2400':
        request_time = '0000'
    
    access_root = '/g/data/lb4/ops_aps2/access-g/0001' #access g
    access_folder = '/'.join([access_root, request_date, request_time, 'an', 'pl'])
    #build filenames
    temp_ffn = access_folder + '/air_temp.nc'
    geop_ffn = access_folder + '/geop_ht.nc'
    if not os.path.isfile(temp_ffn):
        raise FileNotFoundError(f'{temp_ffn}: no such file for temperature.')
    if not os.path.isfile(geop_ffn):
        raise FileNotFoundError(f'{geop_ffn}: no such file for geopotential.')
    #extract data
    temp_ds = xr.open_dataset(temp_ffn)
    temp_profile = temp_ds.air_temp.sel(lon=grlon, method='nearest').sel(lat=grlat, method='nearest').data[0] - 273.15 #units: deg C
    geop_ds = xr.open_dataset(geop_ffn)
    geopot_profile = geop_ds.geop_ht.sel(lon=grlon, method='nearest').sel(lat=grlat, method='nearest').data[0] #units: m
    
    #append surface data using lowest level
    geop_profile = np.append([0], geopot_profile)
    temp_profile = np.append(temp_profile[0], temp_profile)
    
    #generate temperature levels
    level_0C = _sounding_interp(temp_profile, geop_profile, 0.)
    level_minus20C = _sounding_interp(temp_profile, geop_profile, -20.)
    
    return [level_0C, level_minus20C]