def show_image(data, dataname, save_png, colors="rainbow", min_data=None, max_data=None, title=None, add_colorscale=True):
    if min_data is None:
        min_data=data.min()
    if max_data is None:
        max_data=data.max()
    img = trollimage(data, mode="L", fill_value=[0,0,0])
    colormap = get_colormap(colors, min_data, max_data)
    img.colorize(colormap)
    if title is not None:
        title_color=(255,255,255)
        from PIL import ImageFont
        from PIL import ImageDraw 
        PIL_image=img.pil_image()
        draw = ImageDraw.Draw(PIL_image)
        fontsize=18
        font = ImageFont.truetype("/usr/openv/java/jre/lib/fonts/LucidaTypewriterBold.ttf", fontsize)
        draw.text( (10, 10), title, title_color, font=font)

    if add_colorscale:
        dc = DecoratorAGG(PIL_image)
        colormap_r = colormap.reverse()
        dc.align_right()
        dc.write_vertically()
        dc.add_scale(colormap_r, extend=True, tick_marks=5, minor_tick_marks=1, line_opacity=100) #, tick_marks=tick_marks, minor_tick_marks=minor_tick_marks, unit=units
        
    show_or_save_image(PIL_image, save_png, dataname)
def test_colorbar(tmp_path, orientation_func_name, align_func_name, clims):
    fn = tmp_path / "test_colorbar.png"
    img = Image.fromarray(np.zeros((200, 100, 3), dtype=np.uint8))
    dc = DecoratorAGG(img)
    getattr(dc, align_func_name)()
    getattr(dc, orientation_func_name)()
    cmap = rdbu.set_range(*clims, inplace=False)
    dc.add_scale(cmap, extend=True, tick_marks=5.0, line_opacity=100, unit="K")
    img.save(fn)

    # check results
    output_img = Image.open(fn)
    arr = np.array(output_img)
    _assert_colorbar_orientation_alignment(arr, orientation_func_name,
                                           align_func_name)
Beispiel #3
0
def test_style_retention():
    # import aggdraw
    from PIL import Image
    from trollimage.colormap import rdbu

    from pydecorate import DecoratorAGG

    # font = aggdraw.Font("navy", DEJAVU_FONT, size=20)
    # font_scale = aggdraw.Font("black", DEJAVU_FONT, size=12)

    rdbu.colors = rdbu.colors[::-1]
    rdbu.set_range(-90, 10)

    img = Image.open(os.path.join(REPOS_ROOT, "BMNG_clouds_201109181715_areaT2.png"))
    dc = DecoratorAGG(img)

    # dc.write_vertically()
    # dc.add_logo("logos/pytroll_light_big.png")
    # dc.add_logo("logos/NASA_Logo.gif",margins=[10,10],bg='yellow')
    # dc.add_logo("logos/pytroll_light_big.png")
    # font = aggdraw.Font("blue", DEJAVU_FONT, size=16)
    # dc.add_text("Some text",font=font)

    # dc.align_right()
    dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit="K")

    # dc.align_bottom()
    # dc.add_scale(rdbu, extend=True, tick_marks=2.0, line_opacity=100, width=60)

    # dc.align_right()
    # dc.write_vertically()
    dc.align_bottom()
    dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit="K")

    # dc.align_left()
    # dc.add_scale(rdbu, extend=True, font=font_scale, tick_marks=2.0, minor_tick_marks=1.0,
    #              line_opacity=100, width=60, unit='K')

    # img.show()
    img.save("style_retention.png")
fontsize = 18
font = ImageFont.truetype(
    "/usr/openv/java/jre/lib/fonts/LucidaTypewriterBold.ttf", fontsize)

if add_colorscale:
    print('... add colorscale ranging from min_data (', min_data,
          ') to max_data (', max_data, ')')
    dc.align_right()
    dc.write_vertically()
    #font_scale = ImageFont.truetype("/usr/openv/java/jre/lib/fonts/LucidaTypewriterBold.ttf", fontsize)
    colormap_r = colormap.reverse()
    #rainbow_r.set_range(min_data, max_data)
    dc.add_scale(colormap_r,
                 extend=True,
                 ticks=ticks,
                 tick_marks=tick_marks,
                 minor_tick_marks=minor_tick_marks,
                 font=font,
                 line_opacity=100,
                 unit=units)  #

indicate_range = True
if indicate_range:
    mask = global_data[prop_str + '-MASK'].data
    img = trollimage(mask, mode="L",
                     fill_value=None)  #fill_value,[1,1,1], None
    from trollimage.colormap import greys
    img.colorize(greys.reverse())
    img.putalpha(mask * 0 + 0.25)
    PIL_mask = img.pil_image()
    from PIL import Image as PILimage
    PIL_image = PILimage.alpha_composite(PIL_mask, PIL_image)
Beispiel #5
0
img = Image.open('BMNG_clouds_201109181715_areaT2.png')
dc = DecoratorAGG(img)

