IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

matplotlib cmap personnalisée


Sujet :

Python

  1. #1
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 604
    Points : 2 070
    Points
    2 070
    Par défaut matplotlib cmap personnalisée
    Bonsoir,
    Je cherche à créer un graphe avec une échelle de teintes personnalisée, par exemple du noir au jaune, de façon linéaire.
    Je précise que j'ai fait pas mal de recherches et d'essais.
    Le plus approchant auquel je suis parvenu est donné dans le code suivant mais j'aurais souhaité quelque chose de progressif.
    Je n'ai rien compris à la doc sur les dictionnaires de couleurs rouge, vert, bleu, donc ce n'est pas utile de me le donner en lien, sauf à m'expliquer les changements nécessaires.
    Voici donc mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import numpy as np
    import matplotlib.pyplot as plt
     
    my_cmap = plt.matplotlib.colors.ListedColormap(['yellow','grey','black'])
     
    def fr(i):
        return np.cos(np.cos(i)*5e3*np.cos(0.001*i))
     
    scale=np.linspace(0,1,6)
    x = np.linspace(-.1,.1,1000)
    y = np.linspace(-.1,.1,1000)
    X, Y = np.meshgrid(x,y)
     
     
    F = fr(np.sqrt(X**2+Y**2))
    cs = plt.contourf(X,Y,F,scale,cmap=my_cmap);
    plt.show()
    Si vous savez, je suis preneur...
    A bientôt.
    Pas d'aide par mp.

  2. #2
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Salut,

    Tu es peut-être déjà tombé sur ce fil. Je le mets quand même car ça semble répondre à ce que je comprends de la question.

    La fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def make_colormap(seq):
        """Return a LinearSegmentedColormap
        seq: a sequence of floats and RGB-tuples. The floats should be increasing
        and in the interval (0,1).
        """
        seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
        cdict = {'red': [], 'green': [], 'blue': []}
        for i, item in enumerate(seq):
            if isinstance(item, float):
                r1, g1, b1 = seq[i - 1]
                r2, g2, b2 = seq[i + 1]
                cdict['red'].append([item, r1, r2])
                cdict['green'].append([item, g1, g2])
                cdict['blue'].append([item, b1, b2])
        return mcolors.LinearSegmentedColormap('CustomMap', cdict)
    permet visiblement créer automatiquement un nouveau colormap linéaire. Pour l'utiliser il suffit de lui rentrer une séquence de couleur en RGB constituant la nouvelle colormap. Ce qui me semble intéressant c'est que l'on peut aussi ajouter manuellement les "pallier" entre chaque couleur (à partir de quelle valeur on passe du couleur à l'autre) dans la séquence.
    Avec le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    c = mcolors.ColorConverter().to_rgb
    my_cmap = make_colormap([c('yellow'), c('grey'), c('black')])
     
    def fr(i):
        return np.cos(np.cos(i)*5E3*np.cos(0.001*i))
     
    scale = np.linspace(0, 1, 100)
    x = np.linspace(-.1, .1, 1000)
    y = np.linspace(-.1, .1, 1000)
    X, Y = np.meshgrid(x, y)
     
     
    F = fr(np.sqrt(X**2 + Y**2))
    cs = plt.contourf(X, Y, F, scale, cmap=my_cmap)
    plt.colorbar()
    plt.show()
    j'obtiens la figure suivante dont les couleurs sont bien linéaires:
    Nom : figure_1-1.png
