Example #1
0
def period_op(ts, period="D", agg="mean", max_absent_frac=0.):
    period = pd.tseries.frequencies.to_offset(period)
    # resample getting a sum and non-null count
    ts1 = ts.resample(period).agg([agg, 'count']).copy()

    # determine required number data which is exact for period of "D" or smaller
    agged = ts1.loc[:, (slice(None), agg)].droplevel(level=1, axis=1)
    if max_absent_frac is None:
        return agged
    counts = ts1.loc[:, (slice(None), 'count')].droplevel(level=1, axis=1)
    try:
        na_tol = (period / ts.index.freq) * (1. - max_absent_frac)
        invalid = counts < na_tol
    except:
        if period == months(1):
            # determine invalid months
            na_tol = max_absent_frac * ts.index.days_in_month * (days(1) /
                                                                 ts.index.freq)
            invalid = counts < na_tol
        else:
            raise ValueError(
                "Offset {} not supported. Only absolute offsets (<= 1day) or one month averages supported with max_absent_frac option"
                .format(period))
    agged.mask(invalid, inplace=True)
    return agged
Example #2
0
def plot_inst_and_avg(axes, tss, window_inst, window_avg, labels, label_loc, legend_size):
    """ Plot instantaneous and filtered time series plot
    """
    if window_inst is None:
        window_inst = get_union_window(tss)
    lines = plot_tss(axes['inst'], tss, window_inst)
    if labels is not None:
        axes['inst'].legend(lines, labels, prop={'size': legend_size}, loc=label_loc)

    if window_avg is None:
        window_avg = get_union_window(tss)
    pad = days(4)
    window_to_filter = (window_avg[0] - pad, window_avg[1] + pad)
    tss_clipped = [safe_window(ts, window_to_filter) for ts in tss]
    tss_filtered = filter_timeseries(tss_clipped)
    plot_tss(axes['avg'], tss_filtered, window_avg)
Example #3
0
def main():
    parser = create_arg_parser()
    args = parser.parse_args()
    monterey_fpath = args.monterey
    pt_reyes_fpath = args.pt_reyes
    hgrid_fpath = args.hgrid
    fpath_out = args.outfile
    #todo: hardwire 
    nnode = 83
    
    tbuf = days(16)              
    # convert start time string input to datetime       
    sdate = datetime(*map(int, re.split('[^\d]', args.stime)))

    if args.etime:
        # convert start time string input to datetime
        edate = datetime(*map(int, re.split('[^\d]', args.etime)))
        bufend = edate + tbuf
    else:
        edate = None
        bufend = None

   

    # UTM positions of Point Reyes, Monterey, SF
    pos_pr = np.array([502195.03, 4205445.47])
    pos_mt = np.array([599422.84, 4051630.37])
    pos_sf = np.array([547094.79, 4184499.42])

    var_subtidal = np.array([0.938, 0.905, 0.969])  # pr, mt, sf
    var_semi = np.array([0.554, 0.493, 0.580])

    # Assume 45 degree from north-west to south-east
    tangent = np.array([1, -1])
    tangent = tangent / np.linalg.norm(tangent)  # Normalize
    # Rotate 90 cw to get normal vec
    normal = np.array([tangent[1], -tangent[0]])
    print "tangent:", tangent
    print "normal:", normal

    mt_rel = pos_mt - pos_pr
    x_mt = np.dot(tangent, mt_rel)  # In pr-mt direction
    y_mt = np.dot(normal, mt_rel)  # Normal to x-direction to the 
    
    # Grid
    #todo: what is the difference between this and m = read_grid()??
    s = create_schism_setup(hgrid_fpath)
    
    ocean_boundary = s.mesh.boundaries[0]  # First one is ocean
 
    # Data
    print "Reading Point Reyes..."
    pt_reyes = read_ts(pt_reyes_fpath, start=sdate - tbuf, end=bufend, force_regular=True)
    pt_reyes = interpolate_ts_nan(pt_reyes)
    if np.any(np.isnan(pt_reyes.data)):
        print pt_reyes.times[np.isnan(pt_reyes.data)]
    ts_pr_subtidal, ts_pr_diurnal, ts_pr_semi, noise = separate_species(
        pt_reyes)
    del noise

    print "Reading Monterey..."
    monterey = read_ts(monterey_fpath, start=sdate - tbuf, end=bufend, force_regular=True)
    monterey = interpolate_ts_nan(monterey)
    if pt_reyes.interval != monterey.interval:
        raise ValueError(
            "Point Reyes and Monterey time step must be the same in gen_elev2D.py")

    ts_mt_subtidal, ts_mt_diurnal, ts_mt_semi, noise = separate_species(
        monterey)
    del noise

    dt = monterey.interval.seconds

    print "Done Reading"

    print "Interpolating Point Reyes"
    # interpolate_ts(ts_pr_subtidal.window(sdate,edate),step)
    ts_pr_subtidal = ts_pr_subtidal.window(sdate, edate)
    ts_pr_diurnal = ts_pr_diurnal.window(sdate, edate)  # interpolate_ts(,step)
    # interpolate_ts(ts_pr_semi.window(sdate,edate),step)
    ts_pr_semi = ts_pr_semi.window(sdate, edate)

    print "Interpolating Monterey"
    # interpolate_ts(ts_mt_subtidal.window(sdate,edate),step)
    ts_mt_subtidal = ts_mt_subtidal.window(sdate, edate)
    # interpolate_ts(ts_mt_diurnal.window(sdate,edate),step)
    ts_mt_diurnal = ts_mt_diurnal.window(sdate, edate)
    # interpolate_ts(ts_mt_semi.window(sdate,edate),step)
    ts_mt_semi = ts_mt_semi.window(sdate, edate)

    print "Creating writer"  # requires dt be known for netcdf
    if fpath_out.endswith("th"):
        thwriter = BinaryTHWriter(fpath_out,nnode,None)
    elif fpath_out.endswith("nc"):
        thwriter = NetCDFTHWriter(fpath_out,nnode,sdate,dt)
    else:
        raise ValueError("File extension for output not recognized in file: {}".format(fpath_out))    
    
    
    
    # Grid
    boundaries = s.mesh.nodes[ocean_boundary.nodes]
    pos_rel = boundaries[:, :2] - pos_pr

    # x, y in a new principal axes
    x = np.dot(pos_rel, tangent.reshape((2, -1)))
    y = np.dot(pos_rel, normal.reshape((2, -1)))
    theta_x = x / x_mt
    theta_x_comp = 1. - theta_x
    theta_y = y / y_mt
    theta_y_comp = 1. - theta_y

    var_y = (theta_y_comp * var_semi[0] + theta_y * var_semi[1])

    # adj_subtidal_mt = 0.08  # Adjustment in Monterey subtidal signal
    # scaling_diurnal_mt = 0.95 # Scaling of Monterey diurnal signal (for K1/Q1)
    # Used this up to v75
    adj_subtidal_mt = 0.  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 1.  # Scaling of Monterey diurnal signal (for K1/Q1)
    # New trial for LSC2 with v75
    adj_subtidal_mt = -0.07  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.95  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.03

    adj_subtidal_mt = -0.14  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.90  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.07

    adj_subtidal_mt = 0.10  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.90  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.03

    adj_subtidal_mt = 0.10  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.97  # Scaling of Monterey diurnal signal (for K1/Q1)
    # Scaling of Point Reyes diurnal signal (for K1/Q1)
    scaling_diurnal_pr = 0.97
    scaling_semidiurnal_mt = 1.025  # Scaling at Monterey semi-diurnal signal

    adj_subtidal_mt = 0.09  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.94  # Scaling of Monterey diurnal signal (for K1/Q1)
    # Scaling of Point Reyes diurnal signal (for K1/Q1)
    scaling_diurnal_pr = 0.94
    scaling_semidiurnal_mt = 1.0  # Scaling at Monterey semi-diurnal signal

    slr = 0.0  # Sea level rise

    if np.any(np.isnan(ts_pr_semi.data)):
        print ts_pr_semi.times[np.isnan(ts_pr_semi.data)]
        raise ValueError('')