#dc.write_vertically()
#dc.add_logo("logos/pytroll_light_big.png")
#dc.add_logo("logos/NASA_Logo.gif",margins=[10,10],bg='yellow')
#dc.add_logo("logos/pytroll_light_big.png")
font = aggdraw.Font("blue",
                    "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf",
                    size=16)
#dc.add_text("Some text",font=font)

#dc.align_right()
print rdbu.values
print rdbu.colors
dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit='K')

#dc.align_bottom()
#dc.add_scale(rdbu, extend=True, tick_marks=2.0, line_opacity=100, width=60)

#dc.align_right()
#dc.write_vertically()
dc.align_bottom()
dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit='K')

#dc.align_left()
#dc.add_scale(rdbu, extend=True, font=font_scale, tick_marks=2.0, minor_tick_marks=1.0, line_opacity=100, width=60, unit='K')

img.show()
#img.save("style_retention.png")
exit()
Beispiel #6
0
    draw = ImageDraw.Draw(PIL_image)

    if add_colorscale:
        print('... add colorscale ranging from min_data (', min_data,
              ') to max_data (', max_data, ')')
        dc.align_right()
        dc.write_vertically()
        font_scale = aggdraw.Font(
            "black",
            "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf",
            size=16)
        greens2.set_range(min_data, max_data)
        dc.add_scale(greens2,
                     extend=True,
                     tick_marks=tick_marks,
                     minor_tick_marks=minor_tick_marks,
                     font=font_scale,
                     line_opacity=100,
                     unit=units)  #

    # define contour write for coasts, borders, rivers
    cw = ContourWriterAGG('/data/OWARNA/hau/maps_pytroll/')

    if area.find("EuropeCanary") != -1:
        resolution = 'l'
    if area.find("nrEURO3km") != -1:
        resolution = 'l'
    if area.find("nrEURO1km") != -1:
        resolution = 'i'
    if area.find("ccs4") != -1:
        resolution = 'i'
Beispiel #7
0
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)
Beispiel #8
0
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
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)
Beispiel #10
0
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

    if args.cache_dir and not os.path.isdir(args.cache_dir):
        LOG.info(f"Creating cache directory: {args.cache_dir}")
        os.makedirs(args.cache_dir, exist_ok=True)

    # 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
    # gather all options into a single dictionary that we can pass to pycoast
    pycoast_options = _args_to_pycoast_dict(args)
    for input_tiff, output_filename in zip(args.input_tiff, args.output_filename):
        LOG.info("Creating {} from {}".format(output_filename, input_tiff))
        img = Image.open(input_tiff)
        img_bands = img.getbands()
        num_bands = len(img_bands)
        # P = palette which we assume to be an RGBA colormap
        img = img.convert("RGBA" if num_bands in (2, 4) or "P" in img_bands else "RGB")
        if pycoast_options:
            area_id = os.path.splitext(input_tiff[0])[0]
            area_def = get_area_def_from_raster(input_tiff, area_id=area_id)
            cw = ContourWriterAGG(args.shapes_dir)
            cw.add_overlay_from_dict(pycoast_options, area_def, background=img)

        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)
            if num_bands not in (1, 2):
                raise ValueError("Can't add colorbar to RGB/RGBA image")

            # figure out what colormap we are dealing with
            rio_ds = rasterio.open(input_tiff)
            input_dtype = np.dtype(rio_ds.meta["dtype"])
            rio_ct = _get_rio_colormap(rio_ds, 1)
            cmap = get_colormap(input_dtype, rio_ct, num_bands)

            # figure out our limits
            vmin = args.colorbar_min
            vmax = args.colorbar_max
            metadata = rio_ds.tags()
            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:
                vmin = vmin or np.iinfo(input_dtype).min
                vmax = vmax or np.iinfo(input_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)
Beispiel #11
0
img = Image.open('BMNG_clouds_201109181715_areaT2.png')
dc = DecoratorAGG(img)


#dc.write_vertically()
#dc.add_logo("logos/pytroll_light_big.png")
#dc.add_logo("logos/NASA_Logo.gif",margins=[10,10],bg='yellow')
#dc.add_logo("logos/pytroll_light_big.png")
font=aggdraw.Font("blue","/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf",size=16)
#dc.add_text("Some text",font=font)


#dc.align_right()
print rdbu.values
print rdbu.colors
dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit='K')

#dc.align_bottom()
#dc.add_scale(rdbu, extend=True, tick_marks=2.0, line_opacity=100, width=60)

#dc.align_right()
#dc.write_vertically()
dc.align_bottom()
dc.add_scale(rdbu, extend=True, tick_marks=5.0, line_opacity=100, unit='K')

#dc.align_left()
#dc.add_scale(rdbu, extend=True, font=font_scale, tick_marks=2.0, minor_tick_marks=1.0, line_opacity=100, width=60, unit='K')

img.show()
#img.save("style_retention.png")
exit()