Affichages : 2373
Taille : 144,3 Ko

    Mais ce n'est peut-être pas cela que tu as en tête.

  3. #3
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 604
    Points : 2 070
    Points
    2 070
    Par défaut
    Merci Julien N,
    J'avais vu ce fil mais ce n'est pas tout à fait ce que je cherche à faire : je ne veux pas de blanc.
    Je veux qu'au centre, ce soit jaune par exemple et que cela passe au noir de façon linéaire, puis au jaune à nouveau, ...
    En fait, c'est un cmap.binary en remplaçant le blanc par du jaune que je souhaite faire.
    Pas d'aide par mp.

  4. #4
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 604
    Points : 2 070
    Points
    2 070
    Par défaut
    Si quelqu'un comprend comment modifier ces couleurs pour passer du jaune au noir, je veux bien une explication :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    cdict4 = {'red':   ((0.0, 0.0, 0.0),
                       (0.5, 0.0, 0.1),
                       (1.0, 1.0, 1.0)),
     
             'green': ((0.0, 0.0, 1.0),
                       (0.5, 0.1, 0.0),
                       (1.0, 0.0, 0.0)),
     
             'blue':  ((0.0, 0.0, 0.0),
                       (1.0, 0.0, 0.0))
             }
    Pas d'aide par mp.

  5. #5
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Ben pour être honnête je ne vois pas pourquoi il y a du blanc sur le graph. Je comprend que la première valeur de chaque tuple (RGB) correspond à une borne du colormap, ainsi dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    'red':  ((0.0, 1.0, 0.0),
             (0.5, 0.0, 1.0),
             (1.0, 1.0, 0.0)),
    on a trois limites à 0.0, 0.5 et 1.0. A chaque limite on défini la proportion de rouge entre 0 et 1. Mais je ne parviens pas à l'utiliser correctement non plus. cependant il y a une autre façon de faire apparemment en passant par ListedColormap qui est plus facile à appréhender (mais là encore peut-être as-tu déjà explorer cette possibilité):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    N = 20
    color_list = [[i/(N-1), i/(N-1), 0] for i in range(N)] # yellow is [1,1,0]
    color_list.extend(color_list[::-1]) # Symetrical list to produce yellow in center, black outside
    my_cmap = mcolors.ListedColormap(color_list)
    la colorbar est comme attendue (noir, jaune, noir) si c'est bien cela que tu cherches, mais il y a toujours du blanc....

    J

  6. #6
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 604
    Points : 2 070
    Points
    2 070
    Par défaut
    Je n'ai pas creusé la dernière option et là, je suis au boulot sans python.
    S'il y a du blanc, cela ne va pas me convenir.
    En effet, je souhaite uniquement 2 couleurs : noir et jaune (ou autre) avec un mélange des deux en intermédiaire.
    Merci quand même, je continue mes recherches...
    Pas d'aide par mp.

  7. #7
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Ben finalement il m'est venu une idée (j'ai de la chance je bosse en Python ou boulot): le problème vient du scale en spécifiant un range il faut s'assurer de couvrir toute la plage de valeurs à afficher, sans quoi matplotlib n'est pas en mesure de choisir une couleur.

    Donc avec ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    N = 100 # Refinement factor 
    color_list = [[i/(N-1), i/(N-1), 0] for i in range(N)]
    color_list.extend(color_list[::-1])
     
    my_cmap = mcolors.ListedColormap(color_list, name='from_list', N=None)
     
    def fr(i):
        return np.cos(np.cos(i)*5E3*np.cos(0.001*i))
     
    x = np.linspace(-.1, .1, 1000)
    y = np.linspace(-.1, .1, 1000)
    X, Y = np.meshgrid(x, y)
    scale = np.linspace(-1, 1., N)
     
    F = fr(np.sqrt(X**2 + Y**2))
    cs = plt.contourf(X, Y, F, scale, cmap=my_cmap)
    plt.colorbar()
    plt.show()
    J'obtiens cela:
    Nom : figure_1-2.png
Affichages : 2237
Taille : 72,4 Ko

    Après au lieu de mettre scale dans l'appel à countourf, on peut mettre directement N (ici le "raffinement" des couleurs)

    J

    PS: je suis pas fan du jaune et noir perso..

  8. #8
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 604
    Points : 2 070
    Points
    2 070
    Par défaut
    Merci Julien, je verrai pour les couleurs.
    Ton code me convient.
    Entre temps, j'avais trouvé cela mais il y a toujours du blanc et pour le coupo, je n'arrive pas à l'enlever. J'ai laissé le tien pour comparer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors
    from matplotlib.colors import LinearSegmentedColormap
     
    N = 100 # Refinement factor 
    color_list = [[i/(N-1), i/(N-1), 0] for i in range(N)]
    color_list.extend(color_list[::-1])
     
    my_cmap = mcolors.ListedColormap(color_list, name='from_list', N=None)
     
    def fr(i):
        return 1 + np.cos(np.cos(i)*5E3*np.cos(0.001*i))
     
    x = np.linspace(-.1, .1, 10000)
    y = np.linspace(-.1, .1, 10000)
    X, Y = np.meshgrid(x, y)
    scale = np.linspace(-1, 1., N)
     
    plt.figure(figsize=(6,6))
    F = fr(np.sqrt(X**2 + Y**2))
    cs = plt.contourf(X, Y, F, aspect='equal', cmap=my_cmap)
    plt.axis('off')
    #plt.colorbar()
    plt.show()
     
    def yellowblack(y):
        red = [(0.0, y, y), (0.45, y, y), (1.0, 0.0, 0.0)]
        green = [(0.0, y, y), (0.45, y, y), (1.0, 0, 0)]
        blue = [(0.0, y, 0), (0.45, y, y),(1.0,0.0,0.0)]
        colordict = dict(red=red, green=green, blue=blue)
        yellowblackmap = LinearSegmentedColormap('yellowblack', colordict, 256)
        return yellowblackmap
     
    plt.figure(figsize=(6,6))
    F = fr(np.sqrt(X**2 + Y**2))
    cs = plt.contourf(X, Y, F, aspect='equal', cmap=yellowblack(0.85))
    plt.axis('off')
    #plt.colorbar()
    plt.show()
    Tant pis.
    Pas d'aide par mp.

Discussions similaires

  1. matplotlib.pyplot personnalisable ?
    Par Luke spywoker dans le forum Calcul scientifique
    Réponses: 7
    Dernier message: 10/10/2011, 14h17
  2. [langage] personnaliser le tri
    Par schnecke dans le forum Langage
    Réponses: 3
    Dernier message: 24/03/2004, 16h14
  3. Personnaliser un rapport d'erreur sous Windows XP
    Par Neilos dans le forum Windows
    Réponses: 5
    Dernier message: 21/11/2003, 19h13
  4. [FLASH MX2004] Personnaliser les scrollbars
    Par stephane eyskens dans le forum Flash
    Réponses: 10
    Dernier message: 09/10/2003, 13h53
  5. [VB6] [UserControl] Évènements personnalisés
    Par Frankywinky dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 27/05/2003, 18h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo