Search code examples
pythonmatplotlibcartopy

Using cmap for date contours with Cartopy


I have a series of tif sea ice data (see 3 of them here) which I want to make contours where the sea ice concentration has a constant value of 50% (see figure attached).

enter image description here.

Each red dashed line represents the aforementioned 50% value in April for every year between 1979 and 2020. Instead of all in one same color, I want to use a colormap, or something similar, where each line is depicted by one different color, which in turn is related to the year that it belongs to. Ultimately, using a colorbar, the reader can identify how these lines varied over the years. You can find the code for this figure here.

Suggestions?

Thank you in advance.


Solution

  • First, you need to extract time array from your dataset. For the sake of this example let's assume they are of type datetime.

    # necessary imports
    from datetime import datetime
    import matplotlib.colors as mcol
    import matplotlib.cm as mcm
    import matplotlib.dates as mdates
    import matplotlib.pyplot as plt
    import numpy as np
    
    
    # some random dates
    dts = [
        datetime(1991, 5, 6, 0, 0, 0),
        datetime(2000, 1, 1, 0, 0, 0),
        datetime(2015, 1, 15, 12, 34, 56),
        datetime(2020, 12, 3, 4, 5, 6),
    ]
    

    You should then convert them into numbers:

    num_dt = [mdates.date2num(dt) for dt in dts]
    

    If your dataset has dates as "pure" numbers, you can skip this step and just assign them to num_dt:

    num_dt = ds.time.values  # or something like that
    

    Then you should create a Normalize object with a colormap of your choice:

    cmap = mcm.get_cmap("viridis")
    cnorm = mcol.Normalize(num_dt[0], num_dt[-1])
    

    Next, create a ScalarMappable using the colormap and normalisation from above:

    sm = mcm.ScalarMappable(norm=cnorm, cmap=cmap)
    

    Finally, when you loop over time slices of your data, use the given time stamp to define colour:

    for time_stamp in my_times:
        num_time = mdates.date2num(time_stamp)  # or use the numeric value straight away, if time_stamp is a number
        color = sm.to_rgba(num_time)
        plt.contour(data_slice, colors=[color])
    

    Hope this helps.