En juin 2020, nous découvrions avec toi la dernière mise à jour 2.01.7000 du système d'exploitation de ta calculatrice couleur, tactile et formelle Casio fx-CP400.
Au menu au moins des reformulations de messages lorsque la calculatrice était réglée en allemand ou en finnois. Et sans doute d'autres choses, mais comme Casio ne publie pas de changelog détaillé il nous est difficile de tomber dessus parmi la vaste étendue de possibilités de cette machine.
Précisons de plus que Casio t'offre également des applications Classpad et fx-CG500 qui te permettent de retrouver sur ton smartphoneAndroid toutes les possibilités de ses calculatrices haut de gamme.
Toutefois, ces applications étaient jusqu'à présent restées en version 1.0.8, émulant l'ancien système 2.01.6000.
Et bien réjouis-toi car en ce 30 octobre ton attente touche enfin à sa fin, Casio vient enfin de mettre à jour ses applications en version 1.0.9, émulant désormais le tout dernier système 2.01.7000. Tu peux donc dès maintenant profiter sur ton smartphone de l'intégralité des dernières améliorations apportées à la gamme Classpad !
Casio vient tout juste de nous sortir des mises à jour 3.40 et 3.50 absolument superbes pour ses Graph 35+E II et Graph 90+E. Au menu des possibilités Python étendues avec :
pour le module de tracé par pixels casioplot l'indexation dans le catalogue de la fonction de nettoyage clear_screen()
concernant le module de tracés relatifs turtle :
il devient intégré au système, donc indexé au catalogue et disponible en mode examen
la fonction pensize() est maintenant fonctionnelle
quant au module de tracé par coordonnées matplotl :
il est renommé matplotlib.pyplot pour une meilleure compatibilité avec les scripts provenant d'autres plateformes
il devient lui aussi intégré au système, donc indexé au catalogue et disponible en mode examen
la fonction boxplot() gère désormais le tracé à la française des diagrammes en boîte via un paramètre nommé optionnel
nouvelle fonction hist() pour le tracé d'histogrammes, gérant également le tracé à la française via un paramètre nommé optionnel
correction de la fonction arrow() qui dans certains cas traçait les pointes de flèches de vecteurs à l'envers, et en prime remplit désormais ces dernières sur Graph 90+E
Mais par contre, jusqu'à présent la mise à jour ne concernait que les calculatrices, pas les émulateurs pour ordinateur.
Tu pouvais certes leur rajouter manuellement les nouvelles versions turtle.py et matplotl.py que nous t'avions diffusé à l'occasion, mais cela ne te rajoutait pas l'intégralité des nouveautés :
aucun nouvelle entrée indexée au catalogue via cette méthode
et tu ne bénéficiais pas non plus du renommage de matplotl en matplotlib.pyplot de cette façon
Et bien ce fut rapide, Casio te diffuse déjà des mises à jour pour ses émulateurs sur clés USB d'émulation, bien évidemment compatibles avec les deux versions en circulation à ce jour.
Il te suffira tout simplement de placer les fichiers .zip disponibles ci-dessous à la racine de ta clé USB, d'en lancer l'extraction, et éventuellement de confirmer l'écrasement des anciens fichiers. Si tu sais ce que tu fais, tu peux également copier-coller le nouveau fichier .exe directement au bon endroit.
Tu pourras ainsi bénéficier de l'intégralité des nouvelles fonctionnalités en classe dès la rentrée ! Merci Casio.
Téléchargements :
Mises à jour des émulateurs sur clé USB : (clé USB d'émulation officielle uniquement)
Juste à temps pour le lancement des journées APMEP ce week-end, Casio nous a offert une mise à jour majeure de l'ensemble de sa gamme graphique non formelle !
Pour une fois, les mises à jour ciblent aussi bien les dernières générations monochromes et couleurs que les générations les ayant précédées :
3.50 pour Graph 90+E et fx-CG50
3.40 pour la génération monochrome USB Power Graphic 3(Graph 35+E II en France, fx-9750GIII et fx-9860GIII dans d'autres pays)
3.12 pour fx-CG10 et fx-CG20
2.11 pour les anciennes générations monochromes USB Power Graphic 1 et USB Power Graphic 2
Des nouveautés d'importance sont donc ici transversales, d'où notre tentative de les traiter dans un unique article.
Avant cela, nous avons une petite chose à mettre au point. Les logiciels d'installation de mises à jour Casio contiennent usuellement plusieurs images système installables sur différentes variantes d'un modèle selon les pays. Avant de traiter des nouveautés, listons donc rapidement ce que nous avons ici afin de pouvoir nous y référer plus tard :
Mise à jour
Image système
Version nouvelle + précédente
Timbre à date nouveau + précédent
Référence modèles ciblés
Modèles ciblés
3.50
3070
3.50 3.40
2020.0924.1830 2020.0313.0216
CY810A
Graph 90+E, fx-CG50
3071
3.50 3.40
2020.0924.1845 2020.0313.0229
CY810F
fx-CG50AU
3.40
3070
3.40 3.30
2020.0918.1757 2020.0313.0229
CY835A
Graph 35+E II
3071
3.40 3.21
2020.0918.1811 2020.0313.0229
CY837A
fx-9860GIII
3072
3.40 3.21
2020.0918.1820 2020.0313.0229
CY838A
fx-9750GIII
3.12
3070
3.12 3.11
2020.0924.1914 2018.0308.1942
LY755A
fx-CG10/20
3071
3.12 3.11
2020.0924.1926 2018.0308.1951
LY755F
fx-CG20AU
2.11
3071
2.08
2015.1201.1207
GY493A
fx-9860GII SD(USB Power Graphic 1)
3072
2.08
2015.1201.1207
GY493B
Graph 95(USB Power Graphic 1)
3073
2.08
2015.1201.1215
GY495A
fx-9860GII(USB Power Graphic 1)
3074
2.08
2015.1201.1219
GY495B
Graph 75(USB Power Graphic 1)
3075
2.08
2015.1201.1223
GY495E
fx-9860G AU
3080
2.11 2.09
2020.0910.1404 2015.1204.1158
GY497A
fx-9860GII SD(USB Power Graphic 2)
3081
2.09
2015.1204.1203
GY497B
Graph 95(USB Power Graphic 2)
3082
2.09
2015.1204.1208
GY498A
fx-9860GIIs
3083
2.11 2.09
2020.0910.1353 2015.1204.1213
GY499A
fx-9860GII(USB Power Graphic 2)
3084
2.09
2015.1204.1218
GY499B
Graph 75+
3085
2.09
2015.1204.1223
GY499E
fx-9860G AU+
3086
2.09
2015.1202.1718
CY802A
Graph 75+E
Pour ce qui est simple, nous avons donc :
la Graph 90+E et ses équivalents internationaux fx-CG50 qui passent de la version 3.40 du 13 mars 2020 à la nouvelle version 3.50 compilée le 24 septembre 2020
la Graph 35+E II qui passe de la version 3.30 du 13 mars 2020 à la nouvelle version 3.40 compilée le 18 septembre 2020
ses pendants internationaux fx-9750GIII et fx-9860GIII qui passent directement de la version 3.21 du 13 mars 2020 à la nouvelle version 3.40 compilée le 18 septembre 2020
Quant à la mise à jour 2.11 pour les anciennes générations monochromes USB Power Graphic 1 et USB Power Graphic 2 :
rien de nouveau pour les modèles de la génération USB Power Graphic 1(processeur SH3) qui ne seront mis à jour qu'au maximum vers la version 2.08 compilée le 1er décembre 2015
rien de nouveau non plus pour les déclinaisons locales à certains pays de la génération USB Power Graphic 2(Graph 75+ et Graph 75+E pour la France, fx-9860G AU+ pour l'Australie, fx-9860GIIs pour Singapour) qui ne seront mis à jour qu'au maximum vers la version 2.09 compilée le 4 décembre 2015
Ne peuvent être mis à jour vers la nouvelle version 2.11 que les seuls modèles internationaux de la génération USB Power Graphic 2 : fx-9860G II et fx-9860GII SD.
Maintenant que nous avons toutes ces bases, découvrons ensemble les nouveautés.
Commençons par les nouveautés autour de l'application Python intégrée apportées à la fois :
par la mise à jour 3.50 de la dernière génération couleur :
Graph 90+E
fx-CG50
par la mise à jour 3.40 de la dernière génération monochrome :
Graph 35+E II
fx-9860GIII
fx-9750GIII
Rappelons que les fx-9860GIII et fx-9750GIII, équivalents de la Graph 35+E II respectivement en Europe et Amérique du Nord, n'ont à la différence de cette dernière pas bénéficié d'une mise à jour intermédiaire 3.30. En passant directement de la version 3.21 à 3.40, leur application Python bénéficie déjà de tout ce qui a été apporté sur Graph 35+E II avec la version 3.30 et que nous t'invitons à aller consulter, et notamment enfin du module de tracé par pixels casioplot.
Passons maintenant aux nouveautés spécifiquement apportées par la dernière version 3.40 ou 3.50.
Nous avions déjà remarqué que le module de tracé par pixels casioplot offrait une fonction clear_screen() pour effacer l'écran, fonction parfaitement fonctionnelle mais qui bizarrement n'était pas au catalogue de modules et fonctions accessible via
SHIFT
4
, et les appels à cette fonction doivent redonc être saisis à la main caractère par caractère.
Désormais clear_screen() est bien disponible au catalogue.
La dernière mise à jour apportait donc le module de tracé par pixels casioplot. Casio France diffusait de plus un script turtle.py, une réécriture complète en Python du module de tracés relatifs turtle standard.
Ce choix de passer par un script turtle.py additionnel avait toutefois trois inconvénients majeurs :
déjà, turtle.py ne venait pas avec les mises à jour et devait donc être ajouté manuellement dans la calculatrice
les fonctions du module turtle n'étaient pas listées au catalogue ; elles devaient donc être connues et saisies manuellement caractère par caractère
comme tout fichier additionnel, turtle.py était de plus inutilisable en mode examen.
Et bien gros changement sur les modèles français Graph 90+E et Graph 35+E II avec la dernière version, le module turtle est désormais directement intégré au système ! Il devient donc à la fois :
disponible immédiatement
décrit au catalogue
utilisable en mode examen
A noter que cette amélioration semble ne concerner que les modèles français. La fx-9750GIII mise à jour ne bénéficie pas de cette amélioration, et probablement pas mieux pour les autres modèles internationaux fx-9860GIII et fx-CG50.
Sur ces modèles il faudra donc continuer à passer par les scripts additionnels que nous te lierons en fin d'article, scripts qui deviendront indisponibles en mode examen.
Ce qui était déjà remarquable avec la réécriture intégrale du module turtle par Casio, c'est la haute conformité au standard que l'on vérifiait aisément en comparant ce que donne le même script sur ordinateur, et on peut en passant comparer avec les plateformes concurrentes. Voici quelques exemples utilisant du code turtle standard. Nous allons juste mettre dans le code quelques protections concernant les fonctions parfois non définies sur certaines plateformes, afin que leur appel n'empêche pas l'affichage du tracé obtenu. Mais nous ne coderons ici rien pour corriger des incompatibilités avec la norme.
try_colormode(1) 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)) try_pencolor([red, green, blue]) for i in range(1, 5): turtle.forward(60) turtle.right(90) turtle.right(10)
defsierp(n, l): if n == 0: for i in range (0, 3): turtle.forward(l) turtle.left(120) if n > 0: sierp(n-1, l/2) turtle.forward(l/2) sierp(n-1, l/2) turtle.backward(l/2) turtle.left(60) turtle.forward(l/2) turtle.right(60) sierp(n-1, l/2) turtle.left(60) turtle.backward(l/2) turtle.right(60)
Comme tu peux le voir, les Graph 90+E et Graph 35+E II comptaient déjà parmi les meilleures solutions sur le critère de la conformité au standard turtle, pas d'écart sur ces exemples contrairement à certaines solutions concurrentes !
Niveau fonctions dont les appels ont ici été protégés pour palier leur absence sur certaines plateformes, en fait il ne manque pas grand chose aux Graph 90+E et Graph 35+E II, juste turtle.colormode().
Nous remarquons en fait que le module turtle désormais intégré est toujours écrit en Python, son code étant lisible en clair en mémoire. Et nous notons surtout qu'il s'agit d'une nouvelle version par rapport à celle sortie au printemps dernier, une mise à jour assez majeure si tu compares toutes les différences ci-dessous :
defdraw_turtle(x,y,a,c): global turtle_buffer definbuffer(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<=383and0<=ypixel<=191): ifnot inbuffer(xpixel,ypixel): turtle_buffer+=[[xpixel,ypixel,casioplot.get_pixel(xpixel,ypixel)]] casioplot.set_pixel(xpixel,ypixel,c)
deferase_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=[[]]
defpen_brush(x,y,turtle_color): global frame_count erase_turtle() xpixel=int(round(x+192)) ypixel=int(round(-y+96)) if writing==Trueand (0<=xpixel<=383and0<=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()
defforward(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()
defhideturtle(): global turtle_visible turtle_visible=False refresh_turtle()
defhome(): global turtle_pos,turtle_angle turtle_pos[0]=turtle_pos[1]=0 turtle_angle=0 refresh_turtle()
defht(): hideturtle()
defisdown(): return writing
defisvisible(): return turtle_visible
defleft(a): right(-a)
deflt(a): right(-a)
defpd(): down()
defpencolor(*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])==3and isinstance(c[0][0],(int,float)) and isinstance(c[0][1],(int,float)) and isinstance(c[0][2],(int,float)) and0<=c[0][0]<=1and0<=c[0][1]<=1and0<=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()
defpendown(): down()
defpensize(n): global pen_size pen_size=n refresh_turtle()
defright(a): global turtle_angle turtle_angle-=a refresh_turtle()
defrt(a): right(a)
defseth(a): setheading(a)
defsetheading(a): global turtle_angle turtle_angle=a refresh_turtle()
defsetpos(x,y): goto(x,y) refresh_turtle()
defsetposition(x,y): setpos(x,y)
defsetx(x): global turtle_pos turtle_pos[0]=x refresh_turtle()
defsety(y): global turtle_pos turtle_pos[1]=y refresh_turtle()
defshape(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()
defshowturtle(): global turtle_visible turtle_visible=True refresh_turtle()
defspeed(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.5or 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")
defst(): showturtle()
deftowards(x,y): if round(x-turtle_pos[0],8)==0and round(y-turtle_pos[1],8)==0: return0 else: return (atan2(y-turtle_pos[1],x-turtle_pos[0])*180/pi)
def_draw_turtle(x,y,a,c): global turtle_buffer definbuffer(x,y): inlist=False for i in range(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<=383and0<=ypixel<=191): ifnot 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(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.clear()
def_pen_brush(x,y,turtle_color): global frame_count _erase_turtle() xpixel=int(round(x+192)) ypixel=int(round(-y+96)) if writing==Trueand (0<=xpixel<=383and0<=ypixel<=191) : colorpixel=(int(turtle_color[0]*255), int(turtle_color[1]*255),int(turtle_color[2]*255))
for point in pen_pixels: casioplot.set_pixel(xpixel+point[0],ypixel+point[1],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()
defforward(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()
defhideturtle(): global turtle_visible turtle_visible=False _refresh_turtle()
defhome(): global turtle_angle goto(0,0) turtle_angle=0 _refresh_turtle()
defht(): hideturtle()
defisdown(): return writing
defisvisible(): return turtle_visible
defleft(a): right(-a)
deflt(a): left(a)
defpd(): down()
defpencolor(*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])==3and isinstance(c[0][0],(int,float)) and isinstance(c[0][1],(int,float)) and isinstance(c[0][2],(int,float)) and0<=c[0][0]<=1and0<=c[0][1]<=1and0<=c[0][2]<=1: turtle_color=list(c[0])
elif len(c)==3and isinstance(c[0],(int,float)) and isinstance(c[1],(int,float)) and isinstance(c[2],(int,float)) and0<=c[0]<=1and0<=c[1]<=1and0<=c[2]<=1: turtle_color=list(c)
else: raise ValueError('error using pencolor : enter a color text or 3 floats between 0 and 1') _refresh_turtle()
defpendown(): down()
defpensize(n=None): global pen_pixels,pen_size penshape=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[1,-1],[-1,1],[-1,-1],[2,0],[0,2],[-2,0],[0,-2],[2,1],[1,2],[-2,1],[-1,2],[2,-1],[1,-2],[-2,-1],[-1,-2]] if n==None: return pen_size elif isinstance(n,(int,float)) and n>=0: pen_size=n if round(n)==0or round(n)==1 : pen_pixels=[[0,0]] elif round(n)==2 : pen_pixels=penshape[0:5] elif round(n)==3 : pen_pixels=penshape[0:9] elif round(n)==4 : pen_pixels=penshape[0:13] elif round(n)==5 : pen_pixels=penshape[0:21] elif round(n)>5 : pen_pixels=penshape[0:21] pen_size=5 print('Userwarning: pensize over 5 automatically set to 5.') else: raise ValueError('Error using function pensize: enter a real between 0 & 5') _refresh_turtle()
defright(a): global turtle_angle if isinstance(a, (int, float)): turtle_angle = _conv_angle(turtle_angle-a) else: raise ValueError('error') _refresh_turtle()
defrt(a): right(a)
defseth(a): setheading(a)
defsetheading(a): global turtle_angle turtle_angle=_conv_angle(a) _refresh_turtle()
defsetpos(x,y): goto(x,y)
defsetposition(x,y): setpos(x,y)
defsetx(x): goto(x,turtle_pos[1])
defsety(y): goto(turtle_pos[0],y)
defshape(name=None): global turtle_name,turtle_data if name==None: return turtle_name elif name in turtleshapes: turtle_name=name turtle_data=turtleshapes[name] else: raise ValueError('available shapes: "classic" or "turtle"') _refresh_turtle()
defshowturtle(): global turtle_visible turtle_visible=True _refresh_turtle()
defspeed(speed=None): global turtle_speed speedwords = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 } if speed==None: return turtle_speed elif isinstance(speed,(int,float)) and (speed<=0.5or speed>=10.5): turtle_speed=0 elif isinstance(speed,(int,float)) and (0.5<speed<10.5): turtle_speed=int(round(speed)) elif isinstance(speed,str) and speed in speedwords: turtle_speed=speedwords[speed] else: raise ValueError("Error using function speed: enter a real between 0 & 10")
defst(): showturtle()
deftowards(x,y): if round(x-turtle_pos[0],8)==0and round(y-turtle_pos[1],8)==0: return0 else: ang=atan2(y-turtle_pos[1],x-turtle_pos[0])*180/pi if ang>=0: return (ang) else: return (360+ang)
Nous avions remarqué un petit écart avec la fonction turtle.write(), cette dernière écrivant le texte fourni dans un rectangle dont la tortue occupe le sommet supérieur gauche, alors que dans le standard c'est le sommet inférieur gauche. Vérifions :
Non finalement pas de changement ici, mais vu en comparaison les énormes écarts que se permettent d'autres plateformes on peut bien passer l'éponge cette fois-ci.
Autre chose que nous avions remarqué, un petit bug au niveau de la fonction turtle.pensize() qui semblait inopérante :
Ici aussi Casio France diffusait depuis la dernière mise à jour un script matplotl.py, une réécriture complète en Python du module de tracés par coordonnées matplotl.pyplot standard.
Ce choix de passer par un script matplotl.py additionnel avait ici encore plusieurs inconvénients majeurs :
matplotl.py ne venait pas avec les mises à jour et devait donc être ajouté manuellement dans la calculatrice
Les fonctions du module matplotl n'étaient pas listées au catalogue ; elles devaient donc être connues et saisies manuellement caractère par caractère
Comme tout fichier additionnel, matplot.py était de plus inutilisable en mode examen.
La calculatrice ne gérant que partiellement les noms de fichiers longs, le fichier de script correspondant avait donc été nommé matplotl.py et non matplotlib.pyplot.py afin de respecter la limitation à 8 caractères, ce qui introduisait donc une incompatibilté avec les scripts conçus pour le standard matplotlib.pyplot. La compatibilité avec des scripts conçus pour d'autres plateformes nécessitait un léger effort, quelques lignes d'importation spécifiques en début de script :
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
Gros changement en conséquence sur les modèles français Graph 90+E et Graph 35+E II avec la dernière version, le module est désormais directement intégré au système et de plus renommé correctement en matplotlib.pyplot ! Il devient donc à la fois :
disponible immédiatement
décrit au catalogue
utilisable en mode examen
directement utilisable avec les scripts matplotlib.pyplot conçus pour d'autres plateformes, même plus besoin de modifier les lignes d'importation
A noter que cette amélioration semble ici encore ne concerner que les modèles français. La fx-9750GIII mise à jour ne bénéficie pas de cette amélioration, et même si nous n'en disposons pas c'est probablement pareil sur les autres modèles internationaux fx-9860GIII et fx-CG50.
Sur ces modèles il faudra donc continuer à passer par les scripts additionnels que nous te lierons en fin d'article, scripts qui seront inutilisables en mode examen.
Pour une réécriture intégrale, observons ici encore la remarquable compatibilité avec le standard matplotlib.pyplot de l'ordinateur, ainsi que ce que donnent les implémentations concurrentes :
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
deff(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()
Comme tu peux le noter, les Graph 90+E et Graph 35+E II comptent ici encore parmi les meilleures solutions du point de vue de la compatibilité avec le standard matplotlib.pyplot, pas d'écart sur ces exemples contrairement à certaines solutions concurrentes !
Le module matplotlib.pyplot intégré est toujours écrit en Python, son code étant lisible en clair en mémoire. Et il s'agit surtout d'une nouvelle version par rapport à celle sortie au printemps dernier, une mise à jour assez majeure selon toutes les différences ci-dessous :
defaxis(*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')
deftext(x,y,txt): global textes if textes==[[]]: textes[0]=[x,y,txt] else: if [x,y,txt] notin textes : textes+=[[x,y,txt]]
defplot(*L,**kwargs): global color_count,win_scaling # if len(L)==2: # L=([list(L[0]),list(L[1])]) defplotpoint(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] notin points : points+=[[x,y,c]] xmin=min(x,xmin) xmax=max(x,xmax) ymin=min(y,ymin) ymax=max(y,ymax)
defplotline(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] notin 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!=Noneandnot 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)==2and 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)==2and 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)==1and 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)==3and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)) and isinstance(L[2],(str)): color=L[2] if (len(color)==2and 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)==3and 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)==2and 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)==2and isinstance(L[0],(list,tuple)) and isinstance(L[1],(str)): color=L[1] if (len(color)==2and 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<=1and 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
defbar(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')
defscatter(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')
defboxplotFR(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
defmediane(l): l=sorted(l) r=len(l) if r%2==0: return (l[r//2]+l[r//2-1])/2 else: return l[r//2]
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")
defboxplot(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 defmediane(l): r=1 if type(l)!=int and type(l)!=float: l=sorted(l) r=len(l) if r%2==0and 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')
defaxis(*L): global fenetre,win_scaling,axis_display if len(L)==1and L[0]=='auto': win_scaling='auto' if L==() or L[0]=='auto': if win_scaling=='auto': for i in [0,2]: if extrem[i]==extrem[i+1]: if extrem[i]==0: fenetre[i:i+2]=[-0.05,0.05] else: fenetre[i:i+2]=[extrem[i]-0.05*abs(extrem[i]),extrem[i]+0.05*abs(extrem[i])] else: fenetre[i:i+2]=[1.05*extrem[i]-0.05*extrem[i+1],1.05*extrem[i+1]-0.05*extrem[i]] 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]] print('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]] print('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' else: raise Exception('function axis() : error using arguments')
deftext(x,y,txt): global textes txt=str(txt) if textes==[[]]: textes[0]=[x,y,txt] else: if [x,y,txt] notin textes : textes+=[[x,y,txt]]
defplot(*L,**kwargs): global color_count,win_scaling defplotpoint(x,y,c): global points,extrem,win_scaling if points==[[]] and lines==[[]]: points[0]=[x,y,c] extrem=[x,x,y,y] else: if [x,y,c] notin points : points+=[[x,y,c]] extrem=[min(x,extrem[0]),max(x,extrem[1]),min(y,extrem[2]),max(y,extrem[3])] if win_scaling=='init': win_scaling='auto'
defplotline(x1,y1,x2,y2,c): global lines,extrem,win_scaling if lines==[[]] and points==[[]]: lines[0]=[x1,y1,x2,y2,c] extrem=[min(x1,x2),max(x1,x2),min(y1,y2),max(y1,y2)] else: if [x1,y1,x2,y2,c] notin lines : lines+=[[x1,y1,x2,y2,c]] extrem=[min(x1,x2,extrem[0]),max(x1,x2,extrem[1]),min(y1,y2,extrem[2]),max(y1,y2,extrem[3])] if win_scaling=='init': win_scaling='auto'
defauto(c): global color_count if (c != Noneand len(c)==2and c[0] in available_colors and c[1] in ['o','.','+','*','-']): c=c[0] if c in [None,'o','.','+','*','-']: color=color_auto[color_count%7] color_count+=1 return color else: return c
deftestcolor(c): if (len(c)==2and c[0] in available_colors and c[1] in ['o','.','+','*','-']) or (c in available_colors+['o','.','+','*','-']) : returnTrue else: raise ValueError('function plot() : unknown color code')
color=kwargs.get('color',None) if color!=Noneandnot color in available_colors: raise ValueError('function plot() : unknown color code') if len(L)==2and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)): plotpoint(L[0],L[1],auto(color)) elif len(L)==2and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)): if (len(L[0])==len(L[1])): c=auto(color) for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],c) else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==1and isinstance(L[0],(list,tuple)): c=auto(color) for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],c) elif len(L)==3and isinstance(L[0],(int,float)) and isinstance(L[1],(int,float)) and isinstance(L[2],(str)): if testcolor(L[2])==True: plotpoint(L[0],L[1],auto(L[2])) elif len(L)==3and isinstance(L[0],(list,tuple)) and isinstance(L[1],(list,tuple)) and isinstance(L[2],(str)): if (len(L[0])==len(L[1])): if testcolor(L[2])==True : c=auto(L[2]) for i in range(len(L[0])-1): plotline(L[0][i],L[1][i],L[0][i+1],L[1][i+1],c) else: raise ValueError('function plot() : x and y must have same dimension') elif len(L)==2and isinstance(L[0],(list,tuple)) and isinstance(L[1],(str)): if testcolor(L[1])==True : c=auto(L[1]) for i in range(len(L[0])-1): plotline(i,L[0][i],i+1,L[0][i+1],c) else: raise Exception('function plot() : error using arguments') defshow(): global fenetre, limits, points, lines, textes, extrem, win_scaling, axis_display, color_count, color_grid, grid_display defRGB(c): colornames={"black":(0,0,0),"k":(0,0,0),"blue":(0,0,255),"b":(0,0,255),"green":(0,255,0),"g":(0,255,0),"red":(255,0,0),"r":(255,0,0),"cyan":(0,255,255),"c":(0,255,255),"yellow":(255,255,0),"y":(255,255,0),"magenta":(255,0,255),"m":(255,0,255),"white":(255,255,255),"w":(255,255,255),"orange":(255,166,0),"purple":(128,0,128),"brown":(166,42,42),"pink":(255,192,202),"grey":(215,215,215)} if c in colornames: return colornames[c] else: raise ValueError("invalid color code")
defprintable(X): global limits return(limits[0]<=X[0]<=limits[2] and limits[3]<=X[1]<=limits[1]) defechelle(a,b): k=0 e=abs(b-a) while e>=10 : e/=10 k+=1 while e<1 : e*=10 k-=1 return k defpas(a,b): pas=10**echelle(a,b) while (abs(b-a))//pas<4: pas/=2 return pas defconverttopixel(X): global fenetre,limits ax=(limits[2]-limits[0])/(fenetre[1]-fenetre[0]) bx=limits[0]-ax*fenetre[0] xpixel=round(ax*X[0]+bx) ay=(limits[3]-limits[1])/(fenetre[3]-fenetre[2]) by=limits[1]-ay*fenetre[2] ypixel=round(ay*X[1]+by) return [xpixel,ypixel] color_count=0 plt.clear_screen() if win_scaling=='auto': for i in [0,2]: if extrem[i]==extrem[i+1]: if extrem[i]==0: fenetre[i:i+2]=[-0.05,0.05] else: fenetre[i:i+2]=[extrem[i]-0.05*abs(extrem[i]),extrem[i]+0.05*abs(extrem[i])] else: fenetre[i:i+2]=[1.05*extrem[i]-0.05*extrem[i+1],1.05*extrem[i+1]-0.05*extrem[i]] 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]]) pasx=pas(fenetreb[0],fenetreb[1]) pasy=pas(fenetreb[2],fenetreb[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): pix=converttopixel((i+1,fenetre[2])) plt.set_pixel(pix[0],pix[1]+1,RGB("k")) plt.set_pixel(pix[0],pix[1]+2,RGB("k")) plt.set_pixel(pix[0],pix[1]+3,RGB("k")) plt.draw_string(pix[0],pix[1]+13,str(i+1),[0,0,0],"small") else : for i in range(-10,10): x=gx+i*pasx pix=converttopixel((x,fenetre[2])) if printable(pix): plt.set_pixel(pix[0],pix[1]+1,RGB("k")) plt.set_pixel(pix[0],pix[1]+2,RGB("k")) plt.set_pixel(pix[0],pix[1]+3,RGB("k")) plt.set_pixel(pix[0],pix[1]+1,(1,1,1)) if grid_display=='on': for z in range(1,165): if pix[0]!=limits[0]: plt.set_pixel(pix[0],pix[1]-z,RGB(color_grid)) plt.draw_string(pix[0],pix[1]+13,'{:.4g}'.format(x),[0,0,0],"small") for j in range(-10,10): y=gy+j*pasy pix=converttopixel((fenetre[0],y)) if printable(pix): plt.set_pixel(pix[0]-1,pix[1],RGB("k")) plt.set_pixel(pix[0]-2,pix[1],RGB("k")) plt.set_pixel(pix[0]-3,pix[1],RGB("k")) if grid_display=='on': for z in range(1,340): if pix[1]!=limits[1]: plt.set_pixel(pix[0]+z,pix[1],RGB(color_grid)) plt.draw_string(pix[0]-40,pix[1],'{:.4g}'.format(y),[0,0,0],"small") if points!=[[]]: if points[0]==[]: del points[0] for i in range(len(points)): pix=converttopixel((points[i][0],points[i][1])) if printable(pix) and points[i][2]!=None: for j in range(-2,3): plt.set_pixel(pix[0]+j,pix[1],RGB(points[i][2])) plt.set_pixel(pix[0],pix[1]+j,RGB(points[i][2])) if textes!=[[]]: if textes[0]==[]: del textes[0] for i in range(len(textes)): pix=converttopixel((textes[i][0],textes[i][1])) if printable(pix): plt.draw_string(pix[0],pix[1],textes[i][2],[0,0,0],"small") if lines!=[[]]: if lines[0]==[]: del lines[0] for i in range(len(lines)): pixels=[converttopixel((lines[i][j],lines[i][j+1])) for j in [0,2]] deltax=abs(pixels[1][0]-pixels[0][0]) deltay=abs(pixels[1][1]-pixels[0][1]) if deltax<=1and deltay<=1: if printable((pixels[0][0],pixels[0][1])): plt.set_pixel(pixels[0][0],pixels[0][1],RGB(lines[i][4])) plt.set_pixel(pixels[1][0],pixels[1][1],RGB(lines[i][4])) else: if deltax>=deltay: j=0 else: j=1 m=(pixels[1][1-j]-pixels[0][1-j])/(pixels[1][j]-pixels[0][j]) p=pixels[0][1-j]-m*pixels[0][j] pix_extrem=(max(limits[0],min(pixels[0][0],pixels[1][0])),min(limits[2],max(pixels[0][0],pixels[1][0])),max(limits[3],min(pixels[0][1],pixels[1][1])),min(limits[1],max(pixels[0][1],pixels[1][1]))) if pix_extrem[2*j]<=limits[2-j] and pix_extrem[2*j+1]>=limits[-j]: pix=[0,0] for pix[j] in range(pix_extrem[2*j],pix_extrem[2*j+1]+1): pix[1-j]=round(m*pix[j]+p) if printable(pix): plt.set_pixel(pix[0],pix[1],RGB(lines[i][4])) axis([limits[0]-50,limits[2],limits[1]+50,limits[3]]) axis("off") plt.show_screen() points=[[]] lines=[[]] textes=[[]] extrem=[0,1,0,1] fenetre=[0,1,0,1] axis_display='on' win_scaling='init' color_count=0 grid_display='off'
defbar(val,eff,width=0.8): global color_count if isinstance(val,(tuple)): val=list(val) if isinstance(eff,(tuple)): eff=list(eff) if isinstance(val,(int,float)): val=[val] if isinstance(eff,(int,float)): eff=[eff] if isinstance(val,(list)) and isinstance(eff,(list)): if len(val)==len(eff): for i in range(len(val)): plot([val[i]-width/2,val[i]-width/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]+width/2,val[i]+width/2],[0,eff[i]],color_auto[color_count%7]) plot([val[i]-width/2,val[i]+width/2],[eff[i],eff[i]],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function bar() : lists must have same dimension') else: raise ValueError('function bar() : error using arguments')
defscatter(xlist,ylist): global color_count if isinstance(xlist,(tuple)): xlist=list(xlist) if isinstance(ylist,(tuple)): ylist=list(ylist) if isinstance(xlist,(int,float)): xlist=[xlist] if isinstance(ylist,(int,float)): ylist=[ylist] if isinstance(xlist,(list)) and isinstance(ylist,(list)): 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 lists must have same dimension') else: raise ValueError('function scatter() : error using arguments')
defhist(x,bins=10,**kwargs): global color_count hist_type=kwargs.get('hist_type','std') if hist_type notin ['fr','std']: raise ValueError('function hist() : hist_type must be std or fr') if isinstance(x,(tuple,list)): x=sorted(list(x)) if isinstance(bins,(tuple)): bins=list(bins) if isinstance(x,(int,float)): x=[x] if isinstance(bins,(int)) and bins>=1: if x[-1]!=x[0]: bins=[round(x[0]+k*(x[-1]-x[0])/bins,8) for k in range(bins+1)] else : bins=[round(x[0]-0.5+k/bins,8) for k in range(bins+1)] if isinstance(bins,(list)) and bins!=[]: bins=sorted(bins) qt=[] for i in range(len(bins)-1): if i==len(bins)-2: eff=len([val for val in x if bins[i]<=val<=bins[i+1]]) else: eff=len([val for val in x if bins[i]<=val<bins[i+1]]) if hist_type=='fr': if abs(bins[i+1]-bins[i])>1e-8: eff=eff/(bins[i+1]-bins[i]) else : raise ValueError('function hist(,hist_type=''fr'') : bins cannot contain 2 identical values') qt+=[eff] plot([bins[i],bins[i],bins[i+1],bins[i+1]],[0,eff,eff,0],color_auto[color_count%7]) color_count+=1 else: raise ValueError('function hist() : error using arguments') return qt,bins
defboxplot(L,**kwargs): L=list(L) global fenetre,nbre_boite,color_count,axis_display,win_scaling boxplot_type=kwargs.get('boxplot_type','std') if boxplot_type notin ['fr','std']: raise ValueError('function boxplot() : boxplot_type must be std or fr') defmediane(l,p): if p%2==0: return (l[p//2]+l[p//2-1])/2 else: return l[p//2] defquantiles(l,p,r): if boxplot_type=='fr': if p%r==0: return (l[p//r-1],l[((r-1)*p)//r-1]) else: return (l[p//r],l[((r-1)*p)//r]) if boxplot_type=='std': defpercentile(N, q): k = (len(N)-1) * q f = int(k) c = int(k)+1 if f == k: return N[int(k)] d0 = N[f] * (c-k) d1 = N[c] * (k-f) return d0+d1 return (percentile(l,0.25),percentile(l,0.75)) whis=kwargs.get('whis',1.5) if whis<0: whis=0 axis_display='boxplot' n=len(L) if isinstance(L[0],(int,float)): n=1 Max,Min=max(L),min(L) if Max==Min: ampl=1 else: ampl=Max-Min fenetre=[0,2,Min-ampl/20,Max+ampl/20] else: Max,Min=max([max(L[i]) for i in range(len(L))]),min([min(L[i]) for i in range(len(L))]) if Min==Max: ampl=1 else: ampl=Max-Min fenetre=[0,len(L)+1,Min-ampl/20,Max+ampl/20] nbre_boite,largeur=n,0.3/n win_scaling='fixed' for i in range(n): if n==1: if isinstance(L[0],(int,float)): K=L else: K=L[0] else : K=L[i] if isinstance(K,(int,float)): plot([i+1-largeur,i+1+largeur],[K,K],'r') elif isinstance(K[0],(int,float)): K,p=sorted(K),len(K) med=mediane(K,p) Q1,Q3=quantiles(K,p,4) if boxplot_type=='std': down,up=0,p-1 while Q1-whis*(Q3-Q1)>K[down]: down+=1 while Q3+whis*(Q3-Q1)<K[up]: up-=1 left_whis,right_whis=K[down],K[up] if Q1<K[down]: left_whis=Q1 if Q3>K[up]: right_whis=Q3 if boxplot_type=='fr': D1,D9=quantiles(K,p,10) down=K.index(D1) up=K.index(D9) left_whis,right_whis=K[down],K[up] while(up<p-1and K[up]==K[up+1]): up=up+1 right_whis=K[up] 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,left_whis],'k') plot([i+1,i+1],[Q3,right_whis],'k') plot([i+1-largeur/2,i+1+largeur/2],[left_whis,left_whis],'k') plot([i+1-largeur/2,i+1+largeur/2],[right_whis,right_whis],'k') if down>0or up<p-1: from math import pi,cos,sin Z=[i for i in range(down)]+[j for j in range(up+1,p)] for t in Z: 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') plot([i+1-largeur,i+1+largeur],[med,med],'r') else: raise ValueError('wrong type of argument')
defresol(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 abs(dx)<0.00001: dx=0 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) for i in range(15): plot((a-(i/15)*L/2,a-(i/15)*L/2),(b,b+(15-i)/15*c*l),headcolor) plot((a+i/15*L/2,a+i/15*L/2),(b,b+(15-i)/15*c*l),headcolor) 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) for i in range(15): plot((a,a+(15-i)/15*c*l),(b-i/15*L/2,b-i/15*L/2),headcolor) plot((a,a+(15-i)/15*c*l),(b+i/15*L/2,b+i/15*L/2),headcolor) 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 (a-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),color) plot((a,X),(b,Y),headcolor) listeX=[] listeY=[] if abs(X-T[0])<0.000001: for i in range(15): listeX+=[T[0]+i*(a-T[0])/15]+[T[0]] listeY+=[-listeX[2*i]/m+k]+[-T[0]/m+k+i*(Y+T[0]/m-k)/15] else: M=(Y+T[0]/m-k)/(X-T[0]) P=Y-M*X for i in range(15): listeX+=[T[0]+i*(a-T[0])/15]+[T[0]+i*(X-T[0])/15] listeY+=[-listeX[2*i]/m+k]+[listeX[2*i+1]*M+P] plot(listeX,listeY,headcolor) listeX=[] listeY=[] if abs(X-T[1])<0.000001: for i in range(15): listeX+=[T[1]+i*(a-T[1])/15]+[T[1]] listeY+=[-listeX[2*i]/m+k]+[-T[1]/m+k+i*(Y+T[1]/m-k)/15] else: M=(Y+T[1]/m-k)/(X-T[1]) P=Y-M*X for i in range(15): listeX+=[T[1]+i*(a-T[1])/15]+[T[1]+i*(X-T[1])/15] listeY+=[-listeX[2*i]/m+k]+[listeX[2*i+1]*M+P] plot(listeX,listeY,headcolor)
defgrid(*a,**kwargs): global color_grid,grid_display color=kwargs.get('color',None) if a==(): affichage=a else: affichage=a[0] if color!=None: color_grid=color affichage='on' if color notin available_colors: color_grid='grey' if affichage==(): if grid_display=='on': grid_display='off' else: grid_display='on' elif affichage=='on'or affichage=='True'or affichage==Trueor affichage=='true': grid_display='on' elif affichage=='off'or affichage=='False'or affichage==Falseor affichage=='false': grid_display='off' else: raise ValueError('string must be one of : "on","off","True",or "False"')
Donc quelles nouveautés dans tout ça ? Revenons sur le tracé de diagrammes en boîte à l'aide de la fonction boxplot() :
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
Val=[1,2,2,11,8,9,15,18,20,9,2,5,6,7,8,9,5,9]
boxplot(Val) show()
Petit problème concernant donc la fonction boxplot() standard de matplotlib.pyplot, les diagrammes en boîte qu'elle trace ne sont pas conformes à ceux enseignés au lycée français. Afin d'y remédier, Casio avait ajouté avec sa propre fonction boxplotFR(). On pouvait toutefois regretter un écart par rapport au standard.
Dans le nouveau matplotlib.pyplot intégré, Casio fait un effort sur ce dernier point. La fonction boxplotFR() est supprimée, remplacée par un paramètre nommé boxplot_type pouvant être passé à la fonction boxplot(), pouvant prendre les valeurs "std" ou "fr". L'appel équivalent à boxplotFR(l) est donc boxplot(l, boxplot_type="fr") avec la nouvelle version.
Nous avons donc vu plus haut le diagramme en barres à l'aide de la fonction bar(). Et bien grosse nouveauté du matplotlib.pyplot intégré, nous avons droit à une nouvelle fonction cette fois-ci pour les histogrammes, hist() :
l = [] for i in range(len(x)): for j in range(y[i]): l.append(x[i])
hist(l) show()
Si tu regardes bien, tu noteras que la fonction hist() de matplotlib.pyplot ne respecte pas la définition française des histogrammes, à savoir que c'est l'aire des bandes qui indique la valeur.
Et bien nouvel effort remarquable de Casio pour concilier le standard matplotlib.pyplot et l'enseignement français, il te suffira ici encore de passer le paramètre nommé hist_type="fr" pour obtenir le bon histogramme.
Autre ajout, la fonction grid() pour tracer un quadrillage :
Casio nous offrait donc déjà le tracé de pointes de flèches de vecteurs le plus proche du standard.
Toutefois, Casio a quand même souhaité améliorer la chose. Avec le nouveau matplotlib.pyplot intégré de la Graph 90+E, ces pointes font l'objet d'un remplissage.
Ce n'est pas le plus embêtant, nous allons y venir, mais cet ajout est assez gourmand en temps d'exécution. Le tracé de notre exemple de vecteur nécessite dans les 2,5s avec l'ancien matplotl.py additionnel, et désormais 7s avec le nouveau matplotlib.pyplot intégré.
Nous avions déjà noté plusieurs bugs concernant la fonction arrow() :
pointe de flèche tracée de la mauvaise couleur dans certains cas
pointe de flèche tracée à l'envers dans certains cas
La nouvelle version matplotlib.pyplot intégrée corrige ces problèmes !
Quelque chose de bien embêtant par contre, et que ce changement sur arrow() met en évidence, c'est que malgré les 1 Mio de heap (tas) de la Graph 90+E nous ne sommes pas loin d'une erreur de mémoire à l'exécution.
Réduisons progressivement le pas angulaire dans notre appel de rotarrow(), 15, 14, 13... 12 pour le tracé d'un champ radial de
36012=30
vecteurs marche encore. Et puis soudainement avec 11 pour le tracé d'un champ de 32 vecteurs, ça ne marche plus avec le nouveau matplotlib.pyplot intégré, alors que cela fonctionnait parfaitement avec l'ancien matplotl.py additionnel.
Un champ d'une 30aine de vecteurs, ce n'est pas inimaginable en Physique-Chimie, c'est bien embêtant.
Et ce n'est pas juste une légère variation de la limite, avec l'ancien matplotl.py additionnel aucun problème pour 180 vecteurs.
Mais que se passe-t-il ?
Selon notre analyse rapide du code Python de matplotlib.pyplot, tout vient du fait que les tracés sont différés, uniquement effectués à l'appel de show(). Tous nos appels rajoutent à des listes globales de primitives à tracer (points, lines, textes...). Et avec le nouveau matplotlib.pyplot intégré viennent plein d'éléments supplémentaires dans la liste lines afin de remplir les différentes pointes de flèches de vecteurs.
Or comme matplotlib.pyplot est écrit en Python, ces listes globales sont des objets Python, et par conséquent comme nous l'avons déjà vu maintes fois ils sont très gourmands en mémoire.
Casio gagnerait sans doute soit à optimiser ce stockage global, soit à passer à une implémentation native de matplotlib.pyplot maintenant que c'est de toutes façons intégré au système. Ce sera certes dommage pour nous de ne plus avoir accès au code source, mais si cela peut arranger les utilisateurs c'est l'essentiel.
if pf >= 0: curline=0 _p = print defprint(*ls): global curline st="" for s in ls: ifnot(isinstance(s,str)): s=str(s) st=st+s stlines=1 if sh_inf[1]: stlines += sh_inf[2]*int(len(st)/sh_inf[1]) if curline+stlines>=sh_inf[0]: input("Input to continue:") curline=0 _p(st) curline+=stlines
defsstr(obj): try: s=obj.__name__ except: s=str(obj) a=s.find("'") b=s.rfind("'") if a>=0and b!=a: s=s[a+1:b] return s
defisExplorable(obj): if str(obj).startswith("<module"): returnFalse l = () try: l = dir(obj) except: pass return len(l)
defexplmodr(pitm, pitm_name_l=[], pitm_str_l=[], pitm_val_l=[], reset=True): global curline, found pitm_name=sstr(pitm) if(reset): curline=0 found = [] pitm_name_l=[pitm_name] pitm_str_l=[str(pitm)] pitm_val_l=[pitm] hd="."*(len(pitm_name_l)-1) c = 0 l = sorted(dir(pitm)) for i in range(len(l)): l[i] = (l[i], getattr(pitm, l[i]), str(l[i])) try: ifnot isinstanceof(pitm, str): for i in range(len(pitm)): l.append((pitm_name+'['+str(i)+']',pitm[i],str(pitm[i]))) except: pass for itm in l: isFound = itm[0] in found c += not isFound isUnsafe = '.'.join(pitm_name_l + [itm[0]]) in unsafe or itm[0] in unsafe try: if isUnsafe: raise Exception print(hd+itm[0]+"="+str(itm[1])) except: print(hd+itm[0]) ifnot isFound: found.append(itm[0]) ifnot isUnsafe and isExplorable(itm[1]) and itm[1] notin pitm_val_l and itm[2] notin pitm_str_l: pitm_name_l2, pitm_val_l2, pitm_str_l2 = pitm_name_l.copy(), pitm_val_l.copy(), pitm_str_l.copy() pitm_name_l2.append(itm[0]) pitm_val_l2.append(itm[1]) pitm_str_l2.append(itm[2]) c += explmodr(itm[1], pitm_name_l2, pitm_str_l2, pitm_val_l2, False) return c
defexplmod(s): global found module = __import__(s) found = [] return explmodr(module)
#return get_pixel and set_pixel functions for the platform gp_prime = lambda x, y: GETPIX_P(x, y) sp_prime = lambda x, y, c: PIXON_P(x, y, c) defget_pixel_functions(pf): gp, sp = lambda: None, lambda: None if pf == 0: # NumWorks import kandinsky gp, sp = kandinsky.get_pixel, kandinsky.set_pixel elif pf == 1: # Graph 90/35+E II import casioplot gp, sp = casioplot.get_pixel, casioplot.set_pixel elif pf == 2: # 83P/84+ CE import ti_graphics gp, sp = ti_graphics.getPixel, ti_graphics.setPixel elif pf == 3: # Nspire CX II pass elif pf == 4: # HP Prime import hpprime sp = hpprime.pixon elif pf == 6: # Nspire: Ndless MicroPython from nsp import Texture canvas = Texture(320, 240, 0) gp, sp = canvas.getPx, canvas.setPx elif pf == 7or pf == 9: # Nspire/NumWorks: KhiCAS-MicroPython import graphic gp, sp = graphic.get_pixel, graphic.set_pixel elif pf == 13: # HP Prime gp, sp = gp_prime, sp_prime return gp, sp
#returns platform shell infos : visible lines, visible columns, if larger strings are displayed on several lines or not defshell_infos(pf): #NW small: [00] 12.5x30 -> 16 x 42 #HP small: [03] 11.5x39 -> 15.5 x 45 [12] 14 x39 -> 18.5 x 45 #HP big : [03] 11.5x39 -> 09 x 35 [12] 14 x39 -> 11 x 35 # uPy uPy # G352 CPy uPy KhiCAS---------------> CAS # NW G90 CE CX2 HP GXX NS NS NS NW NW G90 G352HP l_vlines = (12, 07, 11, 11, 12, 09, 29, 11, 11, 11, 11, 09, 07, 14) l_vcols = (30, 21, 32, 00, 39, 32, 53, 32, 32, 29, 29, 30, 19, 39) b_vcr = 0b1111100 if pf >= 0: return l_vlines[pf], l_vcols[pf], b_vcr // 2**pf % 2 else: return max(l_vlines), max(l_vcols), 1
L'appel explmod('nom_module') explore le module en question et en compte les différents éléments internes, en évitant les doublons. Nous noterons en rouge les modules inaccessibles en mode examen :
Un net progrès même si cela ne renverse pas la tendance, la solution Python de Casio est désormais intégralement disponible en mode examen !
Casio n'a sans doute pas la solution Python la plus riche, mais on peut quand même noter un soin méticuleux à rester aussi proche que possible du standard et donc faciliter la vie des élèves et des enseignants en ne leur rajoutant pas de travail, préoccupation que l'on ne trouve pas chez tout-le-monde.
Nous abordons maintenant l'autre grosse nouveauté, et la raison pour laquelle la mise à jour de Casio est ici globale, concernant également des modèles d'avant-dernière génération. Les changements dont il est question ici ne concernent pas les modèles spécifiques à la France, uniquement les fx-9860GII, fx-9750GIII, fx-9860GIII, fx-CG10, fx-CG20 et fx-CG50.
Sur ces modèles, lorsque l'on demande l'accès au mode examen, l'écran confirmant le succès de l'opération affiche désormais le numéro de version du système de la calculatrice. Particulièrement utile hors de France dans les pays où ce sont les surveillants qui activent le mode examen des candidats, ou encore pour les examens qui exigent d'installer la dernière version système, une version système récente ou encore une version système spécifique. Cela permet de s'assurer que le candidat n'utilise pas une version interdite, plus ancienne ou même obsolète qui présenterait des failles dans le mode examen.
Mais bien évidemment, lorsque ce sont les candidats qui activent le mode examen en début d'épreuve, impossible d'avoir les yeux sur tous les écrans.
Casio avait également prévu quelque chose pour ça, un écran d'information sur le mode examen accessible via
ALPHA
(-)
, non fonctionnel sur les modèles français. Cet écran indiquait déjà le temps écoulé depuis l'activation du mode examen, permettant ainsi de repérer certaines tentatives de fraude. Notamment les candidats qui auraient activé le mode examen avant l'épreuve et donc potentiellement réinjecté toutes les données de leur choix, et d'une façon ou d'une autre trompé le surveillant sur l'état de la calculatrice en arrivant à leur épreuve (en dissimulant le clignotement de la diode et faisant mine d'appuyer sur les touches ou peu importe).
Et bien nouveauté, cet écran d'information indique dorénavement lui aussi la version de système d'exploitation utilisé. Le surveillant peut donc désormais tout vérifier à n'importe quel moment de l'épreuve en seulement 2 touches.
Mais ce n'est pas tout. Historiquement chez Casio nous avions 2 modes examen aux comportements différents répartis sur différents modèles :
mode examen français (Graph 35+E II, Graph 75+E, Graph 90+E)
mode examen international (fx-9860GII, fx-9750GIII, fx-9860GIII, fx-CG10, fx-CG20, fx-CG50)
Avec la mise à jour 3.30, Casio avait rajouté un 2ème mode examen sur la fx-CG50(mais pas sur la Graph 90+E), portant donc le nombre total de modes examens différents à 3. Le mode examen historique de la fx-CG50 était renommé "mode examen 1", et le nouveau "mode examen 2".
mode examen français (Graph 35+E II, Graph 75+E, Graph 90+E)
mode examen 2 (fx-CG50) qui avait l'avantage d'autoriser l'usage de l'appli additionnelle officielle Graphe 3D
Avec les dernières mises à jour traitées aujourd'hui, c'est un festival :
2 nouveaux modes examen sont rajoutés, portant le total à 5 modes examen différents :
un pour les Pays-Bas qui a la particularité d'interdire le calcul exact sur les irrationnels
un pour le Texas qui a la particularité d'interdire les représentations graphiques d'inéquations, et oui Casio va chasser sur les terres de TI
un même modèle peut désormais gérer jusqu'à un maximum de 4 modes examen différents
sur les modèles qui proposent plusieurs modes examens, le mode examen international historique ou mode examen 1 sur la fx-CG50 est renommé en tant que mode examen pour le Baccalauréat International
le mode examen 2 de la fx-CG50 est renommé en tant que mode examen pour le Royaume-Uni
Voici le détail des modes examens présents sur chaque modèle après la dernière mise à jour :
Graph 35+E II Graph 75+E Graph 90+E
fx-9860G AU+ fx-9860GIIs fx-9860GIII Graph 75/95
fx-9750GIII
fx-9860GII fx-CG10/20
fx-CG50
France
✓
Baccalauréat international
✓
✓
✓
✓
Pays-Bas
✓
✓
Royaume-Uni
✓
Texas
✓
✓
Total
1
1
2
2
4
Sur les modèles qui offrent plusieurs modes examens les combinaisons d'activation sont différentes. Dans ce cas le type de mode examen invoqué est désormais précisé à l'écran de confirmation.
Une deuxième confirmation est de plus demandée dans le cas où le mode examen invoqué ne convient pas au Baccalauréat International.
Une fois le mode examen activé, il reste quand même identifiable à tout moment par le drapeau clignotant en haut à droite de l'écran, ainsi que sur les modèles couleur par la bordure de l'écran qui utilise une couleur différente.
Voici ci-dessous résumé en un seul coup d'œil tout ce qui concerne les désormais 5 modes examens de Casio :
Même si c'est moins essentiel ici, terminons en regardant les modifications apportées aux menus et messages de l'interface, habitude que nous avons prise pour découvrir les nouveautés puisque Casio ne publie pas de changelog détaillé.
Sur Graph 90+E et fx-CG50, lorsque l'on réalise un backup de la calculatrice dans l'application Système, nous avons un message d'alerte contre l'écrasement si l'opération a déjà été réalisée. En français sa formulation avait changé lors de la mise à jour 3.20. Avec la mise à jour 3.12, les fx-CG10 et fx-CG20 passent à leur tour à la nouvelle formulation, rattrapant leur retard.
Autre rattrapage, en Italien la formulation "Elemento aggiuntivo" pour les applications additionnelles dans les applications Mémoire et Système avait été remplacée par "Add-In" sur Graph 90+E et fx-CG50 lors de la mise à jour 3.30, ce qui évitait d'avoir à l'abréger à toutes les sauces dans les différents messages et menus. Avec la mise à jour 3.12, les fx-CG10 et fx-CG20 profitent elles aussi désormais de cette nouvelle formulation.
De façon similaire, sur les Graph 90+E et fx-CG50 dès la mise à jour 3.30, une abrévation isolée avait été supprimée dans l'aide en ligne à l'activation du mode examen. Avec la mise à jour 3.12, même changement dorénavant sur les fx-CG10 et fx-CG20.
Toujours dans l'aide en ligne au mode examen mais cette fois-ci en italien, la dernière mise à jour passe les mentions de restrictions concernant la mémoire et les programmes au pluriel.
Petit bug d'interface, lorsque dans l'application Système on choisissait de supprimer les applications additionnelles, dans toutes les langes le message d'avertissement mentionnait en anglais un MAIN MENU. En effet c'était un héritage lors de l'adaptation pour l'écran couleur du système Casio Graph monochrome en 2012, le titre du menu principal n'étant pas traduit sur les modèles monochromes. Les Graph 90+E et fx-CG50 avaient enfin bénéficié d'une correction pertinente de ce message pour la mise à jour 3.40, et avec la mise à jour 3.12 les fx-CG10 et fx-CG20 en bénéficient à leur tour.
Toujours sur ce même message, les fx-CG10 et fx-CG20 mentionnaient en anglais une application SYSTEM, héritage là encore des modèles monochromes où les noms d'applications ne sont pas traduits. Si on peut certes deviner l'application dont il est question dans la plupart des langues, c'était moins évident en Italien où l'application Système s'appelle Set-Up. Quoiqu'il en soit avec la mise à jour 3.12 le message est désormais correct dans toutes les langues.
Casio fait visiblement attention au moindre petit détail d'intuitivité.
Une très belle mise à jour. La solution Python de Casio est maintenant intégralement disponible en mode examen, le constructeur semble être fort à l'écoute de sa communauté d'utilisateurs et avoir traité la moindre des critiques bienveillantes formulées lors de notre annonce de la version précédente.
Nous louons le soin méticuleux que Casio semble apporter au respect d'un standard Python préexistant avec les modules de tracé par coordonnées matplotlib.pyplot et tracé relatif turtle, évitant de réinventer la roue, et épargnant donc double travail aux élèves et enseignants ! Un exemple à suivre !
Même si cela ne concerne pas la France pour le moment, nous sommes heureux de voir que les choses commencent à bouger niveau mode examen, que Casio a enfin accepté l'idée d'avoir plusieurs modes examens plutôt qu'un unique mode examen avec la somme des restrictions réclamées par chaque institution ou pays concerné. Le mode examen de Casio a en effet le défaut (du point de vue utilisateur en tous cas) d'être le plus restrictif tous constructeurs confondus, allant même jusqu'à bloquer ses propres applications additionnelles officielles alors que de telles applications ou fonctionnalités équivalentes restent parfaitement disponibles chez les modes examens concurrents. Nous apprécierions donc si le mode examen français de Casio pouvait également être affiné à son tour pour mieux coller aux seuls interdits réclamés par la réglementation (infos personnelles préchargées), autorisant donc l'usage des applications additionnelles officielles (Conversions sur Graph 90E+, Graphe 3D, Physium, ProbSim, Géométrie), voir même d'applications additionnelles tierces comme KhiCAS.
Les logiciels Casio Manager/Subscription sont d'excellents émulateurs disponibles dans différentes éditions couvrant l'intégralité des derniers modèles de la marque : fx-92+ Spéciale Collège, Graph 35+E II, Graph 90+E et fx-CP400+E.
D'une conception méticuleuse, ils permettent aux enseignants :
de copier des ressources pour concevoir des documents (captures d'écran, séquences de touches...)
de guider collectivement une classe en vidéoprojection, dans sa recherche du problème du jour
Toutefois ces logiciels ne sont normalement pas gratuits. En théorie, pour pouvoir les utiliser au-delà d'une période d'essai de 90 jours, l'enseignant doit acheter un numéro de licence pour chacune des éditions qu'il souhaitait utiliser. En pratique pour la France, les numéros de licence sont généreusement fournis gratuitement aux enseignants par Casio sur simple demande.
Mais il n'empêche que ces licences ne sont pas permanentes, expirant après 1 ou 3 ans selon le prix (1 an pour celles offertes par Casio France), et sont alors à renouveler, ce qui nécessite donc de faire les démarches à temps.
Au-delà de ça, le plus embêtant dans le contexte scolaire est qu'une fois activées, ces licences sont liées à la machine alors utilisée lors de l'activation, et ne peuvent plus resservir à débloquer un émulateur Casio Manager/Subscription sur une autre machine. Or les imprévus ne sont pas rares pour les enseignants utilisant les ordinateurs de l'établissement :
changement de salle exceptionnel ou définitif
panne/vol/remplacement de l'ordinateur de la salle de classe
Sans compter que l'utilisation nécessite l'installation du logiciel et donc des droits proches de l'administrateur, ce qui est rarement le cas.
Et les enseignants apportant et utilisant leur ordinateur portable personnel ne sont pas non plus à l'abri de ces derniers incidents.
Pour la rentrée 2019, Casio France nous apportait une toute nouvelle solution avec des émulateurs sur clé USB pour le confort des enseignants et par conséquent celui des élèves !
La solution concernait les fx-92+ Spéciale Collège, Graph 35+E II et Graph 90+E.
Plus besoin de s'embêter à gérer des numéros de licence, plus besoin d'installation, il suffit juste de connecter la clé USB à l'ordinateur pour pouvoir de suite vidéoprojeter !
Pour cette rentrée 2020, Casio France nous sort une toute nouvelle clé USB d'émulation.
Première chose qui saute aux yeux, une refonte totale du design, digne d'un vaisseau de Star Trek ! Fini l'embout qui était bien souvent une des premières choses que l'on perdait, la clé désormais monolithique s'ouvre d'une simple pression et se referme automatiquement dès que retirée de l'ordinateur !
La nouvelle clé annonce donc une capacité brute de 8 Go. Ceux qui ont déjà vérifié savent qu'entre l'astuce commerciale d'entretenir la confusion entre les unités Go(109= 1000000000 octets) et Gio(230= 1073741824 octets) pour pouvoir annoncer ce qui arrange et l'espace réservé par le formatage du système de fichiers, en pratique on trouve toujours nettement moins. Par exemple, la clé de l'année dernière n'offrait que 7,5 Go de capacité réelle. Et bien bonne nouvelle, la clé USB de cette rentrée 2020 passe à 7,7 Go de capacité réelle, de quoi stocker encore plus de scripts Python !
Enfin bien évidemment, la nouvelle clé vient directement préchargée des dernières versions des émulateurs avec l'ensemble des derniers ajouts Python dont le module de tracé par pixels casioplot, aucun besoin donc immédiat de la mettre à jour :
l'émulateur Graph 90+E passe de la version 3.25 à la version 3.40
l'émulateur Graph 35+E II passe de la version 3.10 à la version 3.30
En prime les émulateurs viennent même préchargés des modules Python officiels optionnels :
matplot, module de tracé par coordonnées, compatible avec le standard matplotl.pyplot
turtle, module de tracé à la tortue, compatible avec le standard du même nom
Si tu ne l'as toujours pas fait, nous te remettons ci-dessous de quoi mettre ton ancienne clé USB à jour.
Attention, ces émulateurs utilisent EasyGuard, une protection contre la copie.
Ils ne fonctionneront que si ils détectent la présence d'une clé USB d'émulation officielle de Casio, vérifiant dans le dossier racine la conformité d'un fichier de signature par rapport au numéro de série de la clé en question.
Avec le nombre d'événements annulés cette année, tu risques ne ne pas avoir beaucoup d'occasions de récupérer cette clé USB d'émulation...
Et bien réjouis-toi car nous allons t'en faire gagner très prochainement tout un stock à notre concours de rentrée !
Cette année comme chaque année Casio t'a conçu de tous nouveaux goodies. Voici donc ci-contre une des dernières créations du constructeur, une batterie USB externe estampillée à son nom.
Un goodies exceptionnel qui pour une fois n'ira pas ramasser la poussière sur ton étagère ou dormir au fond de ton tiroir mais saura se rendre utile, et qui plus est pourra être utilisé directement avec ta calculatrice ! Et puis ce serait toute une fierté d'adjoindre ça à ta Casio, non ?
Il s'agit en fait de la Power Bank Endurance, un objet publicitaire personnalisable distribué en Europe par Inspirion.
La batterie offre une capacité de 2200 mAh.
Nous disposons donc d'un port USB micro-B pour la recharge, ainsi que d'un port USB A pour alimenter ta calculatrice ou tout autre appareil compatible.
Une fois chargée et connectée au port USB de ta calculatrice, la batterie externe te permet selon les modèles :
d'alimenter ta calculatrice et donc de prolonger la durée de vie de ses piles ou de sa batterie interne
de recharger la batterie interne de ta calculatrice
Avec la Graph 35+E II et autres calculatrices Casio Graph monochromes c'est particulièrement impressionnant, puisque la calculatrice accepte parfaitement de s'allumer et continuer à fonctionner correctement alimentée par la seule batterie externe, piles internes retirées donc ! Tu pourras donc même continuer à utiliser ta calculatrice une fois les piles complètement déchargées !
Attention toutefois, piqûre de rappel, en tant que module externe cette batterie USB est strictement interdite d'utilisation aux examens en France.
La batterie externe USB Casio n'étant pas sectaire, voici d'autres modèles qui s'accomodent parfaitement de cette seule alimentation externe :
TI-Nspire CX
HP Prime
Les modèles Casio couleur Graph 90+E et fx-CP400+E quant à eux n'acceptent pas de fonctionner en l'absence de l'alimentation interne par piles. Malgré l'alimentation externe, la calculatrice s'allume puis s'éteint immédiatement. Soit l'alimentation externe est insuffisante ce qui serait quand même surprenant vu les deux derniers modèles testés, soit ces modèles sont tout simplement plus stricts dans leurs vérifications de l'alimentation interne.
Le reste des modèles testés refuse catégoriquement de s'allumer lorsque alimentés uniquement en externe via leur port USB :
TI-83 Premium CE
TI-82 Advanced
NumWorks
TI-Nspire monochromes
Avec le nombre d'événements annulés cette année, tu risques ne ne pas avoir beaucoup d'occasions de récupérer ce goodies d'exception...
Et bien réjouis-toi car nous allons t'en faire gagner très prochainement tout un stock à notre concours de rentrée ; il y en aura pour récompenser tous les gagnants optant pour un lot Casio !