#    temp=np.zeros((len(ts_pr_semi),nnode))
#    times[:]=[dt*i for i in xrange(len(ts_pr_semi))]   

    for i in xrange(len(ts_pr_semi)):
        t = float(dt * i)
        # semi-diurnal
        # Scaling
        pr = ts_pr_semi[i].value
        mt = ts_mt_semi[i].value * scaling_semidiurnal_mt

        if np.isnan(pr) or np.isnan(mt):
            print pr
            print mt
            raise ValueError("One of values is numpy.nan.")

        eta_pr_side = var_y / var_semi[0] * pr
        eta_mt_side = var_y / var_semi[1] * mt
        eta = eta_pr_side * theta_x_comp + eta_mt_side * theta_x

        # diurnal
        # Interpolate in x-direction only to get a better phase
        pr = ts_pr_diurnal[i].value * scaling_diurnal_pr
        mt = ts_mt_diurnal[i].value * scaling_diurnal_mt

        if np.isnan(pr) or np.isnan(mt):
            raise ValueError("One of values is numpy.nan.")

        eta += pr * theta_x_comp + mt * theta_x

        # Subtidal
        # No phase change in x-direction. Simply interpolate in
        # y-direction.
        pr = ts_pr_subtidal[i].value + slr
        mt = ts_mt_subtidal[i].value + adj_subtidal_mt + slr

        if np.isnan(pr) or np.isnan(mt):
            raise ValueError("One of values is numpy.nan.")

        eta += pr * theta_y_comp + mt * theta_y
        
        # write data to netCDF file   
        thwriter.write_step(i,t,eta)

    # Delete class
    del thwriter
Example #4
0
    def read(self, fpath, start=None, end=None, force_regular=True, selector=None):
        """ Read a text file with the given pattern and parsers.
            Parsers and a pattern must be defined and set in the child class.

            Parameters
            ----------
            fpath: str
                file to read
            start: datetime.datetime, optional
                datetime to start reading in.
                If None, read from the start of the file
            end: datetime.datetime, optional
                datetime to finish reading in.
                If None, read till the end of the file
            force_regular: boolean, optional
                If it is true, it returns a regular time series

            Returns
            -------
            vtools.data.timeseries.TimeSeries
                time series from the file
        """
        # The selector (if it exists) can probably be precalculated or at least recorded.
        # Almost always this amounts to picking variables out of a list of column names
        # and recording indexes, but here we don't ask any questions about what "selector" is.
        n_headerlines, metadata = self.process_header(fpath,selector)
        if n_headerlines is None: raise ValueError("Problem counting header lines (check format?)")
        metadata = dict()
        if not self._header_regexs is None:
            metadata = self.read_metadata_from_header(fpath)
        if not start is None and not end is None:
            if start >= end:
                raise ValueError("The end time must be later than the start")


        with open(fpath, 'r') as f_in:
            times = list()
            values = list()
            # fast forward past header
            if n_headerlines > 0:
                for _ in range(n_headerlines):
                    f_in.readline()
            # process lines starting from current file pointer
            for i, line in enumerate(f_in):
                if self.is_comment(line):
                    continue

                timestamp, vals = self.parse_record(line)
                if start and timestamp < start:
                    continue
                if end and timestamp > end:
                    break
                times.append(timestamp)
                values.append(vals)

        if len(times) < 1:
            return None

        arr = numpy.array(values)

        # Here I assumed that it is more effective to retrieve too much
        # in the reading stage and then do this with numpy fancy indexing.
        # I But you can override this function
        # todo: never seemed complete selector handled elsewhere
        #arr = self.cull_using_selector(arr)
        ts = vts.its(times, arr)


        if force_regular:
            interval = infer_interval(times[:11],
                                      fraction=0.5,
                                      standard=[vtt.minutes(6),
                                                vtt.minutes(10),
                                                vtt.minutes(15),
                                                vtt.hours(1),
                                                vtt.days(1)])
            if not interval:
                # for t in times[:10]:
                #     print t.strftime("%Y-%m-%d %H:%M:%S")
                raise ValueError("Interval could not be inferred from first time steps in %s" % fpath)
            import warnings
            # todo: this really should be an option
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                ts = vts.its2rts(ts, interval)
            # if start is not None:
            #     if start < ts.start:
            #         print "extending front..."
            #         ts = vts.extrapolate_ts(ts, start=start)
            #         print ts.times, ts.data
            #     else:
            #         ts = ts.window(start=start)
            # if end is not None:
            #     if end > ts.end:
            #         print "extending back..."
            #         ts = vts.extrapolate_ts(ts, end=end)
            #     else:
            #         ts = ts.window(end=end)
        for k, v in metadata.items():
            ts.props[k] = v

        return ts
