def generate_image(global_data, filename): """ This function generates an RGB composite directly from a scene with loaded channels and saves to a GeoTiff :param global_data: an mpop scene object with data from IR channels 12.0, 10.8, 8.7 :param filename: a string with the name of the image file to be generated """ # Generate a dust composite with Pytroll inbuilt function img = global_data.image.dust() # Save the image initially so it can be read in as an image object img.save("/ouce-home/students/hert4173/SEVIRI_imagery/" + filename) # Read it back in as an image object img = Image.open("/ouce-home/students/hert4173/SEVIRI_imagery/" + filename) # Define projection parameters proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 ' \ '+h=35785831.0' area_extent = (-2000000, 0, 3000000, 4000000) area_def = (proj4_string, area_extent) # ContourWriterAGG here requires the 'aggdraw' package cw = ContourWriterAGG( '/ouce-home/students/hert4173/.conda_envs/virtual_env/lib/python2.7/' 'pycoast/GSHHS_DATA_ROOT') cw.add_coastlines(img, area_def, resolution='i', width=3) cw.add_borders(img, area_def, outline=(255, 255, 255), resolution='i', width=3) img.save("/ouce-home/students/hert4173/SEVIRI_imagery/" + filename)
def test_europe_agg(self): from pycoast import ContourWriterAGG euro_img = Image.open( os.path.join(os.path.dirname(__file__), 'contours_europe_agg.png')) euro_data = np.array(euro_img) img = Image.new('RGB', (640, 480)) proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84' area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1) area_def = (proj4_string, area_extent) cw = ContourWriterAGG(gshhs_root_dir) cw.add_coastlines(img, area_def, resolution='l', level=4) cw.add_rivers(img, area_def, level=5, outline='blue', width=0.5, outline_opacity=127) cw.add_borders(img, area_def, outline=(255, 0, 0), width=3, outline_opacity=32) res = np.array(img) self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed for AGG')
def add_overlay(orig, area, coast_dir, color=(0, 0, 0), width=0.5, resolution=None): """Add coastline and political borders to image, using *color* (tuple of integers between 0 and 255). Warning: Loses the masks ! *resolution* is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | | 'h' | High resolution | 0.2 km | | 'i' | Intermediate resolution | 1.0 km | | 'l' | Low resolution | 5.0 km | | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ """ img = orig.pil_image() if area is None: raise ValueError("Area of image is None, can't add overlay.") from satpy.resample import get_area_def if isinstance(area, str): area = get_area_def(area) LOG.info("Add coastlines and political borders to image.") if resolution is None: x_resolution = ((area.area_extent[2] - area.area_extent[0]) / area.x_size) y_resolution = ((area.area_extent[3] - area.area_extent[1]) / area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" LOG.debug("Automagically choose resolution " + resolution) from pycoast import ContourWriterAGG cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, area, outline=color, resolution=resolution, width=width) cw_.add_borders(img, area, outline=color, resolution=resolution, width=width) arr = np.array(img) if len(orig.channels) == 1: orgi.channels[0] = np.ma.array(arr[:, :] / 255.0) else: for idx in range(len(orig.channels)): orig.channels[idx] = np.ma.array(arr[:, :, idx] / 255.0)
def add_overlay(orig, area, coast_dir, color=(0, 0, 0), width=0.5, resolution=None, level_coast=1, level_borders=1): """Add coastline and political borders to image, using *color* (tuple of integers between 0 and 255). Warning: Loses the masks ! *resolution* is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | | 'h' | High resolution | 0.2 km | | 'i' | Intermediate resolution | 1.0 km | | 'l' | Low resolution | 5.0 km | | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ """ if area is None: raise ValueError("Area of image is None, can't add overlay.") from pycoast import ContourWriterAGG if isinstance(area, str): area = get_area_def(area) LOG.info("Add coastlines and political borders to image.") if resolution is None: x_resolution = ((area.area_extent[2] - area.area_extent[0]) / area.x_size) y_resolution = ((area.area_extent[3] - area.area_extent[1]) / area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" LOG.debug("Automagically choose resolution %s", resolution) img = orig.pil_image() cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, area, outline=color, resolution=resolution, width=width, level=level_coast) cw_.add_borders(img, area, outline=color, resolution=resolution, width=width, level=level_borders) arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE) orig.data = xr.DataArray(arr, dims=['y', 'x', 'bands'], coords={'y': orig.data.coords['y'], 'x': orig.data.coords['x'], 'bands': list(img.mode)})
def layout(self): self.layouter.layout() cw = ContourWriterAGG(self.layouter.shapes) LOGGER.debug("Add border layout (resolution %s, level %s)" % (self.resolution, BorderLayouter.MAX_LEVEL)) cw.add_borders(self.layouter.image, self.layouter.area, resolution=self.resolution, level=1)
def layout(self): self.layouter.layout() cw = ContourWriterAGG(self.layouter.shapes) LOGGER.debug("Add border layout (resolution %s, level %s)" % (self.resolution, BorderLayouter.MAX_LEVEL)) cw.add_borders(self.layouter.image, self.layouter.area, resolution=self.resolution, level=1)
def test_add_points_agg(self): from pycoast import ContourWriterAGG from pyresample.geometry import AreaDefinition font_file = os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf') grid_img = Image.open( os.path.join(os.path.dirname(__file__), 'nh_points_agg.png')) grid_data = np.array(grid_img) img = Image.new('RGB', (1024, 1024), (255, 255, 255)) proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m' area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625) area_def = AreaDefinition('nh', 'nh', 'nh', proj4_string, 1024, 1024, area_extent) cw = ContourWriterAGG(gshhs_root_dir) cw.add_coastlines(img, area_def, outline='black', resolution='l', level=4) cw.add_borders(img, area_def, outline='black', width=3, level=1, resolution='c') points_list = [((2.3522, 48.8566), 'Paris'), ((0.1278, 51.5074), 'London')] cw.add_points(img, area_def, points_list=points_list, font_file=font_file, symbol='circle', ptsize=16, outline='black', width=3, fill='red', fill_opacity=128, box_outline='blue', box_linewidth=0.5, box_fill='yellow', box_opacity=200) res = np.array(img) self.assertTrue(fft_metric(grid_data, res), 'Writing of nh points failed')
def test_europe_agg(self): from pycoast import ContourWriterAGG euro_img = Image.open(os.path.join(os.path.dirname(__file__), 'contours_europe_agg.png')) euro_data = np.array(euro_img) img = Image.new('RGB', (640, 480)) proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84' area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1) area_def = (proj4_string, area_extent) cw = ContourWriterAGG(gshhs_root_dir) cw.add_coastlines(img, area_def, resolution='l', level=4) cw.add_rivers(img, area_def, level=5, outline='blue', width=0.5, outline_opacity=127) cw.add_borders(img, area_def, outline=(255, 0, 0), width=3, outline_opacity=32) res = np.array(img) self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed for AGG')
def add_overlay(self, color=(0, 0, 0), width=0.5, resolution=None): """Add coastline and political borders to image, using *color* (tuple of integers between 0 and 255). Warning: Loses the masks ! *resolution* is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | | 'h' | High resolution | 0.2 km | | 'i' | Intermediate resolution | 1.0 km | | 'l' | Low resolution | 5.0 km | | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ """ img = self.pil_image() import ConfigParser conf = ConfigParser.ConfigParser() conf.read(os.path.join(CONFIG_PATH, "mpop.cfg")) coast_dir = conf.get('shapes', 'dir') logger.debug("Getting area for overlay: " + str(self.area)) if self.area is None: raise ValueError("Area of image is None, can't add overlay.") from mpop.projector import get_area_def if isinstance(self.area, str): self.area = get_area_def(self.area) logger.info("Add coastlines and political borders to image.") logger.debug("Area = " + str(self.area)) if resolution is None: x_resolution = ((self.area.area_extent[2] - self.area.area_extent[0]) / self.area.x_size) y_resolution = ((self.area.area_extent[3] - self.area.area_extent[1]) / self.area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" logger.debug("Automagically choose resolution " + resolution) from pycoast import ContourWriterAGG cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, self.area, outline=color, resolution=resolution, width=width) cw_.add_borders(img, self.area, outline=color, resolution=resolution, width=width) arr = np.array(img) if len(self.channels) == 1: self.channels[0] = np.ma.array(arr[:, :] / 255.0) else: for idx in range(len(self.channels)): self.channels[idx] = np.ma.array(arr[:, :, idx] / 255.0)
outline='white', resolution=resolution, outline_opacity=127, width=1, level=2) #, outline_opacity=0 outline = (255, 0, 0) outline = 'red' cw.add_coastlines(PIL_image, area_def, outline=outline, resolution=resolution, width=2) #, outline_opacity=0 cw.add_borders(PIL_image, area_def, outline=outline, resolution=resolution, width=2) #, outline_opacity=0 add_logos = 1 add_colorscale = 0 add_title = 1 verbose = 1 layer = ' 2nd layer' ticks = 20 tick_marks = 20 # default minor_tick_marks = 10 # default title_color = 'white' units = global_data[prop_str].info["units"] #global_data[prop_str].units
if add_borders: from pycoast import ContourWriterAGG # define contour write for coasts, borders, rivers cw = ContourWriterAGG('/data/OWARNA/hau/maps_pytroll/') # define area from mpop.projector import get_area_def # obj_area = get_area_def('ccs4') proj4_string = obj_area.proj4_string # e.g. proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0' area_extent = obj_area.area_extent # e.g. area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612) area_def = (proj4_string, area_extent) resolution = 'h' cw.add_borders(PIL_image, area_def, outline=(255, 0, 0), resolution=resolution, width=1) #, outline_opacity=0 if False: print('... add cell velocities') from math import isnan print("traj_ID Rank x0 y0 vx vy") for traj in global_data.traj_IDs: if global_data.TRT[traj].RANKr > min_rank: x0 = global_data.TRT[traj].jCH y0 = global_data.TRT[traj].iCH
def plot_msg(in_msg): # get date of the last SEVIRI observation if in_msg.datetime == None: in_msg.get_last_SEVIRI_date() yearS = str(in_msg.datetime.year) #yearS = yearS[2:] monthS = "%02d" % in_msg.datetime.month dayS = "%02d" % in_msg.datetime.day hourS = "%02d" % in_msg.datetime.hour minS = "%02d" % in_msg.datetime.minute dateS=yearS+'-'+monthS+'-'+dayS timeS=hourS+'-'+minS if in_msg.sat_nr==None: in_msg.sat_nr=choose_msg(in_msg.datetime,in_msg.RSS) if in_msg.datetime.year > 2012: if in_msg.sat_nr == 8: area_loaded = get_area_def("EuropeCanary35") elif in_msg.sat_nr == 9: # rapid scan service satellite area_loaded = get_area_def("EuropeCanary95") elif in_msg.sat_nr == 10: # default satellite area_loaded = get_area_def("met09globeFull") # full disk service, like EUMETSATs NWC-SAF products elif in_msg.sat_nr == 0: # fake satellite for reprojected ccs4 data in netCDF area_loaded = get_area_def("ccs4") # #area_loaded = get_area_def("EuropeCanary") #area_loaded = get_area_def("alps") # new projection of SAM else: print("*** Error, unknown satellite number ", in_msg.sat_nr) area_loaded = get_area_def("hsaf") # else: if in_msg.sat_nr == 8: area_loaded = get_area_def("EuropeCanary95") elif in_msg.sat_nr == 9: # default satellite area_loaded = get_area_def("EuropeCanary") # define contour write for coasts, borders, rivers cw = ContourWriterAGG(in_msg.mapDir) if type(in_msg.sat_nr) is int: sat_nr_str = str(in_msg.sat_nr).zfill(2) elif type(in_msg.sat_nr) is str: sat_nr_str = in_msg.sat_nr else: print("*** Waring, unknown type of sat_nr", type(in_msg.sat_nr)) sat_nr_str = in_msg.sat_nr if in_msg.verbose: print('*** Create plots for ') print(' Satellite/Sensor: '+in_msg.sat + ' ' + sat_nr_str) print(' Date/Time: '+dateS +' '+hourS+':'+minS+'UTC') print(' RGBs: ', in_msg.RGBs) print(' Area: ', in_msg.areas) # check if input data is complete if in_msg.verbose: print("*** check input data") RGBs = check_input(in_msg, in_msg.sat+sat_nr_str, in_msg.datetime) if len(RGBs) != len(in_msg.RGBs): print("*** Warning, input not complete.") print("*** Warning, process only: ", RGBs) # define satellite data object global_data = GeostationaryFactory.create_scene(in_msg.sat, sat_nr_str, "seviri", in_msg.datetime) # print "type(global_data) ", type(global_data) # <class 'mpop.scene.SatelliteInstrumentScene'> # print "dir(global_data)", dir(global_data) [..., '__init__', ... 'area', 'area_def', 'area_id', 'channel_list', 'channels', # 'channels_to_load', 'check_channels', 'fullname', 'get_area', 'image', 'info', 'instrument_name', 'lat', 'load', 'loaded_channels', # 'lon', 'number', 'orbit', 'project', 'remove_attribute', 'satname', 'save', 'set_area', 'time_slot', 'unload', 'variant'] ## define satellite data object one scan before #if in_msg.RSS: # scan_time = 5 # min #else: # scan_time = 15 # min scan_time = 15 # min datetime_m1 = in_msg.datetime - timedelta(minutes=scan_time) global_data_m1 = GeostationaryFactory.create_scene(in_msg.sat, sat_nr_str, "seviri", datetime_m1) if len(RGBs) == 0: return RGBs if in_msg.verbose: print("*** load satellite channels for "+in_msg.sat+sat_nr_str+" ", global_data.fullname) # initialize processed RGBs RGBs_done=[] # load reflectivities, brightness temperatures, NWC-SAF products ... print("*** read ", str(in_msg.datetime)) area_loaded = load_products(global_data, RGBs, in_msg, area_loaded) #print "*** read ", str(datetime_m1) #area_loaded = load_products(global_data_m1, RGBs, in_msg, area_loaded) # check if all prerequisites are loaded #rgb_complete = [] #for rgb in RGBs: # all_loaded = True # if rgb in products.RGBs_buildin or rgb in products.RGB_user: # obj_image = get_image(global_data, rgb) # for pre in obj_image.prerequisites: # if pre not in loaded_channels: # all_loaded = False # elif rgb in products.MSG_color: # if rgb.replace("c","") not in loaded_channels: # all_loaded = False # else: # if rgb not in loaded_channels: # all_loaded = False # if all_loaded: # rgb_complete.append(rgb) #print "rgb_complete", rgb_complete # preprojecting the data to another area # -------------------------------------- for area in in_msg.areas: print("") obj_area = get_area_def(area) # reproject data to new area if obj_area == area_loaded: if in_msg.verbose: print("*** Use data for the area loaded: ", area) #obj_area = area_loaded data = global_data data_m1 = global_data_m1 resolution='l' else: if in_msg.verbose: print("*** Reproject data to area: ", area, "(org projection: ", area_loaded.name, ")") obj_area = get_area_def(area) # PROJECT data to new area data = global_data.project(area, precompute=True) data_m1 = global_data_m1.project(area, precompute=True) resolution='i' loaded_products = [chn.name for chn in data.loaded_channels()] print(loaded_products) #loaded_products_m1 = [chn.name for chn in data_m1.loaded_channels()] #print loaded_products_m1 #for prod in loaded_products: # print "xxx ", prod # print data_m1[prod] # data[prod] = data[prod] - data_m1[prod] # # save reprojected data if area in in_msg.save_reprojected_data: save_reprojected_data(data, area, in_msg) # apply a mask to the data (switched off at the moment) if False: mask_data(data, area) # save average values if in_msg.save_statistics: mean_array = zeros(len(RGBs)) #statisticFile = '/data/COALITION2/database/meteosat/ccs4/'+yearS+'/'+monthS+'/'+dayS+'/MSG_'+area+'_'+yearS[2:]+monthS+dayS+'.txt' statisticFile = './'+yearS+'-'+monthS+'-'+dayS+'/MSG_'+area+'_'+yearS[2:]+monthS+dayS+'.txt' if in_msg.verbose: print("*** write statistics (average values) to "+statisticFile) f1 = open(statisticFile,'a') # mode append i_rgb=0 for rgb in RGBs: if rgb in products.MSG_color: mean_array[i_rgb]=data[rgb.replace("c","")].data.mean() i_rgb=i_rgb+1 # create string to write str2write = dateS +' '+hourS+' : '+minS+' UTC ' for mm in mean_array: str2write = str2write+' '+ "%7.2f" % mm str2write = str2write+"\n" f1.write(str2write) f1.close() # creating plots/images if in_msg.make_plots: # choose map resolution resolution = choose_map_resolution(area, in_msg.mapResolution) # define area proj4_string = obj_area.proj4_string # e.g. proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0' area_extent = obj_area.area_extent # e.g. area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612) area_tuple = (proj4_string, area_extent) for rgb in RGBs: PIL_image = create_PIL_image(rgb, data, in_msg) # !!! in_msg.colorbar[rgb] is initialized inside (give attention to rgbs) !!! if in_msg.add_rivers: if in_msg.verbose: print(" add rivers to image (resolution="+resolution+")") cw.add_rivers(PIL_image, area_tuple, outline='blue', resolution=resolution, outline_opacity=127, width=0.5, level=5) # if in_msg.verbose: print(" add lakes to image (resolution="+resolution+")") cw.add_coastlines(PIL_image, area_tuple, outline='blue', resolution=resolution, outline_opacity=127, width=0.5, level=2) #, outline_opacity=0 if in_msg.add_borders: if in_msg.verbose: print(" add coastlines to image (resolution="+resolution+")") cw.add_coastlines(PIL_image, area_tuple, outline=(255, 0, 0), resolution=resolution, width=1) #, outline_opacity=0 if in_msg.verbose: print(" add borders to image (resolution="+resolution+")") cw.add_borders(PIL_image, area_tuple, outline=(255, 0, 0), resolution=resolution, width=1) #, outline_opacity=0 #if area.find("EuropeCanary") != -1 or area.find("ccs4") != -1: dc = DecoratorAGG(PIL_image) # add title to image if in_msg.add_title: add_title(PIL_image, rgb, int(data.number), dateS, hourS, minS, area, dc, in_msg.font_file, in_msg.verbose ) # add MeteoSwiss and Pytroll logo if in_msg.add_logos: if in_msg.verbose: print('... add logos') dc.align_right() if in_msg.add_colorscale: dc.write_vertically() dc.add_logo("../logos/meteoSwiss3.jpg",height=60.0) dc.add_logo("../logos/pytroll3.jpg",height=60.0) # add colorscale if in_msg.add_colorscale and in_msg.colormap[rgb] != None: add_colorscale(dc, rgb, in_msg) # create output filename outputDir = format_name(in_msg.outputDir, data.time_slot, area=area, rgb=rgb, sat_nr=data.number) outputFile = outputDir + format_name(in_msg.outputFile, data.time_slot, area=area, rgb=rgb, sat_nr=data.number) # check if output directory exists, if not create it path= dirname(outputFile) if not exists(path): if in_msg.verbose: print('... create output directory: ' + path) makedirs(path) # save file if in_msg.verbose: print('... save final file :' + outputFile) PIL_image.save(outputFile, optimize=True) # optimize -> minimize file size if in_msg.compress_to_8bit: if in_msg.verbose: print('... compress to 8 bit image: display '+outputFile.replace(".png","-fs8.png")+' &') subprocess.call("/usr/bin/pngquant -force 256 "+outputFile+" 2>&1 &", shell=True) # 256 == "number of colors" #if in_msg.verbose: # print " add coastlines to "+outputFile ## alternative: reopen image and modify it (takes longer due to additional reading and saving) #cw.add_rivers_to_file(img, area_tuple, level=5, outline='blue', width=0.5, outline_opacity=127) #cw.add_coastlines_to_file(outputFile, obj_area, resolution=resolution, level=4) #cw.add_borders_to_file(outputFile, obj_area, outline=outline, resolution=resolution) # copy to another place if in_msg.scpOutput: if in_msg.verbose: print("... secure copy "+outputFile+ " to "+in_msg.scpOutputDir) subprocess.call("scp "+in_msg.scpID+" "+outputFile+" "+in_msg.scpOutputDir+" 2>&1 &", shell=True) if in_msg.compress_to_8bit: if in_msg.verbose: print("... secure copy "+outputFile.replace(".png","-fs8.png")+ " to "+in_msg.scpOutputDir) subprocess.call("scp "+in_msg.scpID+" "+outputFile.replace(".png","-fs8.png")+" "+in_msg.scpOutputDir+" 2>&1 &", shell=True) if rgb not in RGBs_done: RGBs_done.append(rgb) ## start postprocessing if area in in_msg.postprocessing_areas: postprocessing(in_msg, global_data.time_slot, data.number, area) if in_msg.verbose: print(" ") return RGBs_done
def main(): parser = get_parser() args = parser.parse_args() levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] logging.basicConfig(level=levels[min(3, args.verbosity)]) if args.output_filename is None: args.output_filename = [x[:-3] + "png" for x in args.input_tiff] else: assert len(args.output_filename) == len( args.input_tiff ), "Output filenames must be equal to number of input tiffs" if not (args.add_borders or args.add_coastlines or args.add_grid or args.add_rivers or args.add_colorbar): LOG.error( "Please specify one of the '--add-X' options to modify the image") return -1 # we may be dealing with large images that look like decompression bombs # let's turn off the check for the image size in PIL/Pillow Image.MAX_IMAGE_PIXELS = None for input_tiff, output_filename in zip(args.input_tiff, args.output_filename): LOG.info("Creating {} from {}".format(output_filename, input_tiff)) gtiff = gdal.Open(input_tiff) proj4_str = osr.SpatialReference(gtiff.GetProjection()).ExportToProj4() ul_x, res_x, _, ul_y, _, res_y = gtiff.GetGeoTransform() half_pixel_x = res_x / 2. half_pixel_y = res_y / 2. area_extent = ( ul_x - half_pixel_x, # lower-left X ul_y + res_y * gtiff.RasterYSize - half_pixel_y, # lower-left Y ul_x + res_x * gtiff.RasterXSize + half_pixel_x, # upper-right X ul_y + half_pixel_y, # upper-right Y ) img = Image.open(input_tiff).convert('RGBA' if gtiff.RasterCount in ( 2, 4) else 'RGB') area_def = (proj4_str, area_extent) cw = ContourWriterAGG(args.shapes_dir) if args.add_coastlines: outline = args.coastlines_outline[0] if len( args.coastlines_outline) == 1 else tuple( int(x) for x in args.coastlines_outline) if args.coastlines_fill: fill = args.coastlines_fill[0] if len( args.coastlines_fill) == 1 else tuple( int(x) for x in args.coastlines_fill) else: fill = None cw.add_coastlines(img, area_def, resolution=args.coastlines_resolution, level=args.coastlines_level, width=args.coastlines_width, outline=outline, fill=fill) if args.add_rivers: outline = args.rivers_outline[0] if len( args.rivers_outline) == 1 else tuple( int(x) for x in args.rivers_outline) cw.add_rivers(img, area_def, resolution=args.rivers_resolution, level=args.rivers_level, width=args.rivers_width, outline=outline) if args.add_borders: outline = args.borders_outline[0] if len( args.borders_outline) == 1 else tuple( int(x) for x in args.borders_outline) cw.add_borders(img, area_def, resolution=args.borders_resolution, level=args.borders_level, outline=outline, width=args.borders_width) if args.add_grid: outline = args.grid_outline[0] if len( args.grid_outline) == 1 else tuple( int(x) for x in args.grid_outline) minor_outline = args.grid_minor_outline[0] if len( args.grid_minor_outline) == 1 else tuple( int(x) for x in args.grid_minor_outline) fill = args.grid_fill[0] if len(args.grid_fill) == 1 else tuple( int(x) for x in args.grid_fill) font_path = find_font(args.grid_font, args.grid_text_size) font = Font(outline, font_path, size=args.grid_text_size) cw.add_grid(img, area_def, args.grid_D, args.grid_d, font, fill=fill, outline=outline, minor_outline=minor_outline, write_text=args.grid_text, width=args.grid_width, lon_placement=args.grid_lon_placement, lat_placement=args.grid_lat_placement) if args.add_colorbar: from pydecorate import DecoratorAGG font_color = args.colorbar_text_color font_color = font_color[0] if len(font_color) == 1 else tuple( int(x) for x in font_color) font_path = find_font(args.colorbar_font, args.colorbar_text_size) # this actually needs an aggdraw font font = Font(font_color, font_path, size=args.colorbar_text_size) band_count = gtiff.RasterCount if band_count not in [1, 2]: raise ValueError("Can't add colorbar to RGB/RGBA image") # figure out what colormap we are dealing with band = gtiff.GetRasterBand(1) cmap = get_colormap(band, band_count) # figure out our limits vmin = args.colorbar_min vmax = args.colorbar_max metadata = gtiff.GetMetadata_Dict() vmin = vmin or metadata.get('min_in') vmax = vmax or metadata.get('max_in') if isinstance(vmin, str): vmin = float(vmin) if isinstance(vmax, str): vmax = float(vmax) if vmin is None or vmax is None: data = gtiff.GetRasterBand(1).ReadAsArray() vmin = vmin or np.iinfo(data.dtype).min vmax = vmax or np.iinfo(data.dtype).max cmap.set_range(vmin, vmax) dc = DecoratorAGG(img) if args.colorbar_align == 'top': dc.align_top() elif args.colorbar_align == 'bottom': dc.align_bottom() elif args.colorbar_align == 'left': dc.align_left() elif args.colorbar_align == 'right': dc.align_right() if args.colorbar_vertical: dc.write_vertically() else: dc.write_horizontally() if args.colorbar_width is None or args.colorbar_height is None: LOG.warning("'--colorbar-width' or '--colorbar-height' were " "not specified. Forcing '--colorbar-extend'.") args.colorbar_extend = True kwargs = {} if args.colorbar_width: kwargs['width'] = args.colorbar_width if args.colorbar_height: kwargs['height'] = args.colorbar_height dc.add_scale(cmap, extend=args.colorbar_extend, font=font, line=font_color, tick_marks=args.colorbar_tick_marks, title=args.colorbar_title, unit=args.colorbar_units, **kwargs) img.save(output_filename)
PIL_image = img.pil_image() from pycoast import ContourWriterAGG cw = ContourWriterAGG('/opt/users/common/shapes/') obj_area = get_area_def(area) area_def = (obj_area.proj4_string, obj_area.area_extent) resolution = 'l' cw.add_coastlines(PIL_image, area_def, outline='white', resolution=resolution, outline_opacity=127, width=1, level=2) cw.add_borders(PIL_image, area_def, outline='white', resolution=resolution, width=1) #, outline_opacity=0 add_colorscale = True if add_colorscale: print('... add colorscale ranging from min_radar (', min_radar, ') to max_radar (', max_radar, ')') from pydecorate import DecoratorAGG dc = DecoratorAGG(PIL_image) dc.align_right() dc.write_vertically() ticks = 20 tick_marks = 20 # default minor_tick_marks = 10 # default fontsize = 18
def scatter_rad_rcz(in_msg): # get date of the last SEVIRI observation if in_msg.datetime is None: in_msg.get_last_SEVIRI_date() yearS = str(in_msg.datetime.year) #yearS = yearS[2:] monthS = "%02d" % in_msg.datetime.month dayS = "%02d" % in_msg.datetime.day hourS = "%02d" % in_msg.datetime.hour minS = "%02d" % in_msg.datetime.minute dateS = yearS + '-' + monthS + '-' + dayS timeS = hourS + '-' + minS if in_msg.sat_nr is None: in_msg.sat_nr = choose_msg(in_msg.datetime, in_msg.RSS) # check if PyResample is loaded try: # Work around for on demand import of pyresample. pyresample depends # on scipy.spatial which memory leaks on multiple imports IS_PYRESAMPLE_LOADED = False from pyresample import geometry from mpop.projector import get_area_def IS_PYRESAMPLE_LOADED = True except ImportError: LOGGER.warning( "pyresample missing. Can only work in satellite projection") if in_msg.datetime.year > 2012: if in_msg.sat_nr == 8: area_loaded = get_area_def("EuropeCanary35") elif in_msg.sat_nr == 9: # rapid scan service satellite area_loaded = get_area_def("EuropeCanary95") elif in_msg.sat_nr == 10: # default satellite area_loaded = get_area_def( "met09globeFull" ) # full disk service, like EUMETSATs NWC-SAF products elif in_msg.sat_nr == 0: # fake satellite for reprojected ccs4 data in netCDF area_loaded = get_area_def("ccs4") # #area_loaded = get_area_def("EuropeCanary") #area_loaded = get_area_def("alps") # new projection of SAM else: print("*** Error, unknown satellite number ", in_msg.sat_nr) area_loaded = get_area_def("hsaf") # else: if in_msg.sat_nr == 8: area_loaded = get_area_def("EuropeCanary95") elif in_msg.sat_nr == 9: # default satellite area_loaded = get_area_def("EuropeCanary") # define contour write for coasts, borders, rivers cw = ContourWriterAGG(in_msg.mapDir) if type(in_msg.sat_nr) is int: sat_nr_str = str(in_msg.sat_nr).zfill(2) elif type(in_msg.sat_nr) is str: sat_nr_str = in_msg.sat_nr else: print("*** Waring, unknown type of sat_nr", type(in_msg.sat_nr)) sat_nr_str = in_msg.sat_nr if in_msg.verbose: print('*** Create plots for ') print(' Satellite/Sensor: ' + in_msg.sat + ' ' + sat_nr_str) print(' Date/Time: ' + dateS + ' ' + hourS + ':' + minS + 'UTC') print(' RGBs: ', in_msg.RGBs) print(' Area: ', in_msg.areas) # check if input data is complete if in_msg.verbose: print("*** check input data") RGBs = check_input(in_msg, in_msg.sat + sat_nr_str, in_msg.datetime) if len(RGBs) != len(in_msg.RGBs): print("*** Warning, input not complete.") print("*** Warning, process only: ", RGBs) # define time and data object global_data = GeostationaryFactory.create_scene(in_msg.sat, sat_nr_str, "seviri", in_msg.datetime) # print "type(global_data) ", type(global_data) # <class 'mpop.scene.SatelliteInstrumentScene'> # print "dir(global_data)", dir(global_data) [..., '__init__', ... 'area', 'area_def', 'area_id', 'channel_list', 'channels', # 'channels_to_load', 'check_channels', 'fullname', 'get_area', 'image', 'info', 'instrument_name', 'lat', 'load', 'loaded_channels', # 'lon', 'number', 'orbit', 'project', 'remove_attribute', 'satname', 'save', 'set_area', 'time_slot', 'unload', 'variant'] global_data_radar = GeostationaryFactory.create_scene( "swissradar", "", "radar", in_msg.datetime) global_data_radar.load(['precip']) if len(RGBs) == 0: return RGBs if in_msg.verbose: print( "*** load satellite channels for " + in_msg.sat + sat_nr_str + " ", global_data.fullname) # initialize processed RGBs RGBs_done = [] # load all channels / information for rgb in RGBs: if in_msg.verbose: print(" load prerequisites for: ", rgb) if rgb in products.MSG or rgb in products.MSG_color: for channel in products.MSG: if rgb.find( channel ) != -1: # if a channel name (IR_108) is in the rgb name (IR_108c) if in_msg.verbose: print(" load prerequisites by name: ", channel) if in_msg.reader_level is None: global_data.load( [channel], area_extent=area_loaded.area_extent ) # try all reader levels load the corresponding data else: global_data.load([channel], area_extent=area_loaded.area_extent, reader_level=in_msg.reader_level ) # load the corresponding data if rgb in products.RGBs_buildin or rgb in products.RGBs_user: obj_image = get_image(global_data, rgb) # find corresponding RGB image object if in_msg.verbose: print(" load prerequisites by function: ", obj_image.prerequisites) global_data.load( obj_image.prerequisites, area_extent=area_loaded.area_extent) # load prerequisites if rgb in products.CMa or rgb in products.CT or rgb in products.CTTH or rgb in products.SPhR: if rgb in products.CMa: pge = "CloudMask" elif rgb in products.CT: pge = "CloudType" elif rgb in products.CTTH: pge = "CTTH" elif rgb in products.SPhR: pge = "SPhR" else: print("*** Error in scatter_rad_rcz (" + inspect.getfile(inspect.currentframe()) + ")") print(" unknown NWC-SAF PGE ", rgb) quit() if in_msg.verbose: print(" load NWC-SAF product: " + pge) global_data.load( [pge], calibrate=in_msg.nwcsaf_calibrate, reader_level="seviri-level3" ) # False, area_extent=area_loaded.area_extent (difficulties to find correct h5 input file) #print global_data.loaded_channels() #loaded_channels = [chn.name for chn in global_data.loaded_channels()] #if pge not in loaded_channels: # return [] if area_loaded != global_data[pge].area: print("*** Warning: NWC-SAF input file on a differnt grid (" + global_data[pge].area.name + ") than suggested input area (" + area_loaded.name + ")") print(" use " + global_data[pge].area.name + " as standard grid") area_loaded = global_data[pge].area convert_NWCSAF_to_radiance_format(global_data, area_loaded, rgb, IS_PYRESAMPLE_LOADED) if rgb in products.HSAF: if in_msg.verbose: print(" load hsaf product by name: ", rgb) global_data.load( [rgb] ) # , area_extent=area_loaded.area_extent load the corresponding data if in_msg.HRV_enhancement: # load also the HRV channel (there is a check inside in the load function, if the channel is already loaded) if in_msg.verbose: print( " load additionally the HRV channel for HR enhancement") global_data.load(["HRV"], area_extent=area_loaded.area_extent) # loaded_channels = [chn.name for chn in global_data.loaded_channels()] # print loaded_channels # check if all prerequisites are loaded #rgb_complete = [] #for rgb in RGBs: # all_loaded = True # if rgb in products.RGBs_buildin or rgb in products.RGB_user: # obj_image = get_image(global_data, rgb) # for pre in obj_image.prerequisites: # if pre not in loaded_channels: # all_loaded = False # elif rgb in products.MSG_color: # if rgb.replace("c","") not in loaded_channels: # all_loaded = False # else: # if rgb not in loaded_channels: # all_loaded = False # if all_loaded: # rgb_complete.append(rgb) #print "rgb_complete", rgb_complete # preprojecting the data to another area # -------------------------------------- for area in in_msg.areas: print("") obj_area = get_area_def(area) if obj_area == area_loaded: if in_msg.verbose: print("*** Use data for the area loaded: ", area) #obj_area = area_loaded data = global_data resolution = 'l' else: if in_msg.verbose: print("*** Reproject data to area: ", area, "(org projection: ", area_loaded.name, ")") obj_area = get_area_def(area) # PROJECT data to new area data = global_data.project(area) resolution = 'i' if in_msg.mapResolution is None: if area.find("EuropeCanary") != -1: resolution = 'l' if area.find("ccs4") != -1: resolution = 'i' if area.find("ticino") != -1: resolution = 'h' else: resolution = in_msg.mapResolution # define area proj4_string = obj_area.proj4_string # e.g. proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0' area_extent = obj_area.area_extent # e.g. area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612) area_tuple = (proj4_string, area_extent) # save reprojected data if area in in_msg.save_reprojected_data: # and area != area_loaded _sat_nr = int(data.number) - 7 if int(data.number) - 7 > 0 else 0 nc_dir = ( global_data.time_slot.strftime(in_msg.reprojected_data_dir) % { "area": area, "msg": "MSG" + str(_sat_nr) }) nc_file = (global_data.time_slot.strftime( in_msg.reprojected_data_filename) % { "area": area, "msg": "MSG" + str(_sat_nr) }) ncOutputFile = nc_dir + nc_file # check if output directory exists, if not create it path = dirname(ncOutputFile) if not exists(path): if in_msg.verbose: print('... create output directory: ' + path) makedirs(path) if in_msg.verbose: print("... save reprojected data: ncview " + ncOutputFile + " &") #data.save(ncOutputFile, to_format="netcdf4", compression=False) data.save(ncOutputFile, band_axis=0, concatenate_bands=False) # mask for the cloud depths tests (masked data) #if area == 'ccs4': if area == False: print('... apply convective mask') mask_depth = data.image.mask_clouddepth() #print type(mask_depth.max) #print dir(mask_depth.max) index = where( mask_depth < 5) # less than 5 (of 6) tests successfull -> mask out for rgb in RGBs: if rgb in products.MSG_color: rgb2 = rgb.replace("c", "") data[rgb2].data.mask[index] = True fill_value = data[rgb2].data.fill_value #data["IR_108"].data[index] = fill_value #print "data[IR_108].data.min/max ", data["IR_108"].data.min(), data["IR_108"].data.max() #if rgb == "IR_108c": # print type(data["IR_108"].data) # print dir(data["IR_108"].data) #print data["IR_108"].data.mask # save average values if in_msg.save_statistics: mean_array = zeros(len(RGBs)) #statisticFile = '/data/COALITION2/database/meteosat/ccs4/'+yearS+'/'+monthS+'/'+dayS+'/MSG_'+area+'_'+yearS[2:]+monthS+dayS+'.txt' statisticFile = './' + yearS + '-' + monthS + '-' + dayS + '/MSG_' + area + '_' + yearS[ 2:] + monthS + dayS + '.txt' if in_msg.verbose: print("*** write statistics (average values) to " + statisticFile) f1 = open(statisticFile, 'a') # mode append i_rgb = 0 for rgb in RGBs: if rgb in products.MSG_color: mean_array[i_rgb] = data[rgb.replace("c", "")].data.mean() i_rgb = i_rgb + 1 # create string to write str2write = dateS + ' ' + hourS + ' : ' + minS + ' UTC ' for mm in mean_array: str2write = str2write + ' ' + "%7.2f" % mm str2write = str2write + "\n" f1.write(str2write) f1.close() print("y.shape ", global_data_radar['precip'].data.shape) from numpy import copy y = copy(global_data_radar['precip'].data) y = y.ravel() print("y.shape ", y.shape) if 1 == 0: if 'X' in locals(): del X from numpy import column_stack, append, concatenate for rgb in RGBs: # poor mans parallax correction if rgb in products.MSG_color: rgb2 = rgb.replace("c", "") else: rgb2 = rgb x1 = data[rgb2].data.ravel() if 'X' not in locals(): X = x1 X = [X] else: concatenate((X, [x1]), axis=0) print("X.shape ", X.shape) X = append(X, [[1] * len(x1)], axis=1) print("y.shape ", y.shape) #theta = np.linalg.lstsq(X,y)[0] return ind_gt_1 = y > 1 x = x[ind_gt_1] y = y[ind_gt_1] ind_lt_200 = y < 200 x = x[ind_lt_200] y = y[ind_lt_200] #ind_gt_0 = x>0 #x = x[ind_gt_0] #y = y[ind_gt_0] #X = np.column_stack(x+[[1]*len(x[0])]) #beta_hat = np.linalg.lstsq(X,y)[0] #print beta_hat #X_hat= np.dot(X,theta) #y_hat = X_hat.reshape((640, 710)) # creating plots/images if in_msg.make_plots: ind_cloudy = data['CTH'].data > 0 ind_clear = data['CTH'].data <= 0 ind_cloudy = ind_cloudy.ravel() for rgb in RGBs: if rgb in products.MSG_color: rgb2 = rgb.replace("c", "") else: rgb2 = rgb if rgb == 'ir108': rgb2 = 'IR_108' # poor mans parallax correction if 1 == 0: print("... poor mans parallax correction") data[rgb2].data[25:640, :] = data[rgb2].data[0:615, :] #data[rgb2].data[15:640,:] = data[rgb2].data[0:625,:] data[rgb2].data[:, 0:700] = data[rgb2].data[:, 10:710] # create output filename outputDir = format_name(in_msg.outputDir, data.time_slot, area=area, rgb=rgb, sat_nr=data.number) outputFile = outputDir + format_name(in_msg.outputFile, data.time_slot, area=area, rgb=rgb, sat_nr=data.number) PIL_image = create_PIL_image( rgb, data, in_msg ) # !!! in_msg.colorbar[rgb] is initialized inside (give attention to rgbs) !!! if 1 == 1: y = copy(global_data_radar['precip'].data) ind_gt_300 = y > 300 # replace no rain marker with 0mm/h y[ind_gt_300] = 0 y = y.ravel() print("y.shape ", y.shape) x = copy(data[rgb2].data) x = x.ravel() ## get rid of clear sky x = x[ind_cloudy] y = y[ind_cloudy] #ind_gt_01 = x>0.1 #x = x[ind_gt_01] #y = y[ind_gt_01] # get rid of no rain limits for rainfall ind_gt_01 = y > 0.1 x = x[ind_gt_01] y = y[ind_gt_01] ind_lt_300 = y < 300 x = x[ind_lt_300] y = y[ind_lt_300] plt.figure() plt.title('Scatterplot precipitation - radiance') plt.xlabel(rgb) plt.ylabel('precipitation in mm/h') plt.scatter(x, y) #, s=area, c=colors, alpha=0.5 outputDir = format_name(in_msg.outputDir, data.time_slot, area=area, rgb=rgb, sat_nr=data.number) outputFileScatter = outputDir + format_name( 'scatterplot_%(area)s_%Y%m%d%H%M_%(rgb)s_precip_pc.png', data.time_slot, area=area, rgb=rgb, sat_nr=data.number) #plt.show() from numpy import arange x_line = arange(x.min(), x.max(), 1) print("*** display " + outputFileScatter + " &") from numpy import ones, linalg, array print(x.min(), x.max(), y.min(), y.max()) A = array([x, ones(x.size)]) w = linalg.lstsq(A.T, y)[0] # obtaining the parameters y_line = w[0] * x_line + w[1] # regression line #--- #from scipy import stats #slope, intercept, r_value, p_value, std_err = stats.linregress(x,y) #print "slope, intercept, r_value, p_value, std_err" #print slope, intercept, r_value, p_value, std_err #y_line = slope*x_line + intercept from pylab import plot plot(x_line, y_line, 'r-') plt.savefig(outputFileScatter) y_hat = w[0] * data[rgb2].data + w[1] print("y_hat.shape: ", y_hat.shape) # set clear sky to 0 y_hat[ind_clear] = 0 y_hat = ma.asarray(y_hat) y_hat.mask = (y_hat == 9999.9) | (y_hat <= 0.0001) from trollimage.colormap import RainRate colormap = rainbow min_data = 0.0 #max_data=y_hat.max() max_data = 8 colormap.set_range(min_data, max_data) #colormap = RainRate in_msg.colormap[rgb] = colormap units = 'mm/h' img = trollimage(y_hat, mode="L") img.colorize(in_msg.colormap[rgb]) in_msg.colormap[rgb] = colormap.reverse() PIL_image = img.pil_image() outputFile = outputDir + format_name( 'fit_%(area)s_%Y%m%d%H%M_%(rgb)s_precip.png', data.time_slot, area=area, rgb=rgb, sat_nr=data.number) #PIL_image.save(outputFile) ## add coasts, borders, and rivers, database is heree ## http://www.soest.hawaii.edu/pwessel/gshhs/index.html ## possible resolutions ## f full resolution: Original (full) data resolution. ## h high resolution: About 80 % reduction in size and quality. ## i intermediate resolution: Another ~80 % reduction. ## l low resolution: Another ~80 % reduction. ## c crude resolution: Another ~80 % reduction. if in_msg.add_rivers: if in_msg.verbose: print(" add rivers to image (resolution=" + resolution + ")") cw.add_rivers(PIL_image, area_tuple, outline='blue', resolution=resolution, outline_opacity=127, width=0.5, level=5) # if in_msg.verbose: print(" add lakes to image (resolution=" + resolution + ")") cw.add_coastlines(PIL_image, area_tuple, outline='blue', resolution=resolution, outline_opacity=127, width=0.5, level=2) #, outline_opacity=0 if in_msg.add_borders: if in_msg.verbose: print(" add coastlines to image (resolution=" + resolution + ")") cw.add_coastlines(PIL_image, area_tuple, outline=(255, 0, 0), resolution=resolution, width=1) #, outline_opacity=0 if in_msg.verbose: print(" add borders to image (resolution=" + resolution + ")") cw.add_borders(PIL_image, area_tuple, outline=(255, 0, 0), resolution=resolution, width=1) #, outline_opacity=0 #if area.find("EuropeCanary") != -1 or area.find("ccs4") != -1: dc = DecoratorAGG(PIL_image) # add title to image if in_msg.add_title: PIL_image = add_title(PIL_image, rgb, int(data.number), dateS, hourS, minS, area, dc, in_msg.font_file, in_msg.verbose) # add MeteoSwiss and Pytroll logo if in_msg.add_logos: if in_msg.verbose: print('... add logos') dc.align_right() if in_msg.add_colorscale: dc.write_vertically() dc.add_logo("../logos/meteoSwiss3.jpg", height=60.0) dc.add_logo("../logos/pytroll3.jpg", height=60.0) # add colorscale if in_msg.add_colorscale and in_msg.colormap[rgb] is not None: dc.align_right() dc.write_vertically() font_scale = aggdraw.Font( "black", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf", size=16) # get tick marks tick_marks = 20 # default minor_tick_marks = 5 # default if rgb in list(in_msg.tick_marks.keys()): tick_marks = in_msg.tick_marks[rgb] if rgb in list(in_msg.minor_tick_marks.keys()): minor_tick_marks = in_msg.minor_tick_marks[rgb] if rgb.find( "-" ) != -1: # for channel differences use tickmarks of 1 tick_marks = 1 minor_tick_marks = 1 tick_marks = 2 # default minor_tick_marks = 1 # default if in_msg.verbose: print('... add colorscale') dc.add_scale(in_msg.colormap[rgb], extend=True, tick_marks=tick_marks, minor_tick_marks=minor_tick_marks, font=font_scale, line_opacity=100) #, unit='T / K' ## test to plot a wind barb #import matplotlib.pyplot as plt #ax = plt.axes(PIL_image) #ax.barbs(0, 0, 20, 20, length=8, pivot='middle', barbcolor='red') #ax.barbs(8, 46, 20, 20, length=8, pivot='middle', barbcolor='red') # check if output directory exists, if not create it path = dirname(outputFile) if not exists(path): if in_msg.verbose: print('... create output directory: ' + path) makedirs(path) # save file if in_msg.verbose: print('... save final file :' + outputFile) PIL_image.save(outputFile, optimize=True) # optimize -> minimize file size if in_msg.compress_to_8bit: if in_msg.verbose: print('... compress to 8 bit image: display ' + outputFile.replace(".png", "-fs8.png") + ' &') subprocess.call("/usr/bin/pngquant -force 256 " + outputFile + " 2>&1 &", shell=True) # 256 == "number of colors" #if in_msg.verbose: # print " add coastlines to "+outputFile ## alternative: reopen image and modify it (takes longer due to additional reading and saving) #cw.add_rivers_to_file(img, area_tuple, level=5, outline='blue', width=0.5, outline_opacity=127) #cw.add_coastlines_to_file(outputFile, obj_area, resolution=resolution, level=4) #cw.add_borders_to_file(outputFile, obj_area, outline=outline, resolution=resolution) # copy to another place if in_msg.scpOutput: if in_msg.verbose: print("... secure copy " + outputFile + " to " + in_msg.scpOutputDir) subprocess.call("scp " + in_msg.scpID + " " + outputFile + " " + in_msg.scpOutputDir + " 2>&1 &", shell=True) if in_msg.compress_to_8bit: if in_msg.verbose: print("... secure copy " + outputFile.replace(".png", "-fs8.png") + " to " + in_msg.scpOutputDir) subprocess.call( "scp " + in_msg.scpID + " " + outputFile.replace(".png", "-fs8.png") + " " + in_msg.scpOutputDir + " 2>&1 &", shell=True) if rgb not in RGBs_done: RGBs_done.append(rgb) ## start postprocessing if area in in_msg.postprocessing_areas: postprocessing(in_msg, global_data.time_slot, data.number, area) if in_msg.verbose: print(" ") return RGBs_done
resolution = 'l' #if area=='Etna': # resolution='h' #outline = (255, 0, 0) #outline = 'white' #outline = 'red' cw.add_coastlines(PIL_image, area_def, outline='black', resolution=resolution, level=2, width=0.5) #, outline_opacity=127, outline_opacity=0 #cw.add_coastlines(PIL_image, area_def, outline=outline, resolution=resolution, width=2) #, outline_opacity=0 cw.add_borders(PIL_image, area_def, outline='black', resolution=resolution, width=0.5) #, outline_opacity=0 if False: from plot_msg import add_title from pydecorate import DecoratorAGG if socket.gethostname()[0:5] == 'zueub': font_file = "/usr/openv/java/jre/lib/fonts/LucidaTypewriterBold.ttf" elif socket.gethostname()[0:7] == 'keschln' or socket.gethostname( )[0:7] == "eschaln": font_file = "/usr/share/fonts/dejavu/DejaVuSansMono.ttf" else: print("*** ERROR, unknown computer, unknown location of the ttf-file") quit()
def main(): parser = get_parser() args = parser.parse_args() levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] logging.basicConfig(level=levels[min(3, args.verbosity)]) if args.output_filename is None: args.output_filename = [x[:-3] + "png" for x in args.input_tiff] else: assert len(args.output_filename) == len(args.input_tiff), "Output filenames must be equal to number of input tiffs" if not (args.add_borders or args.add_coastlines or args.add_grid or args.add_rivers or args.add_colorbar): LOG.error("Please specify one of the '--add-X' options to modify the image") return -1 # we may be dealing with large images that look like decompression bombs # let's turn off the check for the image size in PIL/Pillow Image.MAX_IMAGE_PIXELS = None for input_tiff, output_filename in zip(args.input_tiff, args.output_filename): LOG.info("Creating {} from {}".format(output_filename, input_tiff)) gtiff = gdal.Open(input_tiff) proj4_str = osr.SpatialReference(gtiff.GetProjection()).ExportToProj4() ul_x, res_x, _, ul_y, _, res_y = gtiff.GetGeoTransform() half_pixel_x = res_x / 2. half_pixel_y = res_y / 2. area_extent = ( ul_x - half_pixel_x, # lower-left X ul_y + res_y * gtiff.RasterYSize - half_pixel_y, # lower-left Y ul_x + res_x * gtiff.RasterXSize + half_pixel_x, # upper-right X ul_y + half_pixel_y, # upper-right Y ) img = Image.open(input_tiff).convert('RGB') area_def = (proj4_str, area_extent) cw = ContourWriterAGG(args.shapes_dir) if args.add_coastlines: outline = args.coastlines_outline[0] if len(args.coastlines_outline) == 1 else tuple(int(x) for x in args.coastlines_outline) if args.coastlines_fill: fill = args.coastlines_fill[0] if len(args.coastlines_fill) == 1 else tuple(int(x) for x in args.coastlines_fill) else: fill = None cw.add_coastlines(img, area_def, resolution=args.coastlines_resolution, level=args.coastlines_level, outline=outline, fill=fill) if args.add_rivers: outline = args.rivers_outline[0] if len(args.rivers_outline) == 1 else tuple(int(x) for x in args.rivers_outline) cw.add_rivers(img, area_def, resolution=args.rivers_resolution, level=args.rivers_level, outline=outline) if args.add_borders: outline = args.borders_outline[0] if len(args.borders_outline) == 1 else tuple(int(x) for x in args.borders_outline) cw.add_borders(img, area_def, resolution=args.borders_resolution, level=args.borders_level, outline=outline) if args.add_grid: outline = args.grid_outline[0] if len(args.grid_outline) == 1 else tuple(int(x) for x in args.grid_outline) minor_outline = args.grid_minor_outline[0] if len(args.grid_minor_outline) == 1 else tuple(int(x) for x in args.grid_minor_outline) fill = args.grid_fill[0] if len(args.grid_fill) == 1 else tuple(int(x) for x in args.grid_fill) font_path = find_font(args.grid_font, args.grid_text_size) font = Font(outline, font_path, size=args.grid_text_size) cw.add_grid(img, area_def, args.grid_D, args.grid_d, font, fill=fill, outline=outline, minor_outline=minor_outline, write_text=args.grid_text, lon_placement=args.grid_lon_placement, lat_placement=args.grid_lat_placement) if args.add_colorbar: from pydecorate import DecoratorAGG font_color = args.colorbar_text_color font_color = font_color[0] if len(font_color) == 1 else tuple(int(x) for x in font_color) font_path = find_font(args.colorbar_font, args.colorbar_text_size) # this actually needs an aggdraw font font = Font(font_color, font_path, size=args.colorbar_text_size) band_count = gtiff.RasterCount if band_count not in [1, 2]: raise ValueError("Can't add colorbar to RGB/RGBA image") # figure out what colormap we are dealing with band = gtiff.GetRasterBand(1) cmap = get_colormap(band, band_count) # figure out our limits vmin = args.colorbar_min vmax = args.colorbar_max metadata = gtiff.GetMetadata_Dict() vmin = vmin or metadata.get('min_in') vmax = vmax or metadata.get('max_in') if isinstance(vmin, str): vmin = float(vmin) if isinstance(vmax, str): vmax = float(vmax) if vmin is None or vmax is None: data = gtiff.GetRasterBand(1).ReadAsArray() vmin = vmin or np.iinfo(data.dtype).min vmax = vmax or np.iinfo(data.dtype).max cmap.set_range(vmin, vmax) dc = DecoratorAGG(img) if args.colorbar_align == 'top': dc.align_top() elif args.colorbar_align == 'bottom': dc.align_bottom() elif args.colorbar_align == 'left': dc.align_left() elif args.colorbar_align == 'right': dc.align_right() if args.colorbar_vertical: dc.write_vertically() else: dc.write_horizontally() if args.colorbar_width is None or args.colorbar_height is None: LOG.warning("'--colorbar-width' or '--colorbar-height' were " "not specified. Forcing '--colorbar-extend'.") args.colorbar_extend = True kwargs = {} if args.colorbar_width: kwargs['width'] = args.colorbar_width if args.colorbar_height: kwargs['height'] = args.colorbar_height dc.add_scale(cmap, extend=args.colorbar_extend, font=font, line=font_color, tick_marks=args.colorbar_tick_marks, title=args.colorbar_title, unit=args.colorbar_units, **kwargs) img.save(output_filename)
def add_overlay(orig, area, coast_dir, color=(0, 0, 0), width=0.5, resolution=None, level_coast=1, level_borders=1, fill_value=None, grid=None): """Add coastline, political borders and grid(graticules) to image. Uses ``color`` for feature colors where ``color`` is a 3-element tuple of integers between 0 and 255 representing (R, G, B). .. warning:: This function currently loses the data mask (alpha band). ``resolution`` is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | +-----+-------------------------+---------+ | 'h' | High resolution | 0.2 km | +-----+-------------------------+---------+ | 'i' | Intermediate resolution | 1.0 km | +-----+-------------------------+---------+ | 'l' | Low resolution | 5.0 km | +-----+-------------------------+---------+ | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ ``grid`` is a dictionary with key values as documented in detail in pycoast eg. overlay={'grid': {'major_lonlat': (10, 10), 'write_text': False, 'outline': (224, 224, 224), 'width': 0.5}} Here major_lonlat is plotted every 10 deg for both longitude and latitude, no labels for the grid lines are plotted, the color used for the grid lines is light gray, and the width of the gratucules is 0.5 pixels. For grid if aggdraw is used, font option is mandatory, if not ``write_text`` is set to False:: font = aggdraw.Font('black', '/usr/share/fonts/truetype/msttcorefonts/Arial.ttf', opacity=127, size=16) """ if area is None: raise ValueError("Area of image is None, can't add overlay.") from pycoast import ContourWriterAGG if isinstance(area, str): area = get_area_def(area) LOG.info("Add coastlines and political borders to image.") if resolution is None: x_resolution = ((area.area_extent[2] - area.area_extent[0]) / area.x_size) y_resolution = ((area.area_extent[3] - area.area_extent[1]) / area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" LOG.debug("Automagically choose resolution %s", resolution) if hasattr(orig, 'convert'): # image must be in RGB space to work with pycoast/pydecorate orig = orig.convert('RGBA' if orig.mode.endswith('A') else 'RGB') elif not orig.mode.startswith('RGB'): raise RuntimeError("'trollimage' 1.6+ required to support adding " "overlays/decorations to non-RGB data.") img = orig.pil_image(fill_value=fill_value) cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, area, outline=color, resolution=resolution, width=width, level=level_coast) cw_.add_borders(img, area, outline=color, resolution=resolution, width=width, level=level_borders) # Only add grid if major_lonlat is given. if grid and 'major_lonlat' in grid and grid['major_lonlat']: major_lonlat = grid.pop('major_lonlat') minor_lonlat = grid.pop('minor_lonlat', major_lonlat) cw_.add_grid(img, area, major_lonlat, minor_lonlat, **grid) arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE) new_data = xr.DataArray(arr, dims=['y', 'x', 'bands'], coords={ 'y': orig.data.coords['y'], 'x': orig.data.coords['x'], 'bands': list(img.mode) }, attrs=orig.data.attrs) return XRImage(new_data)
def add_overlay(orig, area, coast_dir, color=(0, 0, 0), width=0.5, resolution=None, level_coast=1, level_borders=1, fill_value=None): """Add coastline and political borders to image. Uses ``color`` for feature colors where ``color`` is a 3-element tuple of integers between 0 and 255 representing (R, G, B). .. warning:: This function currently loses the data mask (alpha band). ``resolution`` is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | | 'h' | High resolution | 0.2 km | | 'i' | Intermediate resolution | 1.0 km | | 'l' | Low resolution | 5.0 km | | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ """ if area is None: raise ValueError("Area of image is None, can't add overlay.") from pycoast import ContourWriterAGG if isinstance(area, str): area = get_area_def(area) LOG.info("Add coastlines and political borders to image.") if resolution is None: x_resolution = ((area.area_extent[2] - area.area_extent[0]) / area.x_size) y_resolution = ((area.area_extent[3] - area.area_extent[1]) / area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" LOG.debug("Automagically choose resolution %s", resolution) if hasattr(orig, 'convert'): # image must be in RGB space to work with pycoast/pydecorate orig = orig.convert('RGBA' if orig.mode.endswith('A') else 'RGB') elif not orig.mode.startswith('RGB'): raise RuntimeError("'trollimage' 1.6+ required to support adding " "overlays/decorations to non-RGB data.") img = orig.pil_image(fill_value=fill_value) cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, area, outline=color, resolution=resolution, width=width, level=level_coast) cw_.add_borders(img, area, outline=color, resolution=resolution, width=width, level=level_borders) arr = da.from_array(np.array(img) / 255.0, chunks=CHUNK_SIZE) new_data = xr.DataArray(arr, dims=['y', 'x', 'bands'], coords={'y': orig.data.coords['y'], 'x': orig.data.coords['x'], 'bands': list(img.mode)}, attrs=orig.data.attrs) return XRImage(new_data)