Casio vient tout juste de nous sortir des mises à jour 3.30 et 3.40 pour ses Graph 35+E II et Graph 90+E, avec un nouveau module Pythoncasioplot te permettant de contrôler les pixels de l'écran.
Nous t'en illustrions déjà les hautes possibilités graphiques sur Graph 90+E avec le dégradé de couleurs ci-contre.
Mais quel engouement, quel succès ! À peine J+3 après la sortie et de formidables réalisations commencent à sortir, comme Raytracing par Lightmare !
Au menu, rendu d'un miroir sphérique en lévitation au-dessus d'un plan quadrillé.
Des performances de plus très honorables, sans aucune accélération de la machine seulement 3min 45s pour le rendu en projection orthonormale 192×192 pixels, et 6min 45s pour le rendu en projection plein écran 384×192 pixels ! (avec, précisons-le, un rafraîchissement à chaque nouveau pixel calculé - ce serait sans doute nettement plus rapide en ne rafraîchissant qu'à la fin mais ce serait aussi plus ennuyeux pour toi )
Et si tu t'amusais à changer la scène rendue en jouant sur les paramètres internes au script ?
Casio vient tout juste de nous sortir des mises à jour 3.30 et 3.40 absolument fabuleuses pour ses Graph 35+E II et Graph 90+E. Au menu des possibilités Python largement étendues avec :
un module casioplot permettant de contrôler les pixels de l'écran
un script matplotl.py interfaçant le module casioplot afin de le rendre utilisable comme le module matplotlib.pyplot standard
un script turtle.py interfaçant le module casioplot afin de le rentre utilisable comme le module turtle standard
Tes scripts faisant usage de ces deux derniers ont de plus le gros avantage de pouvoir être très facilement compatibles :
avec les plateformes implémentant les modules turtle et matplotlib.pyplot standard (ordinateur, tablette, ...)
aussi bien avec les Graph 90+E que les Graph 35+E II malgré leurs écrans très différents
et même compatibles NumWorks, non non tu ne rêves pas !
Mais par contre, que faire si tu disposais de la clé d'émulation USB de Casio dans une ancienne version ?
La clé équivalente chez Texas Instruments ne peut officiellement pas être mise à jour.
Et bien non surprise du côté de Casio, pas besoin de te recommander une clé, le constructeur te fournit ici tout ce qu'il te faut pour la mettre à jour directement toi-même sans avoir à bouger de chez toi en ces temps difficiles !
Casio te diffuse en effet dès maintenant les nouvelles versions des émulateurs, qu'il te suffira tout simplement de copier sur ta clé USB officielle à la place des anciens !
Attention toutefois, cette copie des nouveaux émulateurs ne suffit pas à elle seule pour bénéficier en Python des nouvelles interfaces matplotl.py et turtle.py.
Il te faut de plus récupérer séparément ces dernières ci-dessous, et les copier dans le bon dossier de ta clé :
\User_Data\GRAPH90+ E\FLASH_Folder\ pour les versions Graph 90+E de matplotl.py et turtle.py
\User_Data\GRAPH35+ E II\FLASH_Folder\ pour les versions Graph 35+E II de matplotl.py et turtle.py
Dans sa prochaine mise à jour gratuite pour Graph 35+E II et Graph 90+E, Casio te promettait de rajouter de formidables possibilités graphiques à son application Python :
un module casioplot permettant de dessiner en contrôlant les pixels de l'écran
un script matplotl interfaçant le module casioplot afin de le rendre utilisable comme le module matplotlib.pyplot standard
un script turtle interfaçant le module casioplot afin de le rentre utilisable comme le module turtle standard
Et bien tu n'attendras pas plus longtemps, les mises à jour sont disponibles dès maintenant !
Nous avons donc deux versions de mise à jour différentes :
3.30 pour la Graph 35+E II
3.40 pour la Graph 90+E et son équivalent international fx-CG50
Le nombre final 2200 ou 2202 affiché sur les écrans ci-contre ne fait pas partie du numéro de version et est en fait une étiquette informative.
Le chiffre des centaines par exemple est en fait le code de zonage si présent. Pour rappel, Casio utilise les valeurs suivantes :
Australie
France
Amérique du Nord
Chine
Singapour
Il est donc ici normal d'obtenir un 2 aux centaines lorsque les mises à jour sont installées sur des modèles français.
On peut apprendre un peu plus sur ces versions en accédant au menu d'auto-diagnostic. Pour cela il suffit d'allumer la calculatrice tout en maintenant les touches
OPTN
×10^x
, puis de confirmer rapidement en tapant
F1
9
:
la version 3.30 pour la Graph 35+E II a donc été compilée le 13 mars 2020 à 05h03
et la version 3.40 pour Graph 90+E et compagnie un tout petit peu avant, le 13 mars 2020 à 02h16 nous confirmant que les nouveautés pour ces différents modèles sont bien développées en parallèle
En réalité si on fouille, le logiciel de mise à jour pour Graph 90+E contient deux mises à jour différentes :
effectivement une version 3.40 compilée le 13 mars 2020 à 02h16, commune aux modèles Graph 90+E et fx-CG50
et une version 3.40 compilée le 13 mars 2020 à 02h29, probablement la version spécifique pour le modèle australien fx-CG50AU qui utilise une mémoire Flash de 16 Mio au lieu de 32 Mio
De même, fouillons un petit peu le logiciel de mise à jour pour Graph 35+E II, et là nous sommes gâtés avec pas moins de 3 mises à jour différentes :
effectivement une version 3.30 compilée le 13 mars 2020 à 05h03, pour Graph 35+E II donc
mais aussi une mystérieuse version 3.21 compilée le 20 décembre 2019 à 11h51
et également une autre version 3.21 compilée pour sa part le 20 décembre 2019 à 11h58
La version Graph 35+E II précédente étant la 3.20, il s'agit donc ici très probablement des versions 3.21 qui sont censées équiper les nouveaux modèles internationaux similaires à la Graph 35+E II pour la rentrée 2020, les fx-9750GIII et fx-9860GIII.
; aux côtés des modules math et random nous disposons donc d'un tout nouveau module casioplot.
Il s'agit donc d'un module dont le but est de permettre à tes scripts Python d'afficher ce que tu veux à l'écran, en l'adressant pixel par pixel.
Pour te donner une référence, on pourrait le comparer au module kandinsky chez NumWorks.
Au menu tout ce qu'il te faut :
draw_string(,,)
get_pixel(,)
set_pixel(,)
show_screen()
La présence d'une fonction show_screen() suggère toutefois que les affichages ne sont pas effectués directement à l'écran, mais sur un calque invisible dont il faut demander l'affichage, technique du double buffering. Cela pourrait à la différence avoir des conséquences remarquables en terme de performances.
Tentons toutefois de voir si il n'y aura pas quelques fonction secrètes à l'aide de notre script d'exploration suivant :
def getplatform(): id=-1 try: import sys try: if sys.platform=='nspire':id=0 if sys.platform.startswith('TI-Python') or sys.platform=='Atmel SAMD21':id=4 except:id=3 except: try: import kandinsky id=1 except: try: if chr(256)==chr(0):id=5+(not ("HP" in version())) except: id=2 return id
platform=getplatform() #lines shown on screen #plines=[29,12, 7, 9,11,0,0] plines=[29,16, 7, 9,11,0,0] #max chars per line #(error or CR if exceeded) pcols =[53,99,509,32,32,0,0]
def mprint(*ls): global curline st="" for s in ls: if not(isinstance(s,str)): s=str(s) st=st+s stlines=1+int(len(st)/ncols) if curline+stlines>=nlines: input("Input to continue:") curline=0 print(st) curline+=stlines
def sstr(obj): try: s=obj.__name__ except: s=str(obj) a=s.find("'") b=s.rfind("'") if a>=0 and b!=a: s=s[a+1:b] return s
def isExplorable(obj): s=str(obj) return s.startswith("<") and s.find(" ")>=0 and not s.startswith("<module")
def explmod(pitm,pitmsl=[],reset=True): global curline if(reset): curline=0 pitmsl=[sstr(pitm)] hd="."*(len(pitmsl)-1) spath=".".join(pitmsl) c,c2=0,0 spitm=str(pitm) for itms in sorted(dir(pitm)): c,c2=c+1,c2+1 try: itm=eval(spath+"."+itms) mprint(hd+itms+"="+str(itm)) if isExplorable(itm) and itm!=pitm: pitmsl2=pitmsl.copy() pitmsl2.append(itms) c2=c2+explmod(itm,pitmsl2,False)[1] except: mprint(hd+itms) if c>0 and reset: mprint(hd+"Total: "+str(c)+" 1st level item(s)") if c2>0 and c2!=c: mprint(hd+" "+str(c2)+" item(s)") return [c,c2]
Et si visiblement, il y a également un clear_screen() qui n'est pas au menu.
Voici donc où nous en sommes maintenant niveau richesse du Python sur calculatrices :
Pas beaucoup de fonctions à documenter donc, ça va être vite fait. Mais les possibilités n'en restent pas moins gigantesques avec tout ce qu'il te faut pour coder tes interfaces ou jeux Python. C'est enfantin :
set_pixel(x, y, c=(0,0,0)) pour allumer le pixel de coordonnées (x,y) dans la couleur c
get_pixel(x, y) pour inversement récupérer la couleur du pixel de coordonnées (x,y)
draw_string(x, y, s, c=(0,0,0), t="medium") pour afficher la chaîne de caractères s dans la couleur c en partant des coordonnées(x,y) au coin supérieur gauche et selon la taille t
Et tu dois donc appeler show_screen() pour montrer ton affichage à l'utilisateur une fois que tu en as terminé, et ensuite éventuellement clear_screen() si ton script a besoin de repartir d'un écran vierge pour d'autres affichages.
Les couleurs sont indiquées par des listes ou tuples précisant leurs coordonnées RVB, nombres entiers de 0 à 255. Lorsque omises, c'est la valeur (0, 0, 0) qui est utilisée, ce qui donne du noir.
La taille optionnelle de police pour le draw_string() vaut "medium" par défaut, et peut également être réglée à "small" ou "large".
Voici un petit script afin de t'en illustrer les différences ci-contre :
def horiz(x,y,l,c=(0,0,0)): for k in range(l): scr.set_pixel(x+k,y)
def vert(x,y,l,c=(0,0,0)): for k in range(l): scr.set_pixel(x,y+k)
def rect(x,y,w,h,c=(0,0,0)): for k in range(2): vert(x+k*(w-1),y,h,c) for k in range(2): horiz(x,y+k*(h-1),w,c)
Tentons donc de tracer des rectangles de plus en plus grands jusqu'à-ce que leurs côtés débordent de l'écran et disparaissent.
Sur Graph 35+E II c'est fantastique, l'affichage correct associé à l'appel rect(0, 0, 128, 64) nous montre que nous pouvons afficher sur la totalité des 128×64 pixels de l'écran !
Sur Graph 90+E nous avons un écran de 396×224 pixels. Mais il faut retirer la marge d'écran réservée pour indiquer le bon fonctionnement du mode examen (à gauche, à droite et en bas), ainsi que la barre de statut en haut d'écran. C'est ici l'appel rect(0, 0, 384, 192) qui est le dernier à produire un affichage correct et nous montre que tes scripts peuvent donc contrôler librement une superbe zone de 384×192 pixels de l'écran.
Il est également possible de détecter ces mêmes dimensions de façon complètement automatisée, en appelant de get_pixel() qui justement a la bonne idée de renvoyer None hors zone :
def getScreen(): w, h = 0, 0 while(scr.get_pixel(w, 0)): w += 1 while(scr.get_pixel(0, h)): h += 1 return (w, h)
Et oui, tu ne rêves pas, détection complètement automatisée sans effort, qui en prime nous confirme les valeurs précédentes !
Tu as donc un moyen super simple de récupérer les dimensions de la zone affichable si tu ne les connais pas par coeur. Avec la possibilité d'en tenir compte pour faire des scripts qui affichent aussi bien sur Graph 90+E que Graph 35+E II, et pourquoi pas sur d'autres modèles concurrents également !
Nous allons ici t'afficher un dégradé de couleurs couvrant l'ensemble des possibilités d'affichage de la calculatrice, avec toutes les couleurs de l'arc-en-ciel et tous les éclairages.
Pour cela nous travaillerons en coordonnées HSV/TSV (Hue/teinte, Saturation, Valeur) :
teinte qui sera ici codée par un nombre flottant de 0 à 2 est en gros ce que tu appelles naturellement couleur.
saturation, un flottant de 0 à 1 indique de façon inverse la quantité de blanc.
valeur, ici encore un flottant de 0 à 1 indique de façon inverse la quantité de noir.
Les coordonnées ainsi précisées seront alors converties en coordonnées RGB/RVB (Rouge, Green/Vert, Bleu) compatibles avec la calculatrice.
def hsv2c(h,s,v): c=v*s x,m,k=c*(1-abs((h%(2/3))*3-1)),v-c,(h*3)//1 return (round(255*(m+x*(k%3==1)+c*(k%5==0))),round(255*(m+c*(k==1 or k==2)+x*(k%3==0))),round(255*(m+x*(k%3==2)+c*(k==3 or k==4))))
def grad(x,y,w,h): for i in range(w): for j in range(h): c=hsv2c(2*j/(h-1),i>=w//2 and 1 or i/(w//2-1),i<w//2 and 1 or (w-1-i)/((w-w//2)-1)) scr.set_pixel(x+i,y+j,c)
grad(0, 0, 384, 192) scr.show_screen()
Superbe, non ?
Remarquons quand même que le dégradé est visuellement saccadé, ce qui signifie que même si tu précises ici les couleurs sur 24-bits (8 bits par composante), l'affichage est quant à lui réalisé en 16-bits. On peut d'ailleurs noter un davantage de tons intermédiaires dans les teintes tirant sur le vert, plus précisément deux fois plus ce qui indique qu'un bit supplémentaire est utilisé pour la composante verte. Bref l'affichage est donc ici en RGB-565, et ce sera pourra toujours être bon à savoir lorsque tu choisiras les couleurs pour tes scripts.
Et la Graph 35+E II, elle se comporte comment sur ce même script avec son écran monochrome ?
Pas d'affichage en niveaux de gris, mais pas d'erreur non plus. Les scripts utilisant les paramètres de couleurs pourront donc s'exécuter également sur Graph 35+E II, une superbe nouvelle pour la compatibilité !
La Graph 35+E II remplace simplement les couleurs intermédiaires par les extrêmes qu'elle estime être les plus proches : souvent (0, 0, 0) pour le noir comme tu peux le constater ci-contre ou sinon (255, 255, 255) pour le blanc.
C'est d'ailleurs une autre façon pour toi de détecter le type de modèle ou plus généralement si tu as affaire à un écran couleur ou non.
try: import casioplot as scr def getscreen(): w, h = 0, 0 while(scr.get_pixel(w, 0) and scr.get_pixel(w, 0)!=(0,0,0)): w += 1 while(scr.get_pixel(0, h) and scr.get_pixel(0, h)!=(0,0,0)): h += 1 return (w, h) scrdim=getscreen()
except: import kandinsky as scr scrdim = (320, 220)
def iscolorscreen(): c=(1, 1, 1) scr.set_pixel(0, 0, c) return c == scr.get_pixel(0, 0) scrcolor = iscolorscreen()
def horiz(x,y,l,c=(0,0,0)): for k in range(l): scr.set_pixel(x+k,y,c)
def rectf(x,y,w,h,c=(0,0,0)): for k in range(h): horiz(x,y+k,w,c)
Pour que la mesure soit équitable, traçon le même rectangle de 128×64 pixels via l'appel rectf(0, 0, 128, 64, (255, 0, 0)), l'écran de la Graph 35+E II étant ici le facteur limitant, et chronométrons.
Sur NumWorks, on peut chronométrer automatiquement à l'aide du module time :
On trouve autour de 0,2 seconde sur le dernier modèle NumWorks N0110 et un tout petit peu plus sur l'ancien modèle NumWorks N0100.
Sur Graph 35+E II, pas de module time. Chronométrons donc à la main l'appel rect(0, 0, 128, 64, (255, 0, 0)); scr.show_screen(), on trouve autour de 0,8 seconde.
Difficile de chronométrer manuellement moins que ça avec la Graph 90+E plus rapide. Traçons donc plutôt un rectangle de 320×192 pixels pour tenter de la classer.
L'appel rect(0, 0, 320, 192, (255, 0, 0)); scr.show_screen() se termine en 1,75 secondes.
Quant aux NumWorks, nous trouvons 1,5 secondes sur l'ancien modèle N0100 et 1,35 secondes sur le dernier modèle N0110.
Par extrapolation, si la Graph 35+E II pouvait afficher 320×192 pixels, elle mettrait donc autour de 5,35 secondes, d'où le classement suivant pour les performances graphiques :
1,35s : NumWorks N0110
1,5s : NumWorks N0100
1,75s : Graph 90+E / fx-CG50
5,35s : Graph 35+E II
Nous ne pouvons que féliciter la Graph 90+E qui graphiquement n'est donc pas loin des performances d'une NumWorks !
turtle.py est donc le script interface fourni par Casio afin de pouvoir utiliser les possibilités graphiques du module casioplot exactement comme le module turtle standard du Python.
Il est à noter que ce script n'est pas inclus dans la mise à jour. Tu dois le récupérer et le charger séparément; tu auras tous les liens en fin d'article.
Casio a donc fait le choix ambitieux de recoder intégralement le module turtle en Python. Un script de pas moins de 8 Ko dont la lecture est absolument passionnante à elle tout seule :
def draw_turtle(x,y,a,c): global turtle_buffer def inbuffer(x,y): inlist=False for i in range(1,len(turtle_buffer)): if x==turtle_buffer[i][0] and y==turtle_buffer[i][1]: inlist=True return inlist if turtle_visible==True: u=cos(a*pi/180) v=sin(a*pi/180) for point in turtle_data: xx=x+(point[0]*u-point[1]*v) yy=y+(point[1]*u+point[0]*v) xpixel=int(round(xx+64)) ypixel=int(round(-yy+32)) if (0<=xpixel<=127 and 0<=ypixel<=63): if not inbuffer(xpixel,ypixel): turtle_buffer+=[[xpixel,ypixel,casioplot.get_pixel(xpixel,ypixel)]] casioplot.set_pixel(xpixel,ypixel,c)
def erase_turtle(): global turtle_buffer for i in range(1,len(turtle_buffer)): xpixel=turtle_buffer[i][0] ypixel=turtle_buffer[i][1] if turtle_buffer[i][2]!=None : lastcolor=turtle_buffer[i][2] else: lastcolor=(255,255,255) casioplot.set_pixel(xpixel,ypixel,lastcolor) turtle_buffer=[[]]
def pen_brush(x,y,turtle_color): global frame_count erase_turtle() xpixel=int(round(x+64)) ypixel=int(round(-y+32)) if writing==True and (0<=xpixel<=127 and 0<=ypixel<=63) : colorpixel=(int(turtle_color[0]*255), int(turtle_color[1]*255),int(turtle_color[2]*255)) casioplot.set_pixel(xpixel,ypixel,colorpixel) frame_count+=1 if turtle_speed!=0: if frame_count%(turtle_speed*2)==0: draw_turtle(x,y,turtle_angle,colorpixel) casioplot.show_screen() else : if frame_count%200==0: draw_turtle(x,y,turtle_angle,colorpixel) casioplot.show_screen()
def forward(d): global turtle_pos dx=d*cos(turtle_angle*pi/180) dy=d*sin(turtle_angle*pi/180) x1=turtle_pos[0] y1=turtle_pos[1] if round(abs(d))==0: pen_brush(x1+dx,y1+dy,turtle_color) elif abs(dx)>=abs(dy): e=int(dx/abs(dx)) m=dy/dx p=y1-m*x1 for x in range(int(round(x1)),int(round(x1+dx)),e): pen_brush(x,m*x+p,turtle_color) else: e=int(dy/abs(dy)) m=dx/dy p=x1-m*y1 for y in range(int(round(y1)),int(round(y1+dy)),e): pen_brush(m*y+p,y,turtle_color) turtle_pos[0]+=dx turtle_pos[1]+=dy refresh_turtle()
def hideturtle(): global turtle_visible turtle_visible=False refresh_turtle()
def home(): global turtle_pos,turtle_angle turtle_pos[0]=turtle_pos[1]=0 turtle_angle=0 refresh_turtle()
def ht(): hideturtle()
def isdown(): return writing
def isvisible(): return turtle_visible
def left(a): right(-a)
def lt(a): right(-a)
def pd(): down()
def pencolor(*c): global turtle_color colornames={"black":(0,0,0),"blue":(0,0,1),"green":(0,1,0),"red":(1,0,0),"cyan":(0,1,1),"yellow":(1,1,0),"magenta":(1,0,1),"white":(1,1,1),"orange":(1,0.65,0),"purple":(0.66,0,0.66),"brown":(0.75,0.25,0.25),"pink":(1,0.75,0.8),"grey":(0.66,0.66,0.66)} if c==(): return turtle_color elif c[0] in colornames: turtle_color=colornames[c[0]] elif isinstance(c[0],(list,tuple)) and len(c[0])==3 and isinstance(c[0][0],(int,float)) and isinstance(c[0][1],(int,float)) and isinstance(c[0][2],(int,float)) and 0<=c[0][0]<=1 and 0<=c[0][1]<=1 and 0<=c[0][2]<=1: turtle_color=list(c[0]) else: raise ValueError('error using pencolor : enter a color text or 3 floats between 0 and 1') refresh_turtle()
def pendown(): down()
def pensize(n): global pen_size pen_size=n refresh_turtle()
def right(a): global turtle_angle turtle_angle-=a refresh_turtle()
def rt(a): right(a)
def seth(a): setheading(a)
def setheading(a): global turtle_angle turtle_angle=a refresh_turtle()
def setpos(x,y): goto(x,y) refresh_turtle()
def setposition(x,y): setpos(x,y)
def setx(x): global turtle_pos turtle_pos[0]=x refresh_turtle()
def sety(y): global turtle_pos turtle_pos[1]=y refresh_turtle()
def shape(text=None): global turtle_name,turtle_data if text==None: return turtle_name elif text in turtleshapes: turtle_name=text turtle_data=turtleshapes[text] else: raise ValueError('available shapes: "classic" or "turtle"') refresh_turtle()
def showturtle(): global turtle_visible turtle_visible=True refresh_turtle()
def speed(v=None): global turtle_speed speedwords = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 } if v==None: pass elif isinstance(v,(int,float)) and (v<=0.5 or v>=10.5): turtle_speed=0 elif isinstance(v,(int,float)) and (0.5<v<10.5): turtle_speed=int(round(v)) elif isinstance(v,str) and v in speedwords: turtle_speed=speedwords[v] else: raise ValueError("Error using function speed: enter a real between 0 & 10")
def st(): showturtle()
def towards(x,y): if round(x-turtle_pos[0],8)==0 and round(y-turtle_pos[1],8)==0: return 0 else: return (atan2(y-turtle_pos[1],x-turtle_pos[0])*180/pi)
def draw_turtle(x,y,a,c): global turtle_buffer def inbuffer(x,y): inlist=False for i in range(1,len(turtle_buffer)): if x==turtle_buffer[i][0] and y==turtle_buffer[i][1]: inlist=True return inlist if turtle_visible==True: u=cos(a*pi/180) v=sin(a*pi/180) for point in turtle_data: xx=x+(point[0]*u-point[1]*v) yy=y+(point[1]*u+point[0]*v) xpixel=int(round(xx+192)) ypixel=int(round(-yy+96)) if (0<=xpixel<=383 and 0<=ypixel<=191): if not inbuffer(xpixel,ypixel): turtle_buffer+=[[xpixel,ypixel,casioplot.get_pixel(xpixel,ypixel)]] casioplot.set_pixel(xpixel,ypixel,c)
def erase_turtle(): global turtle_buffer for i in range(1,len(turtle_buffer)): xpixel=turtle_buffer[i][0] ypixel=turtle_buffer[i][1] if turtle_buffer[i][2]!=None : lastcolor=turtle_buffer[i][2] else: lastcolor=(255,255,255) casioplot.set_pixel(xpixel,ypixel,lastcolor) turtle_buffer=[[]]
def pen_brush(x,y,turtle_color): global frame_count erase_turtle() xpixel=int(round(x+192)) ypixel=int(round(-y+96)) if writing==True and (0<=xpixel<=383 and 0<=ypixel<=191) : colorpixel=(int(turtle_color[0]*255), int(turtle_color[1]*255),int(turtle_color[2]*255)) casioplot.set_pixel(xpixel,ypixel,colorpixel) frame_count+=1 if turtle_speed!=0: if frame_count%(turtle_speed*4)==0: draw_turtle(x,y,turtle_angle,colorpixel) casioplot.show_screen() else : if frame_count%500==0: draw_turtle(x,y,turtle_angle,colorpixel) casioplot.show_screen()
def forward(d): global turtle_pos dx=d*cos(turtle_angle*pi/180) dy=d*sin(turtle_angle*pi/180) x1=turtle_pos[0] y1=turtle_pos[1] if round(abs(d))==0: pen_brush(x1+dx,y1+dy,turtle_color) elif abs(dx)>=abs(dy): e=int(dx/abs(dx)) m=dy/dx p=y1-m*x1 for x in range(int(round(x1)),int(round(x1+dx)),e): pen_brush(x,m*x+p,turtle_color) else: e=int(dy/abs(dy)) m=dx/dy p=x1-m*y1 for y in range(int(round(y1)),int(round(y1+dy)),e): pen_brush(m*y+p,y,turtle_color) turtle_pos[0]+=dx turtle_pos[1]+=dy refresh_turtle()
def hideturtle(): global turtle_visible turtle_visible=False refresh_turtle()
def home(): global turtle_pos,turtle_angle turtle_pos[0]=turtle_pos[1]=0 turtle_angle=0 refresh_turtle()
def ht(): hideturtle()
def isdown(): return writing
def isvisible(): return turtle_visible
def left(a): right(-a)
def lt(a): right(-a)
def pd(): down()
def pencolor(*c): global turtle_color colornames={"black":(0,0,0),"blue":(0,0,1),"green":(0,1,0),"red":(1,0,0),"cyan":(0,1,1),"yellow":(1,1,0),"magenta":(1,0,1),"white":(1,1,1),"orange":(1,0.65,0),"purple":(0.66,0,0.66),"brown":(0.75,0.25,0.25),"pink":(1,0.75,0.8),"grey":(0.66,0.66,0.66)} if c==(): return turtle_color elif c[0] in colornames: turtle_color=colornames[c[0]] elif isinstance(c[0],(list,tuple)) and len(c[0])==3 and isinstance(c[0][0],(int,float)) and isinstance(c[0][1],(int,float)) and isinstance(c[0][2],(int,float)) and 0<=c[0][0]<=1 and 0<=c[0][1]<=1 and 0<=c[0][2]<=1: turtle_color=list(c[0]) else: raise ValueError('error using pencolor : enter a color text or 3 floats between 0 and 1') refresh_turtle()
def pendown(): down()
def pensize(n): global pen_size pen_size=n refresh_turtle()
def right(a): global turtle_angle turtle_angle-=a refresh_turtle()
def rt(a): right(a)
def seth(a): setheading(a)
def setheading(a): global turtle_angle turtle_angle=a refresh_turtle()
def setpos(x,y): goto(x,y) refresh_turtle()
def setposition(x,y): setpos(x,y)
def setx(x): global turtle_pos turtle_pos[0]=x refresh_turtle()
def sety(y): global turtle_pos turtle_pos[1]=y refresh_turtle()
def shape(text=None): global turtle_name,turtle_data if text==None: return turtle_name elif text in turtleshapes: turtle_name=text turtle_data=turtleshapes[text] else: raise ValueError('available shapes: "classic" or "turtle"') refresh_turtle()
def showturtle(): global turtle_visible turtle_visible=True refresh_turtle()
def speed(v=None): global turtle_speed speedwords = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 } if v==None: pass elif isinstance(v,(int,float)) and (v<=0.5 or v>=10.5): turtle_speed=0 elif isinstance(v,(int,float)) and (0.5<v<10.5): turtle_speed=int(round(v)) elif isinstance(v,str) and v in speedwords: turtle_speed=speedwords[v] else: raise ValueError("Error using function speed: enter a real between 0 & 10")
def st(): showturtle()
def towards(x,y): if round(x-turtle_pos[0],8)==0 and round(y-turtle_pos[1],8)==0: return 0 else: return (atan2(y-turtle_pos[1],x-turtle_pos[0])*180/pi)
Testons maintenant la conformité de cette interface turtle.py avec le module turtle standard, ainsi que la compatibilité entre différentes calculatrices graphiques.
Nous allons pour cela prendre plusieurs exemples où nous lancerons le même code sur différents modèles.
On commence par une petite rosace; tout possesseur de Graph 35+E II sait que Casio adore ça :
speed(0) for i in range(12): left(30) for i in range(8): forward(30) left(45)
Certes, la tortue travaillant en pixels le code aurait besoin d'être adapté pour l'écran Graph 35+E II à plus faible définition. Mais à part cela, le code passe ici sans problème sur Casio, NumWorks et ordi.
from math import exp from turtle import * for i in range(1,37): red=(exp(-0.5 * ((i-6)/12)**2)) green=(exp(-0.5 * ((i-18)/12)**2)) blue=(exp(-0.5 * ((i-30)/12)**2)) pencolor([red, green, blue]) for i in range(1, 5): forward(60) right(90) right(10)
Aille, la NumWorks réagit mal ici.
Le problème semble ici être qu'elle n'utilise pas par défaut le même système de coordonnées pour les composantes couleurs en turtle :
nombre flottant de 0.0 à 1.0 sur Casio et ordinateur
nombre entier de 0 à 255 sur NumWorks
Notons que sur les implémentations Python complètes on peut régler le comportement souhaité à l'aide des appels respectifs turtle.colormode(1.0) et turtle.colormode(255). Toutefois cette fonction n'est hélas pas incluse chez NumWorks.
En conséquence, nous proposons le code corrigé ci-dessous, avec une fonction intermédiaire mypencolor() qui corrigera les coordonnées si nécessaire, et qui à la différence marchera aussi sur NumWorks :
def mypencolor(t): cmax = 255 try: pencolor((2, 2, 2)) except: cmax = 1 if(cmax == 1 and max(t)>1): t = tuple(u/255 for u in t) elif(cmax == 255 and any(isinstance(u, float) for u in t)): t=tuple(int(255*u) for u in t) pencolor(t)
for i in range(1,37): red=(exp(-0.5 * ((i-6)/12)**2)) green=(exp(-0.5 * ((i-18)/12)**2)) blue=(exp(-0.5 * ((i-30)/12)**2)) mypencolor([red, green, blue])
for i in range(1, 5): forward(60) right(90) right(10)
Poursuivons avec une coquille d'escargot en appliquant la même astuce pour contourner le problème de la NumWorks :
def mypencolor(t): cmax = 255 try: pencolor((2, 2, 2)) except: cmax = 1 if(cmax == 1 and max(t)>1): t = tuple(u/255 for u in t) elif(cmax == 255 and any(isinstance(u, float) for u in t)): t=tuple(int(255*u) for u in t) pencolor(t)
penup() goto(0, -20) pendown() for i in range(1,37): red=(exp(-0.5 * ((i-6)/12)**2)) green=(exp(-0.5 * ((i-18)/12)**2)) blue=(exp(-0.5 * ((i-30)/12)**2)) mypencolor([red,green,blue]) circle(50-i) right(10)
Sous réserve donc de cette astuce, compatibilité totale.
Et enfin un petit écran tout spécial, ode à cette superbe Graph 90+E :
Plusieurs nouveaux problèmes hélas ici avec le module turtle de la NumWorks :
d'une part il ne comprend apparemment pas l'astuce de passer un rayon négatif pour changer le sens de tracer d'un cerle, alors que parfaitement standard puisque géré sur ordinateur
d'autre part, il ne dispose apparemment pas de la fonction write() permettant d'écrire du texte à l'emplacement de la tortue
Casio nous signe donc là une réimplémentation en Python hautement fidèle du module turtle.
Elle réussit même l'exploit d'être à ce jour plus fidèle au standard que le portage direct du code source chez NumWorks !
Du travail d'excellente facture, toutes nos félicitations !
matplotl.py est donc le script interface fourni par Casio afin de pouvoir utiliser les possibilités graphiques du module casioplot exactement comme le module matplotlib.pyplot standard du Python.
Il est à noter que ce script n'est lui non plus pas inclus dans la mise à jour. Tu dois le récupérer et le charger séparément; tu auras tous les liens en fin d'article.
Casio a donc fait le choix surhumain de recoder intégralement le module matplotlib.pyplot en Python. Un script de pas moins de 23 Ko, tu te rends compte ? Même si il est possible de le charger il serait impensable de penser pouvoir l'exécuter une telle chose sur plusieurs modèles de calculatrices concurrentes ! Casio tire ici profit de son tas (heap)Python correctement dimensionné; un peu plus de 100 Ko sur Graph 35+E II et un peu plus de 1 Mo sur Graph 90+E; les meilleurs solutions Python pour calculatrice sur ce critère à ce jour !
La lecture de matplotlib.py est un véritable délice :
def axis(*L): global fenetre,win_scaling,axis_display if L==(): if win_scaling=='auto': if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] return fenetre elif isinstance(L[0],(list,tuple)) and len(L[0])==4: fenetre=list(L[0]) if fenetre[0]==fenetre[1]: if fenetre[0]==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*fenetre[0],1.05*fenetre[0]] raise Exception('Userwarning: attempting to set identical bottom == top in function axis(); automatically expanding.') if fenetre[2]==fenetre[3]: if fenetre[2]==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*fenetre[2],1.05*fenetre[2]] raise Exception('Userwarning: attempting to set identical bottom == top in function axis(); automatically expanding.') win_scaling='fixed' axis_display='on' return fenetre elif L[0]=='off': axis_display='off' elif L[0]=='on': axis_display='on' elif L[0]=='auto': win_scaling='auto' if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] return fenetre else: raise Exception('function axis() : error using arguments')
def text(x,y,txt): global textes if textes==[[]]: textes[0]=[x,y,txt] else: if [x,y,txt] not in textes : textes+=[[x,y,txt]]
def plot(*L,**kwargs): global color_count,win_scaling # if len(L)==2: # L=([list(L[0]),list(L[1])]) def plotpoint(x,y,c): global points,xmin,xmax,ymin,ymax if points==[[]]: points[0]=[x,y,c] xmin=xmax=x ymin=ymax=y else: if [x,y,c] not in points : points+=[[x,y,c]] xmin=min(x,xmin) xmax=max(x,xmax) ymin=min(y,ymin) ymax=max(y,ymax)
def plotline(x1,y1,x2,y2,c): global lines,xmin,xmax,ymin,ymax if lines==[[]]: lines[0]=[x1,y1,x2,y2,c] xmin=min(x1,x2) xmax=max(x1,x2) ymin=min(y1,y2) ymax=max(y1,y2) else: if [x1,y1,x2,y2,c] not in lines : lines+=[[x1,y1,x2,y2,c]] xmin=min(x1,x2,xmin) xmax=max(x1,x2,xmax) ymin=min(y1,y2,ymin) ymax=max(y1,y2,ymax)
color=kwargs.get('color',None) if color!=None and not color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: raise ValueError('function plot() : unknown color code') if len(L)==2 and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)): plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' elif len(L)==2 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)): if (len(L[0])==len(L[1])): if color==None: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==1 and isinstance(L[0],(list,tuple)): if color==None: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' elif len(L)==3 and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)) and isinstance(L[2],(str)): color=L[2] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: plotpoint(L[0],L[1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') elif len(L)==3 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)) and isinstance(L[2],(str)): if (len(L[0])==len(L[1])): color=L[2] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==2 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(str)): color=L[1] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') else: raise Exception('function plot() : error using arguments')
color_count=0 plt.clear_screen() if win_scaling=='auto': if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] if axis_display=='on' or axis_display=='boxplot': for i in range(limits[0],limits[2]+1): plt.set_pixel(i,limits[1],RGB("k")) for j in range(limits[3],limits[1]+1): plt.set_pixel(limits[0],j,RGB("k")) fenetreb=sorted([fenetre[0],fenetre[1]])+sorted([fenetre[2],fenetre[3]]) gx=round(fenetreb[0],-echelle(fenetreb[0],fenetreb[1])) gy=round(fenetreb[2],-echelle(fenetreb[2],fenetreb[3])) if axis_display=='boxplot': for i in range(nbre_boite): y=fenetre[2] xpixel,ypixel=converttopixel(i+1,y) plt.set_pixel(xpixel,ypixel+1,RGB("k")) plt.draw_string(xpixel,ypixel+3,str(i+1),[0,0,0],"small") else : for i in range(-11,11): x=gx+i*pas(fenetreb[0],fenetreb[1]) y=fenetre[2] xpixel,ypixel=converttopixel(x,y) if round(x,4)==int(x): x=int(round(x,4)) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel+1,RGB("k")) plt.draw_string(xpixel,ypixel+3,str(x),[0,0,0],"small") for j in range(-11,11): x=fenetre[0] y=gy+j*pas(fenetreb[2],fenetreb[3]) xpixel,ypixel=converttopixel(x,y) if round(y,4)==int(y): y=int(round(y,4)) if printable(xpixel,ypixel): plt.set_pixel(xpixel-1,ypixel,RGB("k")) plt.draw_string(xpixel-17,ypixel,str(y),[0,0,0],"small") if points!=[[]]: if points[0]==[]: del points[0] for i in range(len(points)): xpixel,ypixel=converttopixel(points[i][0],points[i][1]) if printable(xpixel,ypixel) and points[i][2]!=None: for j in range(-2,3): plt.set_pixel(xpixel+j,ypixel,RGB(points[i][2])) plt.set_pixel(xpixel,ypixel+j,RGB(points[i][2])) if textes!=[[]]: if textes[0]==[]: del textes[0] for i in range(len(textes)): xpixel,ypixel=converttopixel(textes[i][0],textes[i][1]) if printable(xpixel,ypixel): plt.draw_string(xpixel,ypixel,textes[i][2],[0,0,0],"small") if lines!=[[]]: if lines[0]==[]: del lines[0] for i in range(len(lines)): xpixel1,ypixel1=converttopixel(lines[i][0],lines[i][1]) xpixel2,ypixel2=converttopixel(lines[i][2],lines[i][3]) deltax=abs(xpixel2-xpixel1) deltay=abs(ypixel2-ypixel1) if deltax==deltay==0: if printable(xpixel1,ypixel1): plt.set_pixel(xpixel1,ypixel1,RGB(lines[i][4])) if deltax<=1 and deltay<=1: if printable(xpixel1,ypixel1): plt.set_pixel(xpixel1,ypixel1,RGB(lines[i][4])) plt.set_pixel(xpixel2,ypixel2,RGB(lines[i][4])) if deltax>=deltay and deltax!=0: m=(ypixel2-ypixel1)/(xpixel2-xpixel1) p=ypixel1-m*xpixel1 xpixelmin=max(limits[0],min(xpixel1,xpixel2)) xpixelmax=min(limits[2],max(xpixel1,xpixel2)) if xpixelmin<=limits[2] and xpixelmax>=limits[0]: for xpixel in range(xpixelmin,xpixelmax+1): ypixel=round(m*xpixel+p) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel,RGB(lines[i][4])) if deltay>deltax: m=(xpixel2-xpixel1)/(ypixel2-ypixel1) p=xpixel1-m*ypixel1 ypixelmin=max(limits[3],min(ypixel1,ypixel2)) ypixelmax=min(limits[1],max(ypixel1,ypixel2)) if ypixelmin<=limits[1] and ypixelmax>=limits[3]: for ypixel in range(ypixelmin,ypixelmax+1): xpixel=round(m*ypixel+p) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel,RGB(lines[i][4])) axis([limits[0]-50,limits[2],limits[1]+50,limits[3]]) axis("off") plt.show_screen() points=[[]] lines=[[]] textes=[[]] xmin,xmax,ymin,ymax=0,1,0,1 fenetre=[0,1,0,1] axis_display='on' win_scaling='init' color_count=0
def bar(val,eff,lar=0.8): val=list(val) eff=list(eff) global color_count if isinstance(val,(list,tuple)) and isinstance(eff,(list,tuple)): if len(val)==len(eff): for i in range(len(val)): plot([val[i]-lar/2,val[i]-lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]+lar/2,val[i]+lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]-lar/2,val[i]+lar/2],[eff[i],eff[i]],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function bar() : lists must have same dimension') elif isinstance(val,(int,float)) and isinstance(eff,(int,float)): for i in range(len(val)): plot([val[i]-lar/2,val[i]-lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]+lar/2,val[i]+lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]-lar/2,val[i]+lar/2],[eff[i],eff[i]],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function bar() : error using arguments or arguments not available in this version')
def scatter(xlist,ylist): xlist=list(xlist) ylist=list(ylist) global color_count if isinstance(xlist,(list,tuple)) and isinstance(ylist,(list,tuple)): if len(xlist)==len(ylist): for i in range(len(xlist)): plot(xlist[i],ylist[i],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function scatter() : x and y must have same dimension')
elif isinstance(xlist,(int,float)) and isinstance(ylist,(int,float)): plot(xlist,ylist,color_auto[color_count%7]) color_count+=1 else: raise ValueError('function scatter() : error using arguments or arguments not available in this version')
def boxplotFR(L): L=list(L) global fenetre,color_count,nbre_boite, axis_display,win_scaling print("boxplotFR:definition \nfrancaise du \ndiagramme en boite") axis_display='boxplot' n=len(L) if type(L[0])==int or type(L[0])==float: n=1 nbre_boite=n largeur=0.3/n
for i in range(n): if n==1: if type(L[0])==int or type(L[0])==float: K=L else: K=L[0] else : K=L[i] if type(K)==int or type(K)==float: plot([i+1-largeur,i+1+largeur],[K,K],'r') elif type(K[0])==int or type(K[0])==float: K=sorted(K) p=len(K) Q1=quartiles(K)[0] Q3=quartiles(K)[1] D1=deciles(K)[0] D9=deciles(K)[1] plot([i+1-largeur,i+1+largeur,i+1+largeur,i+1-largeur,i+1-largeur],[Q1,Q1,Q3,Q3,Q1],'k') plot([i+1,i+1],[Q1,D1],'k') plot([i+1,i+1],[Q3,D9],'k') plot([i+1-largeur/2,i+1+largeur/2],[D1,D1],'k') plot([i+1-largeur/2,i+1+largeur/2],[D9,D9],'k') plot(i+1,K[0],'k') plot(i+1,K[p-1],'k') plot([i+1-largeur,i+1+largeur],[mediane(K),mediane(K)],'r') elif type(min(L[0]))!=int and type(min(L[0]))!=float: raise ValueError('wrong type of argument') if type(L[0])==int or type(L[0])==float: fenetre=[0,2,min(L)-1,max(L)+1] Max=max(L) else: Min=min(L[0]) Max=max(L[0]) for i in range(len(L)): if type(L[i])==int or type(L[i])==float: if L[i]<Min: Min=L[i] if L[i]>Max: Max=L[i] else: if min(L[i])<Min: Min=min(L[i]) if max(L[i])>Max: Max=max(L[i]) fenetre=[0,len(L)+1,Min-1,Max+1] win_scaling='fixed' text(len(L)+1/4,Max+1/2,"boxplotFR")
def boxplot(L,**kwargs): L=list(L) global fenetre,color_count,nbre_boite, axis_display,win_scaling whis=kwargs.get('whis',1.5) axis_display='boxplot' n=len(L) if type(L[0])==int or type(L[0])==float: n=1 nbre_boite=n largeur=0.3/n def mediane(l): r=1 if type(l)!=int and type(l)!=float: l=sorted(l) r=len(l) if r%2==0 and r//2>0: return (l[r//2]+l[r//2-1])/2,l[:r//2],l[r//2:] else: return l[r//2],l[:r//2],l[r//2+1:] return l,l,l if type(L[0])==int or type(L[0])==float: if min(L)==max(L): ampl=1 else: ampl=max(L)-min(L) fenetre=[0,2,min(L)-ampl/20,max(L)+ampl/20] else: Min=min(L[0]) Max=max(L[0]) for i in range(len(L)): if type(L[i])==int or type(L[i])==float: if L[i]<Min: Min=L[i] if L[i]>Max: Max=L[i] else: if min(L[i])<Min: Min=min(L[i]) if max(L[i])>Max: Max=max(L[i]) if Min==Max: ampl=1 else: ampl=Max-Min fenetre=[0,len(L)+1,Min-ampl/20,Max+ampl/20] win_scaling='fixed' for i in range(n): if n==1: if type(L[0])==int or type(L[0])==float: K=L else: K=L[0] else : K=L[i] if type(K)==int or type(K)==float: plot([i+1-largeur,i+1+largeur],[K,K],'r') elif type(K[0])==int or type(K[0])==float: K=sorted(K) p=len(K) Q1,Q3=mediane(mediane(K)[1])[0],mediane(mediane(K)[2])[0] down=0 if Q1-whis*(Q3-Q1)<=K[0]: down=0 else : while Q1-whis*(Q3-Q1)>K[down]: down+=1 up=p-1 if Q3+whis*(Q3-Q1)>=K[p-1]: up=p-1 else : while Q3+whis*(Q3-Q1)<K[up]: up-=1 plot([i+1-largeur,i+1+largeur,i+1+largeur,i+1-largeur,i+1-largeur],[Q1,Q1,Q3,Q3,Q1],'k') plot([i+1,i+1],[Q1,K[down]],'k') plot([i+1,i+1],[Q3,K[up]],'k') plot([i+1-largeur/2,i+1+largeur/2],[K[down],K[down]],'k') plot([i+1-largeur/2,i+1+largeur/2],[K[up],K[up]],'k') from math import pi from math import cos from math import sin if down>0: for t in range(down): x=[i+1+0.05*(fenetre[1])/3*cos(2*j*pi/50) for j in range(50)] y=[K[t]+0.05*(fenetre[3]-fenetre[2])/3*sin(2*j*pi/50) for j in range(50)] plot(x,y,'k') if up<p-1: for t in range(p-1-up): x=[i+1+0.05*(fenetre[1])/3*cos(2*j*pi/50) for j in range(50)] y=[K[p-1-t]+0.05*(fenetre[3]-fenetre[2])/3*sin(2*j*pi/50) for j in range(50)] plot(x,y,'k') plot([i+1-largeur,i+1+largeur],[mediane(K)[0],mediane(K)[0]],'r') elif type(min(L[0]))!=int and type(min(L[0]))!=float: raise ValueError('wrong type of argument')
def axis(*L): global fenetre,win_scaling,axis_display if L==(): if win_scaling=='auto': if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] return fenetre elif isinstance(L[0],(list,tuple)) and len(L[0])==4: fenetre=list(L[0]) if fenetre[0]==fenetre[1]: if fenetre[0]==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*fenetre[0],1.05*fenetre[0]] raise Exception('Userwarning: attempting to set identical bottom == top in function axis(); automatically expanding.') if fenetre[2]==fenetre[3]: if fenetre[2]==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*fenetre[2],1.05*fenetre[2]] raise Exception('Userwarning: attempting to set identical bottom == top in function axis(); automatically expanding.') win_scaling='fixed' axis_display='on' return fenetre elif L[0]=='off': axis_display='off' elif L[0]=='on': axis_display='on' elif L[0]=='auto': win_scaling='auto' if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] return fenetre else: raise Exception('function axis() : error using arguments')
def text(x,y,txt): global textes if textes==[[]]: textes[0]=[x,y,txt] else: if [x,y,txt] not in textes : textes+=[[x,y,txt]]
def plot(*L,**kwargs): global color_count,win_scaling # if len(L)==2: # L=([list(L[0]),list(L[1])]) def plotpoint(x,y,c): global points,xmin,xmax,ymin,ymax if points==[[]]: points[0]=[x,y,c] xmin=xmax=x ymin=ymax=y else: if [x,y,c] not in points : points+=[[x,y,c]] xmin=min(x,xmin) xmax=max(x,xmax) ymin=min(y,ymin) ymax=max(y,ymax)
def plotline(x1,y1,x2,y2,c): global lines,xmin,xmax,ymin,ymax if lines==[[]]: lines[0]=[x1,y1,x2,y2,c] xmin=min(x1,x2) xmax=max(x1,x2) ymin=min(y1,y2) ymax=max(y1,y2) else: if [x1,y1,x2,y2,c] not in lines : lines+=[[x1,y1,x2,y2,c]] xmin=min(x1,x2,xmin) xmax=max(x1,x2,xmax) ymin=min(y1,y2,ymin) ymax=max(y1,y2,ymax)
color=kwargs.get('color',None) if color!=None and not color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: raise ValueError('function plot() : unknown color code') if len(L)==2 and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)): plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' elif len(L)==2 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)): if (len(L[0])==len(L[1])): if color==None: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==1 and isinstance(L[0],(list,tuple)): if color==None: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' elif len(L)==3 and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)) and isinstance(L[2],(str)): color=L[2] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: plotpoint(L[0],L[1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 plotpoint(L[0],L[1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') elif len(L)==3 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)) and isinstance(L[2],(str)): if (len(L[0])==len(L[1])): color=L[2] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==2 and isinstance(L[0],(list,tuple)) and isinstance(L[1],(str)): color=L[1] if (len(color)==2 and color[0] in ['b','r','g','k','m','c','y','w']) and color[1] in ['o','.','+','*','-']: for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color[0]) if win_scaling=='init': win_scaling='auto' elif color in ['b','r','g','k','m','c','y','w','blue','red','green','black','magenta','cyan','yellow','white']: for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' elif color in ['o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],color) if win_scaling=='init': win_scaling='auto' else: raise ValueError('function plot() : available color codes are b,r,g,k,m,c,y,w') else: raise Exception('function plot() : error using arguments')
color_count=0 plt.clear_screen() if win_scaling=='auto': if xmin==xmax: if xmin==0: fenetre[0:2]=[-0.05,0.05] else: fenetre[0:2]=[0.95*xmin,1.05*xmin] else: fenetre[0:2]=[xmin-0.05*(xmax-xmin),xmax+0.05*(xmax-xmin)] if ymin==ymax: if ymin==0: fenetre[2:4]=[-0.05,0.05] else: fenetre[2:4]=[0.95*ymin,1.05*ymin] else: fenetre[2:4]=[ymin-0.05*(ymax-ymin),ymax+0.05*(ymax-ymin)] if axis_display=='on' or axis_display=='boxplot': for i in range(limits[0],limits[2]+1): plt.set_pixel(i,limits[1],RGB("k")) for j in range(limits[3],limits[1]+1): plt.set_pixel(limits[0],j,RGB("k")) fenetreb=sorted([fenetre[0],fenetre[1]])+sorted([fenetre[2],fenetre[3]]) gx=round(fenetreb[0],-echelle(fenetreb[0],fenetreb[1])) gy=round(fenetreb[2],-echelle(fenetreb[2],fenetreb[3])) if axis_display=='boxplot': for i in range(nbre_boite): y=fenetre[2] xpixel,ypixel=converttopixel(i+1,y) plt.set_pixel(xpixel,ypixel+1,RGB("k")) plt.set_pixel(xpixel,ypixel+2,RGB("k")) plt.set_pixel(xpixel,ypixel+3,RGB("k")) plt.draw_string(xpixel,ypixel+13,str(round(i+1,8)),[0,0,0],"small") else : for i in range(-11,11): x=gx+i*pas(fenetreb[0],fenetreb[1]) y=fenetre[2] xpixel,ypixel=converttopixel(x,y) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel+1,RGB("k")) plt.set_pixel(xpixel,ypixel+2,RGB("k")) plt.set_pixel(xpixel,ypixel+3,RGB("k")) plt.draw_string(xpixel,ypixel+13,str(round(x,8)),[0,0,0],"small") for j in range(-11,11): x=fenetre[0] y=gy+j*pas(fenetreb[2],fenetreb[3]) xpixel,ypixel=converttopixel(x,y) if printable(xpixel,ypixel): plt.set_pixel(xpixel-1,ypixel,RGB("k")) plt.set_pixel(xpixel-2,ypixel,RGB("k")) plt.set_pixel(xpixel-3,ypixel,RGB("k")) plt.draw_string(xpixel-40,ypixel,str(round(y,8)),[0,0,0],"small") if points!=[[]]: if points[0]==[]: del points[0] for i in range(len(points)): xpixel,ypixel=converttopixel(points[i][0],points[i][1]) if printable(xpixel,ypixel) and points[i][2]!=None: for j in range(-2,3): plt.set_pixel(xpixel+j,ypixel,RGB(points[i][2])) plt.set_pixel(xpixel,ypixel+j,RGB(points[i][2])) if textes!=[[]]: if textes[0]==[]: del textes[0] for i in range(len(textes)): xpixel,ypixel=converttopixel(textes[i][0],textes[i][1]) if printable(xpixel,ypixel): plt.draw_string(xpixel,ypixel,textes[i][2],[0,0,0],"small") if lines!=[[]]: if lines[0]==[]: del lines[0] for i in range(len(lines)): xpixel1,ypixel1=converttopixel(lines[i][0],lines[i][1]) xpixel2,ypixel2=converttopixel(lines[i][2],lines[i][3]) deltax=abs(xpixel2-xpixel1) deltay=abs(ypixel2-ypixel1) if deltax==deltay==0: if printable(xpixel1,ypixel1): plt.set_pixel(xpixel1,ypixel1,RGB(lines[i][4])) if deltax<=1 and deltay<=1: if printable(xpixel1,ypixel1): plt.set_pixel(xpixel1,ypixel1,RGB(lines[i][4])) plt.set_pixel(xpixel2,ypixel2,RGB(lines[i][4])) if deltax>=deltay and deltax!=0: m=(ypixel2-ypixel1)/(xpixel2-xpixel1) p=ypixel1-m*xpixel1 xpixelmin=max(limits[0],min(xpixel1,xpixel2)) xpixelmax=min(limits[2],max(xpixel1,xpixel2)) if xpixelmin<=limits[2] and xpixelmax>=limits[0]: for xpixel in range(xpixelmin,xpixelmax+1): ypixel=round(m*xpixel+p) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel,RGB(lines[i][4])) if deltay>deltax: m=(xpixel2-xpixel1)/(ypixel2-ypixel1) p=xpixel1-m*ypixel1 ypixelmin=max(limits[3],min(ypixel1,ypixel2)) ypixelmax=min(limits[1],max(ypixel1,ypixel2)) if ypixelmin<=limits[1] and ypixelmax>=limits[3]: for ypixel in range(ypixelmin,ypixelmax+1): xpixel=round(m*ypixel+p) if printable(xpixel,ypixel): plt.set_pixel(xpixel,ypixel,RGB(lines[i][4])) axis([limits[0]-50,limits[2],limits[1]+50,limits[3]]) axis("off") plt.show_screen() points=[[]] lines=[[]] textes=[[]] xmin,xmax,ymin,ymax=0,1,0,1 fenetre=[0,1,0,1] axis_display='on' win_scaling='init' color_count=0
def bar(val,eff,lar=0.8): val=list(val) eff=list(eff) global color_count if isinstance(val,(list,tuple)) and isinstance(eff,(list,tuple)): if len(val)==len(eff): for i in range(len(val)): plot([val[i]-lar/2,val[i]-lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]+lar/2,val[i]+lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]-lar/2,val[i]+lar/2],[eff[i],eff[i]],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function bar() : lists must have same dimension') elif isinstance(val,(int,float)) and isinstance(eff,(int,float)): for i in range(len(val)): plot([val[i]-lar/2,val[i]-lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]+lar/2,val[i]+lar/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]-lar/2,val[i]+lar/2],[eff[i],eff[i]],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function bar() : error using arguments or arguments not available in this version')
def scatter(xlist,ylist): xlist=list(xlist) ylist=list(ylist) global color_count if isinstance(xlist,(list,tuple)) and isinstance(ylist,(list,tuple)): if len(xlist)==len(ylist): for i in range(len(xlist)): plot(xlist[i],ylist[i],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function scatter() : x and y must have same dimension')
elif isinstance(xlist,(int,float)) and isinstance(ylist,(int,float)): plot(xlist,ylist,color_auto[color_count%7]) color_count+=1 else: raise ValueError('function scatter() : error using arguments or arguments not available in this version')
def boxplotFR(L): L=list(L) global fenetre,color_count,nbre_boite, axis_display,win_scaling print("boxplotFR:definition \nfrancaise du \ndiagramme en boite") axis_display='boxplot' n=len(L) if type(L[0])==int or type(L[0])==float: n=1 nbre_boite=n largeur=0.3/n
for i in range(n): if n==1: if type(L[0])==int or type(L[0])==float: K=L else: K=L[0] else : K=L[i] if type(K)==int or type(K)==float: plot([i+1-largeur,i+1+largeur],[K,K],'r') elif type(K[0])==int or type(K[0])==float: K=sorted(K) p=len(K) Q1=quartiles(K)[0] Q3=quartiles(K)[1] D1=deciles(K)[0] D9=deciles(K)[1] plot([i+1-largeur,i+1+largeur,i+1+largeur,i+1-largeur,i+1-largeur],[Q1,Q1,Q3,Q3,Q1],'k') plot([i+1,i+1],[Q1,D1],'k') plot([i+1,i+1],[Q3,D9],'k') plot([i+1-largeur/2,i+1+largeur/2],[D1,D1],'k') plot([i+1-largeur/2,i+1+largeur/2],[D9,D9],'k') plot(i+1,K[0],'k') plot(i+1,K[p-1],'k') plot([i+1-largeur,i+1+largeur],[mediane(K),mediane(K)],'r') elif type(min(L[0]))!=int and type(min(L[0]))!=float: raise ValueError('wrong type of argument') if type(L[0])==int or type(L[0])==float: fenetre=[0,2,min(L)-1,max(L)+1] Max=max(L) else: Min=min(L[0]) Max=max(L[0]) for i in range(len(L)): if type(L[i])==int or type(L[i])==float: if L[i]<Min: Min=L[i] if L[i]>Max: Max=L[i] else: if min(L[i])<Min: Min=min(L[i]) if max(L[i])>Max: Max=max(L[i]) fenetre=[0,len(L)+1,Min-1,Max+1] win_scaling='fixed' text(len(L)+1/4,Max+1/2,"boxplotFR")
def boxplot(L,**kwargs): L=list(L) global fenetre,color_count,nbre_boite, axis_display,win_scaling whis=kwargs.get('whis',1.5) axis_display='boxplot' n=len(L) if type(L[0])==int or type(L[0])==float: n=1 nbre_boite=n largeur=0.3/n def mediane(l): r=1 if type(l)!=int and type(l)!=float: l=sorted(l) r=len(l) if r%2==0 and r//2>0: return (l[r//2]+l[r//2-1])/2,l[:r//2],l[r//2:] else: return l[r//2],l[:r//2],l[r//2+1:] return l,l,l if type(L[0])==int or type(L[0])==float: if min(L)==max(L): ampl=1 else: ampl=max(L)-min(L) fenetre=[0,2,min(L)-ampl/20,max(L)+ampl/20] else: Min=min(L[0]) Max=max(L[0]) for i in range(len(L)): if type(L[i])==int or type(L[i])==float: if L[i]<Min: Min=L[i] if L[i]>Max: Max=L[i] else: if min(L[i])<Min: Min=min(L[i]) if max(L[i])>Max: Max=max(L[i]) if Min==Max: ampl=1 else: ampl=Max-Min fenetre=[0,len(L)+1,Min-ampl/20,Max+ampl/20] win_scaling='fixed' for i in range(n): if n==1: if type(L[0])==int or type(L[0])==float: K=L else: K=L[0] else : K=L[i] if type(K)==int or type(K)==float: plot([i+1-largeur,i+1+largeur],[K,K],'r') elif type(K[0])==int or type(K[0])==float: K=sorted(K) p=len(K) Q1,Q3=mediane(mediane(K)[1])[0],mediane(mediane(K)[2])[0] down=0 if Q1-whis*(Q3-Q1)<=K[0]: down=0 else : while Q1-whis*(Q3-Q1)>K[down]: down+=1 up=p-1 if Q3+whis*(Q3-Q1)>=K[p-1]: up=p-1 else : while Q3+whis*(Q3-Q1)<K[up]: up-=1 plot([i+1-largeur,i+1+largeur,i+1+largeur,i+1-largeur,i+1-largeur],[Q1,Q1,Q3,Q3,Q1],'k') plot([i+1,i+1],[Q1,K[down]],'k') plot([i+1,i+1],[Q3,K[up]],'k') plot([i+1-largeur/2,i+1+largeur/2],[K[down],K[down]],'k') plot([i+1-largeur/2,i+1+largeur/2],[K[up],K[up]],'k') from math import pi from math import cos from math import sin if down>0: for t in range(down): x=[i+1+0.05*(fenetre[1])/3*cos(2*j*pi/50) for j in range(50)] y=[K[t]+0.05*(fenetre[3]-fenetre[2])/3*sin(2*j*pi/50) for j in range(50)] plot(x,y,'k') if up<p-1: for t in range(p-1-up): x=[i+1+0.05*(fenetre[1])/3*cos(2*j*pi/50) for j in range(50)] y=[K[p-1-t]+0.05*(fenetre[3]-fenetre[2])/3*sin(2*j*pi/50) for j in range(50)] plot(x,y,'k') plot([i+1-largeur,i+1+largeur],[mediane(K)[0],mediane(K)[0]],'r') elif type(min(L[0]))!=int and type(min(L[0]))!=float: raise ValueError('wrong type of argument')
def resol(A,B,C): D=B**2-4*A*C if D>0: return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A)) if dx==0: if dy>=0: c=1 else: c=-1 plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),color) elif dy==0: if dx>=0: c=1 else: c=-1 plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),color) else: m=dy/dx p=y-m*x S=resol(m**2+1,2*(-a-b*m+m*p),p**2+a**2+b**2-l**2-2*b*p) if S[0]*dx<0: X=S[0] else: X=S[1] Y=m*X+p k=b+a/m T=resol(1+1/m**2,2*(-a-k/m+b/m),a**2+k**2-2*b*k+b**2-(L**2)/4) plot((T[0],T[1],X,T[0]),(-T[0]/m+k,-T[1]/m+k,Y,-T[0]/m+k),headcolor)
Testons maintenant la conformité de cette interface matplotl.py avec le module matplotlib.pyplot standard, ainsi que la compatibilité entre différentes calculatrices graphiques.
Nous allons pour cela prendre plusieurs exemples où nous lancerons le même code sur différents modèles.
Commençons déjà avec les fonctions de base, comme axis() pour régler les bornes de la fenêtre graphique, même si ce n'est pas obligatoire et qu'elles s'adapteront par défaut au contenu affiché :
Ici nous travaillons donc non pas sur des pixels mais des coordonnées, ce qui permet à la Graph 35+E II de nous produire sans effort pour le même code un affichage similaire correct et ce malgré un écran plus petit, c'est fantastique !
Passons maintenant à des nuages de points à l'aide de la fonction scatter() :
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
x = [100, 110, 120, 130, 140, 150, 160] y = [105, 95, 75, 68, 53, 46, 31]
scatter(x, y) axis([80, 170, 10, 130]) text(110, 125, "Nombre d'acheteurs vs prix de vente") show()
Un petit problème de positionnement de texte sur la NumWorks. Au lieu d'utiliser comme les autres les coordonnées comme coin supérieur gauche du texte affiché, elle les utilise apparemment comme coin inférieur gauche...
Mais précisons que c'est compensé sur NumWorks par la possibilité de faire défiler la fenêtre graphique en cours d'affichage à l'aide des flèches du clavier, ce qui n'est pas possible chez Casio.
Passons maintenant à quelques diagrammes en ligne brisée et à la fonction plot() :
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
def fonction(): def f(x): return x**3-6*x**2+9*x+1 start = -0.5 end = 4.5 steps = 0.1 x = [start+i*steps for i in range(int((end-start)/steps)+1)] y = [f(j) for j in x] plot(x, y) show()
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
plot([1,5,7],[8,12,10],"magenta") show()
Ah, problème ici sur la NumWorks qui n'accepte pas le 3ème argument pour la couleur avec la fonction plot(). C'est embêtant, vu que c'est du standard puisque fonctionnel sur ordinateur. Que la gestion des couleurs n'ait pas été codée est une chose, mais à des fins de compatibilité il eut mieux valu ignorer l'argument de couleur que le refuser...
Casio nous signe ici encore une superbe pièce d'horlogerie.
Une réimplémentation en Python hautement fidèle du module matplotlib.pyplot. Elle réussit l'exploit d'être nettement plus fidèle au standard que le portage direct du code source chez NumWorks. Toutefois il convient de nuancer, Casio est sur ce projet depuis des mois et NumWorks à notre connaissance depuis à peine quelques semaines.
N'ayons pas peur des mots, Casio nous signe aujourd'hui une superbe mise à jour pour ta Graph 35+E II ou Graph 90+E.
Le respect d'un standard préexistant (modules turtle et matplotlib.pyplot) est fort intéressant, introduisant des compatibilités au niveau des instructions graphiques jamais vues en plus de trois décennies de calculatrices graphiques scolaires :
excellente compatibilité entre modèles de la même marque utilisant des écrans couleur et monochromes (Graph 35+E II et Graph 90+E)
excellente compatibilité entre modèles de la même marque utilisant des écrans de définitions différentes (Graph 35+E II et Graph 90+E)
enfin une compatibilité entre modèles de marques différentes (Graph 90+E / 35+E II et NumWorks); certes une compatibilité à améliorer mais cela n'en reste pas moins énorme pour un début !
compatibilité vers le Python complet pour ordinateur
C'est d'autant plus remarquable que la solution choisie, celle de réimplémenter intégralement ces modules sous le forme de scripts Python interfaçant casioplot n'était pas la plus simple, chapeau !
Il n'empêche que cette décision nous surprend. Cela nous donne l'impression que le projet d'avoir turtle et matplotlib.pyplot pour cette mise à jour a été un projet piloté au niveau de Casio France, sans grande implication des équipes de développement de Casio Japan.
C'est un choix qui a également des conséquences plus ou moins regrettables qui renforcent notre impression :
déjà matplotl.py et turtle.py étant ici des scripts et non des modules, ils ne sont donc pas listés au catalogue, leurs fonctions non plus, et sur calculatrice il faudra donc saisir les noms de ces dernières à la main lettre par lettre
mais surtout, matplotl.py et turtle.py n'étant pas des éléments intégrés à la mise à jour mais des fichiers à charger séparément comme n'importe quel autre fichier tiers, le système les considère effectivement comme des fichiers tiers et ils disparaissent en mode examen, et ça c'est hautement problématique dans le contexte français
Notre bilan global n'en reste pas moins très positif, c'est une superbe avancée et dans tous les cas largement mieux que rien.
En ce jour historique, les hautes compatibilité et conformité au standard ouvrent à nous tous, enseignants et lycéens, de formidables nouvelles possibilités de mutualisation en classe, d'activités et de projets; nous avons hâte de voir ce que cela va donner !
Espérons simplement que ces fonctionnalités pourront quand même continuer à évoluer à l'avenir dans le sens des besoins des lycéens français et donc vers une meilleure intégration au sein de la calculatrice.
Dans sa prochaine mise à jour gratuite pour Graph 35+E II et Graph 90+E, Casio va rajouter de formidables possibilités graphiques à son application Python sous la forme de deux modules importables :
matplotl(en fait un matplotlib.pyplot)
turtle
Les fonctions implémentées sont de plus conformes aux modules Python de même nom déjà existants sur d'autres plateformes, si bien que les scripts conçus pour ta calculatrice Casio seront compatibles !
Afin de te les faire découvrir en avant-première Casio t'invitait à un formidable événement, la tournée pédagique, au cours duquel le constructeur se proposait de faire le tour de France avec des étapes dans pas moins de 18 villes en avril et mai 2020.
Dans le contexte de la crise sanitaire qui nous touche actuellement, les étapes du mois d'avril 2020 sont annulées :
Mercredi 8 avril : Bordeaux, Dijon, Grenoble
Mercredi 29 avril : Créteil, Nice, Reims
Mercredi 6 mai : Clermont-Ferrand, Mulhouse, Rouen, Toulouse
Mercredi 13 mai : La Rochelle, Nancy, Rennes, Versailles
Mercredi 27 mai : Lille, Lyon, Nantes, Paris
Toutefois, en remplacement Casio te propose ce mois d'avril de découvrir ces mêmes nouveautés lors de formations en ligne rajoutées à son calendrier :
Mercredi 1er avril - 14h-14h45 : mises à jour Graph 90/35+E II; bibliothèques graphiques Pythonmatplotlib et turtle
Lundi 6 avril - 14h-15h30 : tournée pédagogique en ligne; atelier collège
Mercredi 8 avril - 14h-16h : tournée pédagogique en ligne; atelier lycée
Mercredi 15 avril - 14h-15h30 : tournée pédagogique en ligne; atelier collège
Vendredi 17 avril - 14h-16h : tournée pédagogique en ligne; atelier lycée
Pour toute participation à la tournée pédagogique, Casio te proposait de repartir avec l'une des calculatrices mises à ta disposition lors de la formation. Et bien précisons que cette offre est maintenue de le cadre de la tournée pédagogique en ligne, la calculatrice en question sera expédiée à la fin du confinement.
Dans le cadre de sa tournée pédagogique à compter du 8 avril, Casio se proposait de faire le tour de la Métropole pour venir te présenter les nouveaux modules Pythonturtle et matplotl de sa prochaine mise à jour gratuite pour Graph 35+E II et Graph 90+E qui devrait justement sortir le 8 avril.
Des nouveautés hautement pertinentes; turtle permettra par exemple en Seconde de passer au Python tout en s'appuyant sur les acquis de Scratch du collègue ! Quant à lui matplotl t'offrira des possibilités graphiques conformes aux attendus du programme de Physique-Chimie de Seconde, mais également utilisables en Maths (fonctionnement d'un grapheur de fonction) ou encore pour les activités/projets de SNT ou NSI, qui plus est avec une compatibilité matplotlib.pyplot !
A date la tournée pédagogique n'est encore ni annulée ni reportée ni allégée, mais avec la crise sanitaire qui nous touche actuellement autant prendre ses précautions.
Casio se propose donc dans tous les cas de te présenter ces nouveautés lors d'une formation en ligne de 45 minutes le Mercredi 1er avril à 14h.
Enseignant ce n'est pas tout, pour préparer tes documents numériques pour tes élèves dans le cadre de la continuité pédagogique, comme Texas InstrumentsCasio t'offre également des licences gratuites d'un an pour l'ensemble des logiciels d'émulation de ses calculatrices commercialisées en France !