Example #5
0
    def plot(self):
        """ Generate metrics plots
        """
        # Process input parameters
        params = self.params
        variable = params['variable']
        outputs_dir = params['outputs_dir']
        if isinstance(outputs_dir, str):
            outputs_dir = outputs_dir.split()
        time_basis = process_time_str(params['time_basis'])
        stations_input = params.get('stations_input')
        if stations_input is None:
            stations_input = params.get(
                'flow_station_input') if variable == "flow" else params.get(
                    'station_input')
        else:
            raise ValueError(
                "Old style input file. \nUse 'station_input' and 'flow_station_input' respectively for staout* and flow.dat"
            )
        if isinstance(stations_input, str):
            stations_input = stations_input.split()

        db_stations = station.read_station_dbase(params['stations_csv'])
        db_obs = station.read_obs_links(params['obs_links_csv'])
        excluded_stations = params.get('excluded_stations')
        selected_stations = params.get('selected_stations')
        start_avg = process_time_str(params["start_avg"])
        end_avg = process_time_str(params["end_avg"])
        start_inst = process_time_str(params["start_inst"])
        end_inst = process_time_str(params["end_inst"])
        labels = params['labels']
        dest_dir = params.get('dest_dir')
        if dest_dir is None:
            dest_dir = '.'
        else:
            if not os.path.exists(dest_dir):
                os.mkdir(dest_dir)
        plot_format = params.get('plot_format')
        padding = days(4)
        window_common = (min(start_inst, start_avg), max(end_inst, end_avg))
        window_to_read = (window_common[0] - padding,
                          window_common[1] + padding)
        plot_all = read_optional_flag_param(params, 'plot_all')
        remove_outliers = read_optional_flag_param(params, 'remove_outliers')
        adjust_datum = read_optional_flag_param(params, 'auto_adjustment')
        fill_gap = read_optional_flag_param(params, 'fill_gap')
        max_gap_to_fill = hours(1)
        if 'max_gap_to_fill' in params:
            max_gap_to_fill = pd.tseries.frequencies.to_offset(
                params['max_gap_to_fill'])
        else:
            max_gap_to_fill = hours(1)

        # Prepare readers of simulation outputs
        sim_outputs = self.read_simulation_outputs(variable, outputs_dir,
                                                   time_basis, stations_input)
        assert len(sim_outputs) > 0
        assert sim_outputs[0] is not None

        # Iterate through the stations in the first simulation outputs
        for stn in sim_outputs[0].columns:
            station_id = stn[0] if type(stn) == tuple else stn
            # Prepare
            self.logger.info(
                "==================================================")

            self.logger.info(
                "Start processing station:: {}".format(station_id))

            if not station_id in db_stations.index:
                self.logger.warning(
                    "Station id {} not found in station listings".format(
                        station_id))
                continue
            alias = db_stations.loc[station_id, 'alias']

            if selected_stations is not None:
                if station_id not in selected_stations:
                    self.logger.info(
                        "Skipping..."
                        " Not in the list of the selected stations: %s",
                        station_id)
                    continue
            if excluded_stations is not None:
                if station_id in excluded_stations:
                    self.logger.info(
                        "Skipping... "
                        "In the list of the excluded stations: %s", station_id)
                    continue

            if variable == 'flow':
                vert_pos = 'default'
            else:
                vert_pos = stn[1]
            adj_obs = 0.

            # Read Obs
            subloc = 'default' if variable == 'flow' else stn[1]
            ts_obs = self.retrieve_ts_obs(station_id, subloc, variable,
                                          window_to_read, db_stations, db_obs)

            if ts_obs is None or ts_obs.isnull().all():
                self.logger.warning("No observation data: %s.", station_id)
                if plot_all is False:
                    self.logger.warning("Skipping this station")
                    continue
            else:
                if remove_outliers is True:
                    self.logger.info("Removing outliers...")
                    ts_obs = med_outliers(ts_obs, level=3, copy=False)
                adj = db_obs.loc[(station_id, subloc, variable), 'datum_adj']
                if adj is not None and adj != 0.:
                    self.logger.info(
                        "Adjusting obs value with the value in the table...")
                    ts_obs += adj

                    if obs_unit == 'ft':
                        adj = ft_to_m(adj)
                    else:
                        ValueError("Not supported unit for adjustment.")
                    adj_obs += adj
                try:
                    obs_unit = db_obs.loc[(station_id, subloc, variable),
                                          'unit']

                    ts_obs = self.convert_unit_of_ts_obs_to_SI(
                        ts_obs, obs_unit)

                    obs_unit = ts_obs.unit
                except Exception as e:
                    raise Exception("Station {}".format(station_id)) from e

            # Read simulation
            if variable == "flow":
                tss_sim = [
                    None if simout[station_id].isnull().all() else
                    simout[station_id] for simout in sim_outputs
                ]

            else:
                tss_sim = [
                    simout.loc[:, (station_id, subloc)].iloc[:, 0]
                    for simout in sim_outputs
                ]

            for ts in tss_sim:
                if ts is None: continue
                if ts_obs is None or ts_obs.isnull().all():
                    ts.unit = self.variable_units[variable]
                else:
                    ts.unit = obs_unit

            # Adjust datum if necessary
            if adjust_datum and ts_obs is not None:
                ts_obs, adj = self.adjust_obs_datum(ts_obs, tss_sim[0],
                                                    station_id, variable,
                                                    db_obs)
                adj_obs += adj
            if ts_obs is not None and fill_gap is True:
                self.logger.info("Filling gaps in the data.")
                ts_obs = fill_gaps(ts_obs, max_gap_to_fill)

            # Plot
            if check_if_all_tss_are_bad([ts_obs] + tss_sim):
                self.logger.error("None of time series have data.")
                continue
            self.logger.info("Start plotting...")
            source = db_obs.loc[(station_id, subloc, variable),
                                "agency"].upper()
            figtitle = self.create_title(db_stations, station_id, source,
                                         variable, vert_pos)

            title = None
            if type(tss_sim) == list: tss_sim = tuple(tss_sim)

            # labels
            labels_to_plot = deepcopy(labels)
            if adj_obs != 0.:
                if adj_obs > 0.:
                    labels_to_plot[0] += " + {:g}".format(adj_obs)
                else:
                    labels_to_plot[0] += " - {:g}".format(-adj_obs)

            if plot_format == 'simple':
                fig = plot_comparison(ts_obs,
                                      tss_sim,
                                      window_inst=(start_inst, end_inst),
                                      window_avg=(start_avg, end_avg),
                                      labels=labels_to_plot,
                                      title=title)
            else:
                fig = plot_metrics(ts_obs,
                                   tss_sim,
                                   window_inst=(start_inst, end_inst),
                                   window_avg=(start_avg, end_avg),
                                   labels=labels_to_plot,
                                   title=title)
            fname_output = self.set_fname_out(alias, variable, station_id,
                                              vert_pos)
            fpath_output = os.path.join(dest_dir, fname_output + '.png')
            fig.suptitle(figtitle, fontsize=14)
            fig.savefig(fpath_output, dpi=300)
            self.logger.info("Done for the station.")
