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
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)
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
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
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.")
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.")
# -*- 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()
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