def plot_geo(geo, coastline, symbol, legend, title, code): with NamedTemporaryFile(delete=False, suffix=f"__WT_{code}.pdf") as pdf: pdf_obj = mv.pdf_output(output_name=pdf.name.replace(".pdf", "")) mv.setoutput(pdf_obj) mv.plot(coastline, symbol, legend, title, geo) os.chmod(pdf.name, 0o444) return {"pdf": pdf.name}
def plot_obs_freq(predictor_matrix, code): coastline = mv.mcoast(map_coastline_thickness=2, map_boundaries="on", map_coastline_colour="chestnut") symbol = mv.msymb( legend="on", symbol_type="marker", symbol_table_mode="on", symbol_outline="on", symbol_min_table=[1, 2, 5, 10, 15, 20, 25, 30], symbol_max_table=[2, 5, 10, 15, 20, 25, 30, 100000], symbol_colour_table=[ "RGB(0.7020,0.7020,0.7020)", "RGB(0.4039,0.4039,0.4039)", "blue", "RGB(0.4980,1.0000,0.0000)", "RGB(1.0000,0.8549,0.0000)", "orange", "red", "magenta", ], symbol_marker_table=15, symbol_height_table=0.3, ) legend = mv.mlegend( legend_text_font="arial", legend_text_font_size=0.35, legend_entry_plot_direction="row", legend_box_blanking="on", legend_entry_text_width=50, ) title = mv.mtext( text_line_count=4, text_line_1= "OBS Frequency", # To sostitute with "FE" values when relevant. text_line_2=f"WT Code = {code}", text_line_4=" ", text_font="arial", text_font_size=0.4, ) df = predictor_matrix[["LonOBS", "LatOBS", "OBS"]] grouped_df = df.groupby(["LatOBS", "LonOBS"], as_index=False).count() geo = mv.create_geo(len(grouped_df), "xyv") geo = mv.set_latitudes(geo, grouped_df["LatOBS"].to_numpy(dtype=np.float)) geo = mv.set_longitudes(geo, grouped_df["LonOBS"].to_numpy(dtype=np.float)) geo = mv.set_values(geo, grouped_df["OBS"].to_numpy(dtype=np.float)) with NamedTemporaryFile(delete=False, suffix=".pdf") as pdf: pdf_obj = mv.pdf_output(output_name=pdf.name.replace(".pdf", "")) mv.setoutput(pdf_obj) mv.plot(coastline, symbol, legend, title, geo) return pdf.name
def plot_std(predictor_matrix, code): coastline = mv.mcoast(map_coastline_thickness=2, map_boundaries="on", map_coastline_colour="chestnut") symbol = mv.msymb( legend="on", symbol_type="marker", symbol_table_mode="on", symbol_outline="on", symbol_min_table=[0, 0.0001, 0.5, 1, 2, 5], symbol_max_table=[0.0001, 0.5, 1, 2, 5, 1000], symbol_colour_table=[ "RGB(0.7020,0.7020,0.7020)", "RGB(0.2973,0.2973,0.9498)", "RGB(0.1521,0.6558,0.5970)", "RGB(1.0000,0.6902,0.0000)", "red", "RGB(1.0000,0.0000,1.0000)", ], symbol_marker_table=15, symbol_height_table=0.3, ) legend = mv.mlegend( legend_text_font="arial", legend_text_font_size=0.35, legend_entry_plot_direction="row", legend_box_blanking="on", legend_entry_text_width=50, ) error = "FER" if "FER" in predictor_matrix.columns else "FE" title = mv.mtext( text_line_count=4, text_line_1=f"{error} Standard Deviation", text_line_2=f"WT Code = {code}", text_line_4=" ", text_font="arial", text_font_size=0.4, ) df = predictor_matrix[["LonOBS", "LatOBS", error]] grouped_df = df.groupby(["LatOBS", "LonOBS"])[error].mean().reset_index() geo = mv.create_geo(len(grouped_df), "xyv") geo = mv.set_latitudes(geo, grouped_df["LatOBS"].to_numpy(dtype=np.float)) geo = mv.set_longitudes(geo, grouped_df["LonOBS"].to_numpy(dtype=np.float)) geo = mv.set_values(geo, grouped_df[error].to_numpy(dtype=np.float)) with NamedTemporaryFile(delete=False, suffix=".pdf") as pdf: pdf_obj = mv.pdf_output(output_name=pdf.name.replace(".pdf", "")) mv.setoutput(pdf_obj) mv.plot(coastline, symbol, legend, title, geo) return pdf.name
def test_plot_2_pages(): output_name = file_in_testdir('test_plot_2_pages') png = mv.png_output(output_name=output_name) degraded_field = mv.read(data=TEST_FIELDSET, grid=[4, 4]) page1 = mv.plot_page(top=2.2, bottom=52.2, right=100) page2 = mv.plot_page(top=50) dw = mv.plot_superpage(pages=[page1, page2]) mv.setoutput(png) mv.plot(dw[0], degraded_field, dw[1], degraded_field + 50) output_name_from_magics = output_name + '.1.png' assert (os.path.isfile(output_name_from_magics)) os.remove(output_name_from_magics)
def plot_geo(geo, coastline, symbol, legend, title): with NamedTemporaryFile(suffix=".png") as png, NamedTemporaryFile( delete=False, suffix=".pdf") as pdf: png_obj = mv.png_output(output_name=png.name.replace(".png", "")) mv.setoutput(png_obj) mv.plot(coastline, symbol, legend, title, geo) pdf_obj = mv.pdf_output(output_name=pdf.name.replace(".pdf", "")) mv.setoutput(pdf_obj) mv.plot(coastline, symbol, legend, title, geo) os.chmod(pdf.name, 0o444) with open(png.name.replace(".png", ".1.png"), "rb") as img: return {"preview": b64encode(img.read()).decode(), "pdf": pdf.name}
def test_plot_2(): output_name = file_in_testdir('test_plot_2') png = mv.png_output(output_name=output_name) grid_shade = { 'legend': True, 'contour': False, 'contour_highlight': True, 'contour_shade': True, 'contour_shade_technique': 'grid_shading', 'contour_shade_max_level_colour': 'olive', 'contour_shade_min_level_colour': 'blue', 'contour_shade_colour_direction': 'clockwise', } degraded_field = mv.read(data=TEST_FIELDSET, grid=[4, 4]) mv.plot(png, degraded_field, mv.mcont(grid_shade)) output_name_from_magics = output_name + '.1.png' assert (os.path.isfile(output_name_from_magics)) os.remove(output_name_from_magics)
def _build(self, img_size): img = [] names = [] # img_size = 120 tmp_dir = os.path.join(os.getenv("METVIEW_TMPDIR", ""), "_maparea_") Path(tmp_dir).mkdir(exist_ok=True) for name in map_area_names(): f_name = os.path.join(tmp_dir, name + ".png") if not os.path.exists(f_name): view = mv.make_geoview(area=name, style="grey_1") mv.setoutput( mv.png_output( output_name=f_name[:-4], output_width=300, output_name_first_page_number="off", )) mv.plot(view) if os.path.exists(f_name): names.append(name) img.append(self.to_base64(f_name)) return (img, names)
def _build(self, img_size): img = [] names = [] # img_size = 120 tmp_dir = os.path.join(os.getenv("METVIEW_TMPDIR", ""), "_mapstyle_") Path(tmp_dir).mkdir(exist_ok=True) for name, d in map_styles().items(): f_name = os.path.join(tmp_dir, name + ".png") if not os.path.exists(f_name): view = mv.make_geoview(area=[30, -30, 75, 45], style=name) view.update({"MAP_COASTLINE_RESOLUTION": "low"}, sub="coastlines") mv.setoutput( mv.png_output( output_name=f_name[:-4], output_width=300, output_name_first_page_number="off", )) mv.plot(view) if os.path.exists(f_name): names.append(name) img.append(self.to_base64(f_name)) return (img, names)
) area_view = mv.geoview( map_area_definition="corners", area=[45.83, -13.87, 62.03, 8.92], coastlines=land_shade, ) # Simplest plot: # NOTE that when plotting a 'raw' BUFR file, Magics will plot synop symbols as shown in # https://software.ecmwf.int/wiki/display/METV/Data+Part+1 "Plotting BUFR Data" obs = mv.read("../tests/obs_3day.bufr") mv.setoutput(mv.png_output(output_width=1200, output_name="./obsplot1")) mv.plot(area_view, obs) # ALTERNATIVELY, add an Observations Plotting visual definition obs_plotting = mv.mobs( obs_temperature=False, obs_cloud=False, obs_low_cloud=False, obs_dewpoint_colour="purple", ) mv.setoutput(mv.png_output(output_width=1200, output_name="./obsplot2")) mv.plot(area_view, obs, obs_plotting) # ALTERNATIVELY, if we don't want to plot the whole observations, but instead want to # extract a specific parameter from the BUFR messages, then we use the Observation Filter
# read geopotential z = mv.read("./z_for_UC-04.grib") t_shade_c = mv.mcont( legend=True, contour_highlight=False, contour_level_selection_type="interval", contour_interval=10, contour_shade=True, contour_shade_max_level=60, contour_shade_min_level=-60, contour_shade_method="area_fill", contour_shade_max_level_colour="red", contour_shade_min_level_colour="blue", contour_shade_colour_direction="clockwise", ) z_isolines = mv.mcont( legend=True, contour_line_thickness=2, contour_line_colour="black", contour_highlight_colour="black", contour_highlight_thickness=4, contour_level_selection_type="interval", contour_interval=5, contour_legend_text="Geopotential", ) mv.setoutput(mv.png_output(output_width=1000, output_name="./gribplot")) mv.plot(t2, t_shade_c, z, z_isolines)
t2m_grib = mv.read("./t2m_grib.grib") obs_3day = mv.read("./obs_3day.bufr") t2m_gpt = mv.obsfilter(parameter="012004", output="geopoints", data=obs_3day) diff = t2m_grib - t2m_gpt diff_symb = mv.msymb( legend=True, symbol_type="marker", symbol_table_mode="advanced", ) mv.setoutput(mv.png_output(output_width=1000, output_name="./obsdiff1")) mv.plot(area_view, diff, diff_symb) # Extract geopoints that are hotter by 1 deg or more # hotter = mv.filter(diff, diff >= 1) hotter = diff.filter(diff >= 1) # Extract geopoints that are colder by 1 deg or more # colder = mv.filter(diff, diff <= -1) colder = diff.filter(diff <= -1) # Get geopoints that are within +/-1 # exact = mv.filter(diff, (diff > -1) * (diff < 1)) exact = diff.filter((diff > -1) * (diff < 1)) # Symbol visdefs for each classification red = mv.msymb(symbol_type="marker", symbol_colour="red")
def plot_cdf(*args, location=None, title_font_size=0.4, x_range=None): """ Plot CDF curve """ # check x range x_range = [] if x_range is None else x_range if x_range and len(x_range) not in [2, 3]: raise Exception( f"plot_cdf: invalid x_range specified. Format [x_min, x_max, [x_tick]]" ) if len(x_range) == 2 and x_range[1] <= x_range[0]: raise Exception( f"plot_cdf: invalid x_range specified. x_min={x_range[0]} >= x_max={x_range[1]}" ) layers = _make_layers(*args, form_layout=False) desc = [] cdf_data = [] cdf_label = [] title_data = [] y_values = np.arange(0, 101) plot_units = "" units_scaler = None # compute the cdf for each input layer for layer in layers: if isinstance(layer["data"], mv.Fieldset): # we assume each field has the same units and paramId if plot_units == "": meta = mv.grib_get(layer["data"][0], ["units", "paramId"]) if meta and len(meta[0]) == 2: meta = {"units": meta[0][0], "paramId": meta[0][1]} units_scaler = Scaling.find_item(meta) if units_scaler is not None: plot_units = units_scaler.to_units else: plot_units = meta.get("units", "") # determine ens number and steps members = layer["data"]._unique_metadata("number") steps = layer["data"]._unique_metadata("step") # print(f"members={members}") # ens forecast if len(members) > 1: for step in steps: v = layer["data"].select(step=step) v = mv.nearest_gridpoint(v, location) # print(f"step={step}") x = np.percentile(v, y_values) if units_scaler is not None: x = units_scaler.scale_value(x) # print(f" x={x}") cdf_data.append(x) cdf_label.append(layer["data"].label + f" +{step}h") # deterministic forecast else: raise Exception(f"plot_cds: only ENS data accepted as input!") title_data.append(layer["data"]) # define x axis params if not x_range: x_tick, x_min, x_max = Layout.compute_axis_range( _y_min(cdf_data), _y_max(cdf_data)) elif len(x_range) == 2: x_min = x_range[0] x_max = x_range[1] x_tick, _, _ = Layout.compute_axis_range(x_min, x_max) elif len(x_range) == 3: x_min = x_range[0] x_max = x_range[1] x_tick = x_range[2] else: raise Exception(f"plot_cdf: invalid x_range={x_range} specified!") # print(f"x_tick={x_tick} x_min={x_min} x_max={x_max}") x_title = f"[{plot_units}]" # define y axis params y_min = 0 y_max = 100 y_tick = 10 y_title = "Percentage [%]" # define the view view = Layout().build_xy(x_min, x_max, y_min, y_max, x_tick, y_tick, x_title, y_title) desc.append(view) # define curves line_colours = [ "red", "blue", "green", "black", "cyan", "evergreen", "gold", "pink", ] line_styles = ["solid", "dash", "dotted"] colour_idx = -1 style_idx = 0 for i, d in enumerate(cdf_data): vis = mv.input_visualiser(input_x_values=d, input_y_values=y_values) colour_idx = (colour_idx + 1) % len(line_colours) vd = mv.mgraph( graph_type="curve", graph_line_colour=line_colours[colour_idx], graph_line_thickness=3, legend_user_text=cdf_label[i], legend="on", ) desc.append(vis) desc.append(vd) # add title title = Title(font_size=title_font_size) t = title.build_cdf(title_data) if t is not None: desc.append(t) # add legend legX = 3.5 legY = 14 # Legend legend = mv.mlegend( legend_display_type="disjoint", legend_entry_plot_direction="column", legend_text_composition="user_text_only", legend_border="on", legend_border_colour="black", legend_box_mode="positional", legend_box_x_position=legX, legend_box_y_position=legY, legend_box_x_length=4, legend_box_y_length=3, legend_text_font_size=0.35, legend_box_blanking="on", ) desc.append(legend) mv.plot(desc, animate=False)
def plot_rmse(*args, ref=None, area=None, title_font_size=0.4, y_max=None): """ Plot RMSE curve """ desc = [] if not isinstance(ref, mv.Fieldset): raise Exception(f"Missing or invalid ref argument!") layers = _make_layers(*args, form_layout=False) # compute the rmse for each input layer data = [] # list of tuples rmse_data = [] title_data = [] has_ef = False for layer in layers: if isinstance(layer["data"], mv.Fieldset): # determine ens number members = layer["data"]._unique_metadata("number") # print(f"members={members}") # ens forecast if len(members) > 1: if has_ef: raise Exception( "Only one ENS fieldset can be used in plot_rmse()!") has_ef = True em_d = None # ens mean for m in members: pf_d = layer["data"].select(number=m) ref_d, pf_d = _prepare_grid(ref, pf_d) data.append(("cf" if m == "0" else "pf", layer["data"])) rmse_data.append(mv.sqrt(mv.average((pf_d - ref_d)**2))) em_d = pf_d if em_d is None else em_d + pf_d # compute rmse for ens mean data.append(("em", layer["data"])) rmse_data.append( mv.sqrt(mv.average((em_d / len(members) - ref_d)**2))) # deterministic forecast else: ref_d, dd = _prepare_grid(ref, layer["data"]) data.append(("fc", layer["data"])) rmse_data.append(mv.sqrt(mv.average((dd - ref_d)**2))) title_data.append(layer["data"]) # define x axis params dates = ref.valid_date() x_min = dates[0] x_max = dates[-1] x_tick = 1 x_title = "" # define y axis params y_min = 0 if y_max is None: y_tick, _, y_max = Layout.compute_axis_range(0, _y_max(rmse_data)) else: y_tick, _, _ = Layout.compute_axis_range(0, y_max) y_title = "RMSE [" + mv.grib_get_string(ref[0], "units") + "]" # print(f"y_tick={y_tick} y_max={y_max}") # define the view view = Layout().build_rmse(x_min, x_max, y_min, y_max, x_tick, y_tick, x_title, y_title) desc.append(view) # define curves ef_label = {"cf": "ENS cf", "pf": "ENS pf", "em": "ENS mean"} ef_colour = {"cf": "black", "pf": "red", "em": "kelly_green"} fc_colour = [ "red", "blue", "green", "black", "cyan", "evergreen", "gold", "pink" ] if has_ef: fc_colour = [x for x in fc_colour if x not in list(ef_colour.values())] pf_label_added = False colour_idx = -1 legend_item_count = 0 for i, d in enumerate(rmse_data): vis = mv.input_visualiser(input_x_type="date", input_date_x_values=dates, input_y_values=d) vd = {"graph_type": "curve"} line_colour = "black" line_width = 1 if data[i][0] == "fc": line_width = 3 colour_idx = (colour_idx + 1) % len(fc_colour) line_colour = fc_colour[colour_idx] # print(f"label={data[i][1][0].label}") vd["legend_user_text"] = data[i][1].label vd["legend"] = "on" legend_item_count += 1 elif data[i][0] == "pf": line_width = 1 line_colour = ef_colour["pf"] if not pf_label_added: pf_label_added = True vd["legend_user_text"] = ef_label.get("pf", "") vd["legend"] = "on" legend_item_count += 1 elif data[i][0] in ["cf", "em"]: line_width = 3 line_colour = ef_colour[data[i][0]] vd["legend_user_text"] = ef_label.get(data[i][0], "") vd["legend"] = "on" legend_item_count += 1 vd["graph_line_colour"] = line_colour vd["graph_line_thickness"] = line_width desc.append(vis) desc.append(mv.mgraph(**vd)) # add title title = Title(font_size=title_font_size) t = title.build_rmse(ref, title_data) if t is not None: desc.append(t) # add legend leg_left = 3.5 # legY = 14 leg_height = legend_item_count * (0.35 + 0.5) + (legend_item_count + 1) * 0.1 leg_bottom = 17.5 - leg_height # Legend legend = mv.mlegend( legend_display_type="disjoint", legend_entry_plot_direction="column", # "row", legend_text_composition="user_text_only", legend_border="on", legend_border_colour="black", legend_box_mode="positional", legend_box_x_position=leg_left, legend_box_y_position=leg_bottom, legend_box_x_length=4, legend_box_y_length=leg_height, legend_text_font_size=0.35, legend_box_blanking="on", ) desc.append(legend) mv.plot(desc, animate=False)
def plot_stamp( *args, an=[], fc=[], layout=None, view=None, area=None, title_font_size=0.4, frame=-1, animate="auto", diff_base=None, ): """ Plot ENS stamp maps """ # define the view view = _make_view(view, area) desc = [] data = {} vd = {} if diff_base is not None: assert isinstance(diff_base, mv.Fieldset) if len(args) > 0: assert isinstance(args[0], mv.Fieldset) layers = _make_layers(*args, form_layout=False) assert len(layers) == 1 # prepare ens data["ens"] = layers[0]["data"] assert data["ens"] is not None if diff_base is not None: vd["ens"] = _make_visdef(data["ens"], [], style_db="diff") else: vd["ens"] = _make_visdef(data["ens"], layers[0]["vd"]) # prepare an and fc d = {"an": an, "fc": fc} for k, v in d.items(): if v: layers = _make_layers(v, form_layout=False) if layers: data[k] = layers[0]["data"] vd[k] = layers[0]["vd"] if diff_base is not None: vd[k] = vd["ens"] else: if len(vd[k]) == 0 and "ens" in vd: vd[k] = vd["ens"] else: vd[k] = _make_visdef(data[k], vd[k]) # determine ens number members = [] if "ens" in data: members = data["ens"]._unique_metadata("number") LOG.debug(f"members={members}") if len(members) == 0: raise Exceception("No ENS data found in input!") # determine number of maps num = len(members) + sum([1 for x in ["an", "fc"] if x in data]) # build the layout dw = Layout().build_stamp(num, layout=layout, view=view) if len(dw) < num + 1: raise Exception( f"Layout has less maps (={len(dw)}) than expected (={num})") title = Title(font_size=title_font_size) # ens members for i, m in enumerate(members): desc.append(dw[i]) d = data["ens"].select(number=m) if diff_base is not None: d = d - diff_base desc.append(d) if vd["ens"]: desc.extend(vd["ens"]) t = title.build_stamp(d, member=str(i)) desc.append(t) # add an and fc n = len(members) for t in ["an", "fc"]: if t in data: desc.append(dw[n]) d = data[t] if diff_base is not None: d = d - diff_base desc.append(d) if vd[t]: desc.append(vd[t]) t = title.build_stamp(data[t], member="") desc.append(t) n += 1 for i in range(n, len(dw)): desc.append(dw[i]) if len(members) > 0 and "ens" in data: cont = mv.mcont(contour="off", contour_label="off") dummy = d = data["ens"].select(number=members[0]) t = title.build(dummy) desc.extend([dw[-1], t, dummy, cont]) return mv.plot(desc, animate=animate)
def plot_xs( *args, map_line=True, map_data=None, line=[], layout="", view=None, area=None, title_font_size=0.3, legend_font_size=0.2, frame=-1, animate="auto", ): """ Plot cross section with map """ assert len(line) == 4 assert len(args) >= 1 assert isinstance(args[0], mv.Fieldset) layers = _make_layers(*args, form_layout=False) assert len(layers) > 0 # build the layout - if no map_data is specified no map view is # added to the layout if not map_line and map_data is None: view = None else: view = _make_view(view, area) dw = Layout().build_xs(line=line, map_view=view) # the plot description desc = [] title = Title(font_size=title_font_size) data_items = [] # build cross section plot desc.append(dw[0]) for layer in layers: data = layer["data"] vd = _make_visdef(data, layer["vd"], plot_type="xs") param_info = data.ds_param_info # print(f"param_info={param_info}") data_items.append(data) # print(f"data={len(data)}") if param_info is not None and param_info.name == "wind3d": xs_d = mv.mcross_sect( data=data, line=line, wind_parallel="on", w_wind_scaling_factor_mode="compute", w_wind_scaling_factor="100", # bottom_level=1015, # top_level=250, # vertical_scaling = "log", # vertical_axis= vertical_axis ) desc.append(xs_d) else: if param_info is not None: if param_info.name == "t": data = data - 273.16 elif param_info.name == "pv": data = data * 1e6 elif param_info.name == "q": data = data * 1e3 elif param_info.name in ["vo", "absv"]: data = data * 1e5 desc.append(data) if vd: desc.extend(vd) # print(f"vd={vd}") t = title.build_xs(data_items) desc.append(t) # LOG.debug(f"desc={desc}") # build side map plot if map_line or map_data is not None: desc.append(dw[1]) t = None if map_data is not None and len(map_data) > 0: layers = _make_layers(map_data, form_layout=False) data_items = [] for layer in layers: data = layer["data"] vd = _make_visdef(data, layer["vd"]) if isinstance(data, mv.Fieldset): data_items.append(data) if frame != -1: data = data[frame] desc.append(data) if vd: desc.extend(vd) if data_items: t = title.build(data_items) if map_line: # define xsection line graph graph = mv.mgraph(graph_line_colour="red", graph_line_thickness=3, graph_symbol="off") lv = mv.input_visualiser( input_plot_type="geo_points", input_longitude_values=[line[1], line[3]], input_latitude_values=[line[0], line[2]], ) desc.extend([lv, graph]) if t is not None: desc.append(t) LOG.debug(f"desc={desc}") return mv.plot(desc, animate=animate)
def plot_diff_maps( *args, view=None, area=None, overlay=None, diff_style=None, pos_values=None, title_font_size=0.4, legend_font_size=0.35, frame=-1, animate="auto", ): """ Plot difference maps """ # handle default arguments pos_values = [] if pos_values is None else pos_values diff_style = [] if diff_style is None else diff_style if not isinstance(diff_style, list): diff_style = [diff_style] # define the view view = _make_view(view, area, plot_type="diff") # build the layout dw = Layout().build_diff(view=view) data = {} vd = {} # the positional arguments has the following order: # data1, visdef1.1 visdef1.2 ... data2, visdef2.1, visdef2.2 ... # the visdef objects are optional! assert len(args) >= 2 assert isinstance(args[0], mv.Fieldset) layers = _make_layers(*args, form_layout=False) assert len(layers) == 2 # LOG.debug(f"layers={layers}") data["0"] = layers[0]["data"] data["1"] = layers[1]["data"] vd["0"] = _make_visdef(data["0"], layers[0]["vd"]) vd["1"] = _make_visdef(data["1"], layers[1]["vd"]) # overlay data ov_data = {} ov_vd = {} if overlay is not None: # single value, list or tuple: a data item that will be plotted into each map if not isinstance(overlay, dict): if isinstance(overlay, tuple): ov_args = list(overlay) else: ov_args = [overlay ] if not isinstance(overlay, list) else overlay # print(ov_args) ov_layers = _make_layers(*ov_args, form_layout=False) # print(ov_layers) assert len(ov_layers) == 1 d = ov_layers[0]["data"] if isinstance(d, Track): d = d.build(style=ov_layers[0]["vd"]) for k in ["d", "0", "1"]: ov_data[k] = d ov_vd[k] = _make_visdef(d, ov_layers[0]["vd"]) else: pass # LOG.debug("len_0={}".format(len(data["0"]))) # LOG.debug("len_1={}".format(len(data["0"]))) # the plot description desc = [] title = Title(font_size=title_font_size) # compute diff data["0"], data["1"] = _prepare_grid(data["0"], data["1"]) data["d"] = data["0"] - data["1"] data["d"]._ds_param_info = data["1"].ds_param_info if data["0"].label and data["1"].label: data["d"]._label = "{}-{}".format(data["0"].label, data["1"].label) else: data["d"]._label = "" vd["d"] = _make_visdef(data["d"], diff_style, plot_type="diff", pos_values=pos_values) # LOG.debug("len_d={}".format(len(data["d"]))) for i, k in enumerate(["d", "0", "1"]): desc.append(dw[i]) if frame == -1: d = data[k] else: d = data[k][frame] d._ds_param_info = data[k]._ds_param_info d._label = data[k]._label desc.append(d) if vd[k]: desc.append(vd[k]) # add overlay if k in ov_data: if isinstance(ov_data[k], mv.Fieldset): dd = ov_data[k] if frame == -1 else ov_data[k][frame] else: dd = ov_data[k] desc.append(dd) if k in ov_vd and ov_vd[k]: desc.append(ov_vd[k]) t = title.build(data[k]) legend = mv.mlegend(legend_text_font_size=legend_font_size) desc.append(legend) desc.append(t) # print(desc) return mv.plot(desc, animate=animate)
def plot_maps( *args, layout=None, view=None, area=None, use_eccharts=False, title_font_size=0.4, legend_font_size=0.35, frame=-1, animate="auto", ): """ Plot maps with generic contents """ # in the positional arguments we have two options: # 1. we only have non-list items. They belong to a single plot page. # 2. we only have list items. Each list item defines a separate plot page. plot_def = _make_layers(*args, form_layout=True) # collect the data items data_items = [] for i, sc_def in enumerate(plot_def): for layer in sc_def: data = layer["data"] if isinstance(data, mv.Fieldset): data_items.append(data[0]) # define the view view = _make_view(view, area, data=data_items) # build the layout num_plot = len(plot_def) dw = Layout().build_grid(page_num=num_plot, layout=layout, view=view) # the plot description desc = [] title = Title(font_size=title_font_size) # build each scene data_id = ("d0", 0) for i, sc_def in enumerate(plot_def): desc.append(dw[i]) # define layers data_items = [] use_data_id = (sum([ 1 for layer in sc_def if isinstance(layer["data"], mv.Fieldset) ]) > 1) for layer in sc_def: data = layer["data"] vd = layer["vd"] if isinstance(data, mv.Fieldset): if use_data_id: data_items.append((data, data_id[0])) else: data_items.append(data) if frame != -1: if data.ds_param_info.scalar: data = data[frame] else: data = data[2 * frame:2 * frame + 2] elif isinstance(data, Track): data = data.build(style=vd) desc.append(data) if isinstance(data, mv.Fieldset): vd = _make_visdef( data, vd, use_eccharts=use_eccharts, style_db="param", plot_type="map", data_id=data_id[0] if use_data_id else None, ) if vd: desc.extend(vd) data_id = (f"d{data_id[1]+1}", data_id[1] + 1) if data_items: legend = mv.mlegend(legend_text_font_size=legend_font_size) desc.append(legend) t = title.build(data_items) # LOG.debug(f"t={t}") desc.append(t) for i in range(len(plot_def), len(dw)): desc.append(dw[i]) LOG.debug(f"desc={desc}") return mv.plot(desc, animate=animate)
mydata = mv.read('../tests/test.grib') derived = mydata * 2 + 5 mv.write('derived_data.grib', derived) grid_shade = mv.mcont( legend=True, contour=False, contour_highlight=True, contour_shade=True, contour_shade_technique='grid_shading', contour_shade_max_level_colour='red', contour_shade_min_level_colour='blue', contour_shade_colour_direction='clockwise', ) # Macro-like PNG creation: png = mv.png_output(output_width=1200, output_name='./myplot') mv.plot(png, derived, grid_shade) # Using a different notation: png_output = { 'output_type': 'png', 'output_width': 1200, 'output_name': './myplot2' } mv.plot(derived, grid_shade, **png_output)
UC-05. The Analyst retrieves certain parameters, computes a derived parameter and plots its values for a specific time. -------------------------------------------------------------------------------- 1. Analyst filters, the chosen parameters of a file from a given source (i.e. MARS, files, observation databases) -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 2. Analyst computes the desired derived parameter (i.e. wind velocity from zonal and meridional components) -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 3. Analyst plots the derived parameter values -------------------------------------------------------------------------------- """ import metview as mv uv = mv.read('./uv.grib') u = mv.read(data=uv, param='u') v = mv.read(data=uv, param='v') wind_speed = mv.sqrt(u * u + v * v) mv.setoutput(mv.png_output(output_width=1000, output_name='./uvplot')) mv.plot(wind_speed)