Example #6
0
    def plot(self):
        """ Generate metrics plots
        """
        # Process input parameters
        params = self.params
        variable = params['variable']
        outputs_dir = params['outputs_dir']
        if isinstance(outputs_dir, str):
            outputs_dir = outputs_dir.split()
        time_basis = process_time_str(params['time_basis'])
        stations_input = params.get('stations_input')
        if stations_input is None:
            stations_input = params.get(
                'flow_station_input') if variable == "flow" else params.get(
                    'station_input')
        else:
            raise ValueError(
                "Old style input file. \nUse 'station_input' and 'flow_station_input' respectively for staout* and flow.dat"
            )
        if isinstance(stations_input, str):
            stations_input = stations_input.split()
        db_stations = station_db.StationDB(params['stations_csv'])
        db_obs = obs_links.ObsLinks(params['obs_links_csv'])
        excluded_stations = params.get('excluded_stations')
        selected_stations = params.get('selected_stations')
        start_avg = process_time_str(params["start_avg"])
        end_avg = process_time_str(params["end_avg"])
        start_inst = process_time_str(params["start_inst"])
        end_inst = process_time_str(params["end_inst"])
        labels = params['labels']
        dest_dir = params.get('dest_dir')
        if dest_dir is None:
            dest_dir = '.'
        else:
            if not os.path.exists(dest_dir):
                os.mkdir(dest_dir)
        plot_format = params.get('plot_format')
        padding = days(4)
        window_common = (min(start_inst, start_avg), max(end_inst, end_avg))
        window_to_read = (window_common[0] - padding,
                          window_common[1] + padding)
        plot_all = read_optional_flag_param(params, 'plot_all')
        remove_outliers = read_optional_flag_param(params, 'remove_outliers')
        adjust_datum = read_optional_flag_param(params, 'auto_adjustment')
        fill_gap = read_optional_flag_param(params, 'fill_gap')
        max_gap_to_fill = hours(1)
        if 'max_gap_to_fill' in params:
            max_gap_to_fill = parse_interval(params['max_gap_to_fill'])

        # Prepare readers of simulation outputs
        sim_outputs = self.read_simulation_outputs(variable, outputs_dir,
                                                   time_basis, stations_input)
        assert len(sim_outputs) > 0
        assert sim_outputs[0] is not None
        # Iterate through the stations in the first simulation outputs
        for station in sim_outputs[0].stations:
            # Prepare
            self.logger.info(
                "==================================================")
            self.logger.info("Start processing a station: %s", station["name"])
            station_id = station['name']
            alias = db_stations.alias(station_id)

            if selected_stations is not None:
                if station_id not in selected_stations:
                    self.logger.info(
                        "Skipping..."
                        " Not in the list of the selected stations: %s",
                        station_id)
                    continue
            if excluded_stations is not None:
                if station_id in excluded_stations:
                    self.logger.info(
                        "Skipping... "
                        "In the list of the excluded stations: %s", station_id)
                    continue
            if not variable == 'flow':
                vert_pos = station['vert_pos']
            else:
                vert_pos = 0
            adj_obs = 0.

            # Read Obs
            ts_obs = self.retrieve_ts_obs(station_id, variable, window_to_read,
                                          db_stations, db_obs, vert_pos)
            if ts_obs is None:
                self.logger.warning("No observation data: %s.", station_id)
                if plot_all is False:
                    self.logger.warning("Skipping this station")
                    continue
            else:
                if remove_outliers is True:
                    self.logger.info("Removing outliers...")
                    ts_obs, filtered = med_outliers(ts_obs, copy=False)
                adj = db_obs.adjustment(station_id, variable)
                if adj is not None and adj != 0.:
                    self.logger.info(
                        "Adjusting obs value with the value in the table...")
                    ts_obs += adj
                    obs_unit = db_obs.unit(station_id, variable, vert_pos)
                    if obs_unit == 'ft':
                        adj = ft_to_m(adj)
                    else:
                        ValueError("Not supported unit for adjustment.")
                    adj_obs += adj
                if 'unit' not in ts_obs.props:
                    ts_obs.props['unit'] = db_obs.unit(station_id, variable)
                ts_obs = self.convert_unit_of_ts_obs_to_SI(ts_obs)

            # Read simulation
            tss_sim = self.retrieve_tss_sim(sim_outputs, station_id, variable,
                                            vert_pos)

            # Adjust datum if necessary
            if adjust_datum is True and ts_obs is not None:
                ts_obs, adj = self.adjust_obs_datum(ts_obs, tss_sim[0],
                                                    station_id, variable,
                                                    db_obs)
                adj_obs += adj
            if ts_obs is not None and fill_gap is True:
                self.logger.info("Filling gaps in the data.")
                fill_gaps((ts_obs, ), max_gap_to_fill)

            # Plot
            if check_if_all_tss_are_bad([
                    ts_obs,
            ] + tss_sim):
                self.logger.error("None of time series have data.")
                continue
            self.logger.info("Start plotting...")
            source = db_obs.agency(station_id, variable).upper()
            figtitle = self.create_title(db_stations, station_id, source,
                                         variable, vert_pos)

            title = None
            # labels
            labels_to_plot = deepcopy(labels)
            if adj_obs != 0.:
                if adj_obs > 0.:
                    labels_to_plot[0] += " + %g" % adj_obs
                else:
                    labels_to_plot[0] += " - %g" % (-adj_obs)
            if plot_format == 'simple':
                fig = plot_comparison(ts_obs,
                                      *tss_sim,
                                      window_inst=(start_inst, end_inst),
                                      window_avg=(start_avg, end_avg),
                                      labels=labels_to_plot,
                                      title=title)
            else:
                fig = plot_metrics(ts_obs,
                                   *tss_sim,
                                   window_inst=(start_inst, end_inst),
                                   window_avg=(start_avg, end_avg),
                                   labels=labels_to_plot,
                                   title=title)
            fname_output = self.set_fname_out(alias, variable, station_id,
                                              vert_pos)
            fpath_output = os.path.join(dest_dir, fname_output + '.png')
            fig.suptitle(figtitle, fontsize=14)
            fig.savefig(fpath_output, dpi=300)
            self.logger.info("Done for the station.")
Example #7
0
# -*- coding: utf-8 -*-

from vtools.functions.period_op import *
from vtools.data.vtime import days
from vtools.data.sample_series import *
import matplotlib.pyplot as plt


ts_week=synthetic_tide_series()
## get 2 days of data
ts=ts_week.window(ts_week.times[0],ts_week.times[0]+days(2))
ts_max=period_max(ts,hours(1))
fig=plt.figure()
ax0 = fig.add_subplot(111)
ax0.set_ylabel("surface (feet)")
p0=ax0.plot(ts.times,ts.data,color='g',linewidth=1.0)
p1=ax0.step(ts_max.times,ts_max.data,color='r',linewidth=1.0,where="post")
p2=ax0.plot(ts_max.centered().times,ts_max.centered().data,color='black',\
linewidth=1.0,linestyle="--")
plt.legend(["Surface","Max_step","Max_centered"])
plt.grid(b=True, which='major', color='0.9', linestyle='-', linewidth=0.5)
fig.autofmt_xdate()
plt.show()

Example #8
0
def gen_elev2D(hgrid_fpath, outfile, pt_reyes_fpath, monterey_fpath, start,
               end, slr):
    max_gap = 5
    stime = start
    etime = end
    fpath_out = outfile

    #todo: hardwire
    nnode = 83

    tbuf = days(16)
    # convert start time string input to datetime
    sdate = pd.Timestamp(stime)

    if not etime is None:
        # convert start time string input to datetime
        edate = pd.Timestamp(etime)
        bufend = edate + tbuf
    else:
        edate = None
        bufend = None

    # UTM positions of Point Reyes, Monterey, SF
    pos_pr = np.array([502195.03, 4205445.47])
    pos_mt = np.array([599422.84, 4051630.37])
    pos_sf = np.array([547094.79, 4184499.42])

    var_subtidal = np.array([0.938, 0.905, 0.969])  # pr, mt, sf
    var_semi = np.array([0.554, 0.493, 0.580])

    # Assume 45 degree from north-west to south-east
    tangent = np.array([1, -1])
    tangent = tangent / np.linalg.norm(tangent)  # Normalize
    # Rotate 90 cw to get normal vec
    normal = np.array([tangent[1], -tangent[0]])
    print("tangent: {}".format(tangent))
    print("normal: {}".format(normal))

    mt_rel = pos_mt - pos_pr
    x_mt = np.dot(tangent, mt_rel)  # In pr-mt direction
    y_mt = np.dot(normal, mt_rel)  # Normal to x-direction to the

    # Grid
    #todo: what is the difference between this and m = read_grid()??
    mesh = read_mesh(hgrid_fpath)

    ocean_boundary = mesh.boundaries[0]  # First one is ocean

    # Data
    print("Reading Point Reyes...")
    pt_reyes = read_noaa(pt_reyes_fpath,
                         start=sdate - tbuf,
                         end=bufend,
                         force_regular=True)
    pt_reyes.interpolate(limit=max_gap, inplace=True)
    if pt_reyes.isna().any(axis=None):
        raise ValueError("pt_reyes has gaps larger than fill limit")
    ts_pr_subtidal, ts_pr_diurnal, ts_pr_semi, noise = separate_species(
        pt_reyes, noise_thresh_min=150)

    del noise

    print("Reading Monterey...")
    monterey = read_noaa(monterey_fpath,
                         start=sdate - tbuf,
                         end=bufend,
                         force_regular=True)
    monterey.interpolate(limit=max_gap, inplace=True)
    if pt_reyes.isna().any(axis=None):
        raise ValueError("monterey has gaps larger than fill limit")

    if pt_reyes.index.freq != monterey.index.freq:
        raise ValueError(
            "Point Reyes and Monterey time step must be the same in gen_elev2D.py"
        )

    ts_mt_subtidal, ts_mt_diurnal, ts_mt_semi, noise = separate_species(
        monterey, noise_thresh_min=150)
    del noise

    dt = monterey.index.freq / seconds(1)

    print("Done Reading")

    print("Interpolating and subsetting Point Reyes")
    # interpolate_ts(ts_pr_subtidal.window(sdate,edate),step)
    ts_pr_subtidal = ts_pr_subtidal.loc[sdate:edate]
    ts_pr_diurnal = ts_pr_diurnal.loc[sdate:edate]
    # interpolate_ts(ts_pr_semi.window(sdate,edate),step)
    ts_pr_semi = ts_pr_semi.loc[sdate:edate]

    print("Interpolating and subsetting Monterey")
    # interpolate_ts(ts_mt_subtidal.window(sdate,edate),step)
    ts_mt_subtidal = ts_mt_subtidal.loc[sdate:edate]
    # interpolate_ts(ts_mt_diurnal.window(sdate,edate),step)
    ts_mt_diurnal = ts_mt_diurnal.loc[sdate:edate]
    # interpolate_ts(ts_mt_semi.window(sdate,edate),step)
    ts_mt_semi = ts_mt_semi.loc[sdate:edate]

    print("Creating writer")  # requires dt be known for netcdf
    if fpath_out.endswith("th"):
        thwriter = BinaryTHWriter(fpath_out, nnode, None)
    elif fpath_out.endswith("nc"):
        thwriter = NetCDFTHWriter(fpath_out, nnode, sdate, dt)
    else:
        raise ValueError(
            "File extension for output not recognized in file: {}".format(
                fpath_out))

    # Grid
    boundaries = mesh.nodes[ocean_boundary.nodes]
    pos_rel = boundaries[:, :2] - pos_pr

    # x, y in a new principal axes
    x = np.dot(pos_rel, tangent.reshape((2, -1)))
    y = np.dot(pos_rel, normal.reshape((2, -1)))
    theta_x = x / x_mt
    theta_x_comp = 1. - theta_x
    theta_y = y / y_mt
    theta_y_comp = 1. - theta_y

    var_y = (theta_y_comp * var_semi[0] + theta_y * var_semi[1])

    # adj_subtidal_mt = 0.08  # Adjustment in Monterey subtidal signal
    # scaling_diurnal_mt = 0.95 # Scaling of Monterey diurnal signal (for K1/Q1)
    # Used this up to v75
    adj_subtidal_mt = 0.  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 1.  # Scaling of Monterey diurnal signal (for K1/Q1)
    # New trial for LSC2 with v75
    adj_subtidal_mt = -0.07  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.95  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.03

    adj_subtidal_mt = -0.14  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.90  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.07

    adj_subtidal_mt = 0.10  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.90  # Scaling of Monterey diurnal signal (for K1/Q1)
    scaling_semidiurnal_mt = 1.03

    adj_subtidal_mt = 0.10  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.97  # Scaling of Monterey diurnal signal (for K1/Q1)
    # Scaling of Point Reyes diurnal signal (for K1/Q1)
    scaling_diurnal_pr = 0.97
    scaling_semidiurnal_mt = 1.025  # Scaling at Monterey semi-diurnal signal

    adj_subtidal_mt = 0.09  # Adjustment in Monterey subtidal signal
    scaling_diurnal_mt = 0.94  # Scaling of Monterey diurnal signal (for K1/Q1)
    # Scaling of Point Reyes diurnal signal (for K1/Q1)
    scaling_diurnal_pr = 0.94
    scaling_semidiurnal_mt = 1.0  # Scaling at Monterey semi-diurnal signal

    if ts_pr_semi.isna().any(axis=None):
        print(ts_pr_semi[ts_pr_semi.isna()])
        raise ValueError('Above times are missing in Point Reyes data')

    for i in range(len(ts_pr_semi)):
        t = float(dt * i)
        # semi-diurnal
        # Scaling
        pr = ts_pr_semi.iloc[i, 0]
        mt = ts_mt_semi.iloc[i, 0] * scaling_semidiurnal_mt

        if np.isnan(pr) or np.isnan(mt):
            raise ValueError("One of values is numpy.nan.")

        eta_pr_side = var_y / var_semi[0] * pr
        eta_mt_side = var_y / var_semi[1] * mt
        eta = eta_pr_side * theta_x_comp + eta_mt_side * theta_x

        # diurnal
        # Interpolate in x-direction only to get a better phase
        pr = ts_pr_diurnal.iloc[i, 0] * scaling_diurnal_pr
        mt = ts_mt_diurnal.iloc[i, 0] * scaling_diurnal_mt
        #if i < 5:
        #    print("yu")
        #    print(pr)
        #    print(mt)

        if np.isnan(pr) or np.isnan(mt):
            raise ValueError("One of values is numpy.nan.")

        eta += pr * theta_x_comp + mt * theta_x

        # Subtidal
        # No phase change in x-direction. Simply interpolate in
        # y-direction.
        pr = ts_pr_subtidal.iloc[i, 0]
        mt = ts_mt_subtidal.iloc[i, 0] + adj_subtidal_mt

        if np.isnan(pr) or np.isnan(mt):
            raise ValueError("One of values is numpy.nan.")
        eta += pr * theta_y_comp + mt * theta_y + slr

        # write data to netCDF file
        thwriter.write_step(i, t, eta)

    # Delete class
    del thwriter