se réunissent pour te proposer un concours de rentrée exceptionnel autour de ton outil numérique scolaire favori, ta calculatrice graphique. Un événement difficile à organister avec tout le retard accumulé pour diverses raisons dans le contexte sanitaire actuel, mais justement dans ce contexte nous tenions particulièrement à ce qu'il puisse avoir lieu pour toi.
Aucune obligation d'achat pour participer et même gagner, grâce aux précieuses ressources gratuites que nous te compilons en fin d'annonce.
Au total 3 défis indépendants te seront lancés, tous en langage
Les défis ont tous été conçus pour être ludiques et abordables dès le collège. Rien d'insurmontable, à chaque fois nous te fournissons un script fonctionnel sur un maximum de calculatrices
Python
officielles ou non, script qu'il te suffira tout simplement d'améliorer. Tout-le-monde peut donc participer et gagner ! Tu peux relever autant de défis que tu veux et ton but sera aussi simple que dans un jeu vidéo ; réaliser selon le cas le plus grand ou le plus petit score possible. Il t'est même possible d'envoyer plusieurs participations à un même défi, dans ce cas nous ne prenons en compte que la meilleure, sous réserve qu'elle n'ait pas déjà été soumise par quelqu'un d'autre. Cela te permet à tout moment de tenter sans risque une amélioration de ton score. Les défis sont de plus totalement indépendants, tu peux parfaitement gagner à un défi sans avoir participé aux défis précédents.
Rien de secret chez nous, pas de rôle obscur et secret d'un jury, le script te renvoie directement ton score et tu as de plus accès à un classement en ligne régulièrement mis à jour de toutes les participations reçues :
il n'y a plus de service marketing spécifique à la France pour les calculatrices, nous relevons désormais d'un service gérant de façon unifiée le marketing des calculatrices pour l'ensemble de l'Europe, service de plus sous-traité en externe auprès d'une entreprise en République tchèque chez qui nous n'avons strictement aucun contact ce qui ne facilite pas la chose. Des approches auprès de nos quelques contacts par chance encore restants chez
Hewlett Packard
ne nous ont hélas pas permis d'obtenir jusqu'à présent de réponse autre que l'assemblage d'éléments que nous venons de te communiquer.
Nous te tiendrons au courant si jamais la situation évoluait favorablement en cours de concours, nous tentons quelques dernières approches qui n'ont pas encore reçu de réponse. Et sinon ben tant pis pour
Hewlett Packard
.
Toutefois tu n'es absolument pas pénalisé·e si tu souhaites participer sur
HP Prime
cette année. De notre côté le travail a bel et bien été fait, nos scripts de participation restent compatibles avec la
HP Prime
, et c'est paradoxalement la compatibilité avec ce modèle qui nécessité le plus d'efforts de notre part.
Les
13
participants ayant réalisé les plus petits scores distincts au défi de
Quetzalcóatl
pourront librement choisir et personnaliser leur lot parmi les propositions suivantes, par ordre de classement :
et que tu pensais être tiré·e d'affaire, voilà que tu tombes dans un gouffre.
Heureusement, ton formidable véhicule enclenche un protocole d'urgence et se métamorphose, faisant sortir et grandir un ballon d'hélium de ses entrailles. Dans le même temps, les têtes de forage se mettent enfin en marche et un nouveau script de pilotage se télécharge sur ta calculatrice.
C'est en fait toute une grotte qui s'étend devant toi, avec ses stalactites et stalacmites. La gallerie semble s'enfoncer davantage dans les profondeurs de la terre, mais plus possible de faire demi-tour n'est-ce pas ?
Afin de peut-être enfin trouver une sortie, tente maintenant de piloter ton excavatrice-dirigeable jusqu'au bout de la grotte, tout en consommant le moins d'énergie possible. Attention aux divers stalactites et stalacmites qui se dressent sur ton chemin, tu devras ou les contourner ou les forer...
Pour cela, nous te fournissons 3 scripts
Python
:
polycal2.py
, bibliothèque de compatibilité graphique gérant pas moins de 13 environnements
Python
graphiques sur calculatrices, officiels ou non
cave.py
, définissant tout ce qui concerne la grotte et que nous te laissons découvrir
cavetest.py
, un exemple de ce que tu dois fournir comme production
Tu dois donc définir une fonction effectuant une série d'appels modifier_vol(...) afin de piloter l'excavatrice-dirigeable jusqu'à la sortie. Voici un début de code en ce sens qu'il te suffit de compléter, et qui passe même pas trop mal le 1er pincement :
Tu peux ensuite évaluer ton plan de vol via les appels suivants, affichant le tracé, les éventulles collisions et donc zones de forage, ainsi que ta consommation :
Le script te renverra automatiquement ta consommation qu'il te suffira tout simplement de réduire le plus possible.
Aucune initiative n'est a priori interdite.
Tu es libre de définir et utiliser tout ce que tu veux
(fonctions, variables globales, autres scripts...)
mais ton code ne doit effectuer aucun accès en lecture ou écriture à des éléments de
cave.py
autres que la fonction précédente à appeler, ni interférer avec leur fonctionnement. Tu es également libre de modifier les scripts
polycal2.py
et
cave.py
fournis si cela peut t'aider, mais note bien que ton script sera testé avec les scripts tels que téléchargés chez nous. Donc attention à ce que tout reste bien fonctionnel.
Une fois ton script prêt, il te suffira de nous l'envoyer par courriel à
info@tiplanet.org
, avec :
en objet :
défi de Quetzalcóatl
une adresse courriel personnelle valide, si différente de l'adresse utilisée pour l'envoi de la participation
ton adresse postale complète avec nom et prénom(s)
si tu le souhaites, ton pseudonyme sur
TI-Planet
ou
Planète Casio
(la liste des participants publiée en fin de concours utilisera les pseudonymes si fournis, et à défaut seulement les prénoms et initiales des noms)
si tu le souhaites, sans conséquence sur ta victoire ou ton choix de lot, les badges à afficher dans notre classement à côté de tes participations :
l'équipe que tu soutiens :
TI-Planet
ou
Planète Casio
la guilde que tu soutiens :
Casio
,
Hewlett Packard
,
Lexibook
,
NumWorks
,
Symbolibre
ou
Texas Instruments
un numéro de téléphone personnel valide
(utilisé uniquement dans ton intérêt en cas d'urgence - par exemple en cas de problème avec une participation ou un choix de lot et qu'il reste peu de temps pour participer/répondre)
Note: tout ceci (informations personnelles) sera
uniquement
utilisé dans le cadre du concours puis supprimé dès qu'il est fini et/ou après utilisation pour communication sur la livraison des lots le cas échéant
Si il y avait un rendez-vous annuel à ne pas rater pour un constructeur de calculatrices en France, ce serait les journées de l'
APMEP
(Association des Professeurs de Mathématiques de l'Enseignement Public)
.
Les journées
APMEP
devaient initialement avoir lieu le week-end prochain à Bourges.
Dans le contexte sanitaire à aggravation exponentielle que nous connaissons actuellement, l'événement est reporté à 2021.
Toutefois,
en attendant Bourges
l'
APMEP
et les constructeurs de calculatrices se sont démenés pour t'offrir quand même cette année une édition virtuelle de ces journées, ouverte à toutes et tous et totalement gratuite.
Et oui, pour la première fois après plus d'une décennie de fidélité,
Hewlett Packard
et sa
HP Prime
ne seront pas présents cette année.
Cela semble faire suite aux lourdes réorganisations au sein de l'entreprise en 2019-2020. Il n'y a plus de service marketing spécifique à la France pour les calculatrices, nous relevons désormais d'un service gérant de façon unifiée le marketing des calculatrices pour l'ensemble de l'Europe, service de plus sous-traité en externe auprès d'une entreprise en République tchèque,
, entreprise qui ne semble pas avoir bien saisi le caractère incontournable de ces journées ou pire ignorer totalement leur existence.
De nombreux ateliers sont prévus en vidéoconférence. Toutefois le site ne nous semble pas très clair, dans le sens où certains sont annoncés sur le planning général, et d'autres sur les seules pages de certains des exposants.
Voici donc pour te clarifier la chose directement par rapport à tes disponibilités, une petite liste chronologique des vidéoconférences tournant autour de la calculatrice graphique, l'outil
TICE
nomade du lycéen, avec les liens pour s'inscrire et rejoindre :
"Il suffit de 1,1 volt à nos pseudo-personnalités pour maintenir leur intégrité même dans des environnements apocalyptiques..."
Non décidément
Aperture Science
se moque de toi, ce n'est pas demain la veille que
GlaDOS
fonctionnera de façon durable et fiable sur batteries-patates, et encore moins sur une seule.
Et une
TI-84 Plus
alors ? C'est déjà bien plus réaliste. Ce modèle monochrome avait en effet le gros avantage d'être fort peu gourmand par rapport aux modèles couleurs à batterie plus récents qui ne tiennent même pas une journée complète en utilisation continue.
Commençons déjà par nous poser la question. Combien ça consomme une
TI-84 Plus
?
Pour mesurer la consommation de la calculatrice, il nous faut couper le circuit de la calculatrice afin de pouvoir y intercaler un capteur d'intensité. Nous allons utiliser pour cela un éliminateur de piles. Il s'agit d'un adaptateur initialement conçu pour permettre de brancher des appareils à piles sur secteur. L'adaptateur utilise pour cela un jeu de fausses piles, l'une d'entre elles étant câblée.
Nous allons ici modifier la chose ; débarrassons-nous de l'adaptateur secteur et rajoutons en série la 4ème vraie pile que l'on ne peut plus insérer dans la
TI-84 Plus
. Nous pouvons alors intercaler un capteur d'intensité
se propose de répondre à la question de façon empirique, environ
200
!
Voici
Doom
ou du moins son adaptation pour
TI-82 Stats
,
TI-83 Plus
et
TI-84 Plus
, pour la première fois au monde propulsé par un champ de patates :
À quand les cultures de champs de patates dans la cour du lycée afin de compenser la consommation de piles en période d'examens, ainsi que leur surconsommation désormais induite par l'utilisation du mode examen et donc de sa diode clignotante ?
Dès 1999, le constructeur sortait son successeur, la
TI-83 Plus
, toujours commercialisée aujourd'hui dans certains pays.
La principale nouveauté était l'exploitation de la technologie
Flash
, pour la première fois sur le milieu de gamme après avoir été introduite en 1998 sur l'entrée de gamme
TI-73
ainsi que sur le haut de gamme
TI-89
puis
TI-92 Plus
.
Une innovation majeure, permettant l'exploitation d'une mémoire de stockage bien plus conséquente que ce que permettait la
RAM
jusque-là, l'installation d'applications, et surtout enfin la mise à jour du système d'exploitation de la calculatrice, plus besoin de racheter une calculatrice pour profiter des corrections de bugs !
utilisé par l'équipe de développement avant la sortie de ce modèle. Le nom n'est d'ailleurs affiché que par le logiciel, le boîtier étant estampillé d'un simple
XX-X
à la place du nom du modèle. Une pièce exceptionnelle dénichée par
qui dispose d'une fonctionnalité formidable, celle de pouvoir échanger des données avec une vraie calculatrice. Certes la validation de l'
OS
reçu était toujours refusée, à la différence qu'ici sur ordinateur il a pu en profiter pour écouter et garder une trace de l'ensemble des paquets de données transférés.
. Plus précisément il s'agit ici de la version bleue avec un très beau motif, mais d'autres teintes sont disponibles :
bleu
rouge
turquoise
noir
gris
La housse de protection est destinée à protéger ta calculatrice contre les rayures et les chocs.
Elle s'ouvre et se referme sur 3 côtés à l'aide d'une fermeture éclair pour un bien meilleur accès à son contenu, et dispose même d'une boucle d'attache.
Notons qu'elle vient également avec 3 bandes à la fois auto-agrippantes et adhésives.
Mais où faut-il coller ces bandes de 6,55 cm, la housse n'étant pas accompagnée d'un mode d'emploi ?
Nombre d'utilisateurs choisissent de les installer au dos de la calculatrice, et ne sachant alors plus quoi faire du couvercle de la calculatrice finissent par cesser de l'utiliser.
Or c'est une grave erreur. Bien qu'il ne s'agisse pas ici d'une simple poche en tissu, cela reste quand même une housse souple. Avec housse mais sans couvercle ton écran, soit dit en passant la pièce la plus fragile de ta calculatrice, est certes protégé contre les rayures mais ne l'est plus contre les diverses pressions pouvant s'exercer au sein de ton sac. Rappelons que le bris de l'écran n'est pas couvert par la garantie.
Donc comment bien utiliser ta housse ? Voici notre tuto.
En fait c'est très simple, les bandes velcro sont à coller non pas directement sur ta calculatrice, mais sur la face extérieure de ton couvercle. C'est ensuite le couvercle que tu installes dans la housse.
Par la suite, à chaque fois que tu as terminé de te servir de ta calculatrice, tu la glisses dans la housse écran du côté du couvercle.
A chaque fois que tu souhaites t'en servir à nouveau, il te suffit soit de la sortir de la housse, soit de la retourner.
Cette housse ne convient pas aux calculatrices à piles bien plus épaisses. Par contre, elle reste parfaitement utilisable de façon similaire avec d'autres modèles à batterie rechargeable :
TI-84 Plus CE
,
TI-Nspire CX
,
HP Prime
et
NumWorks
.
Envie de cette superbe housse
Wyngs
pour habiller ta non moins superbe calculatrice ? Tu peux la gagner actuellement à notre concours de rentrée, ou sinon si tu préfères l'acheter ci-dessous.
, du nom du philosophe, grammairien et pédagogue tchèque, est une récompense prestigieuse à rayonnement européen décernée chaque année depuis 1995 par l'allemand
GPI
(
G
esellschaft für
P
ädagogik,
I
nformation und Medien; soit société pour l'éducation, l'information et les médias)
, à des produits multimédias d'intérêt pédagogique ou didactique exceptionnel.
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.
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)
def sierp(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)
, 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 :
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)
def _draw_turtle(x,y,a,c): global turtle_buffer def inbuffer(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<=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(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==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))
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()
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_angle goto(0,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): left(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])
elif len(c)==3 and isinstance(c[0],(int,float)) and isinstance(c[1],(int,float)) and isinstance(c[2],(int,float)) and 0<=c[0]<=1 and 0<=c[1]<=1 and 0<=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()
def pendown(): down()
def pensize(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)==0 or 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()
def right(a): global turtle_angle if isinstance(a, (int, float)): turtle_angle = _conv_angle(turtle_angle-a) else: raise ValueError('error') _refresh_turtle()
def rt(a): right(a)
def seth(a): setheading(a)
def setheading(a): global turtle_angle turtle_angle=_conv_angle(a) _refresh_turtle()
def setpos(x,y): goto(x,y)
def setposition(x,y): setpos(x,y)
def setx(x): goto(x,turtle_pos[1])
def sety(y): goto(turtle_pos[0],y)
def shape(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()
def showturtle(): global turtle_visible turtle_visible=True _refresh_turtle()
def speed(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.5 or 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")
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: 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.
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.
try: from matplotlib.pyplot import * except ImportError: from matplotl import *
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()
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 !
, 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 :
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 axis(*L): global fenetre,win_scaling,axis_display if len(L)==1 and 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')
def text(x,y,txt): global textes txt=str(txt) 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 def plotpoint(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] not in 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'
def plotline(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] not in 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'
def auto(c): global color_count if (c != None and len(c)==2 and 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
def testcolor(c): if (len(c)==2 and c[0] in available_colors and c[1] in ['o','.','+','*','-']) or (c in available_colors+['o','.','+','*','-']) : return True else: raise ValueError('function plot() : unknown color code')
color=kwargs.get('color',None) if color!=None and not color in available_colors: 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],auto(color)) elif len(L)==2 and 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)==1 and 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)==3 and 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)==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])): 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)==2 and 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') def show(): global fenetre, limits, points, lines, textes, extrem, win_scaling, axis_display, color_count, color_grid, grid_display def RGB(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")
def printable(X): global limits return(limits[0]<=X[0]<=limits[2] and limits[3]<=X[1]<=limits[1]) def echelle(a,b): k=0 e=abs(b-a) while e>=10 : e/=10 k+=1 while e<1 : e*=10 k-=1 return k def pas(a,b): pas=10**echelle(a,b) while (abs(b-a))//pas<4: pas/=2 return pas def converttopixel(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<=1 and 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'
def bar(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')
def scatter(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')
def hist(x,bins=10,**kwargs): global color_count hist_type=kwargs.get('hist_type','std') if hist_type not in ['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
def boxplot(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 not in ['fr','std']: raise ValueError('function boxplot() : boxplot_type must be std or fr') def mediane(l,p): if p%2==0: return (l[p//2]+l[p//2-1])/2 else: return l[p//2] def quantiles(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': def percentile(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-1 and 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>0 or 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')
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 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)
def grid(*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 not in 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==True or affichage=='true': grid_display='on' elif affichage=='off' or affichage=='False' or affichage==False or 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
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
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
$mathjax$\frac{360}{12}=30$mathjax$
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.
unsafe = () if pf == 4: #HP Prime unsafe = ('count','encode','endswith','find','format','index','islower','lstrip','replace','rfind','rindex','rsplit','rstrip','split','splitlines','startswith','strip','from_bytes','to_bytes','fromkeys','get','pop','setdefault','update','values','sort','__enter__','__exit__','read','readinto','readline','seek','write') if pf == 5 or pf == 7 or pf == 9: #CasioPython / Nspire+NumWorks KhiCAS MicroPython unsafe = ('sys.argv', 'sys.path')
if pf >= 0: curline=0 _p = print def print(*ls): global curline st="" for s in ls: if not(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
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): if str(obj).startswith("<module"): return False l = () try: l = dir(obj) except: pass return len(l)
def explmodr(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: if not 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]) if not isFound: found.append(itm[0]) if not isUnsafe and isExplorable(itm[1]) and itm[1] not in pitm_val_l and itm[2] not in 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
def explmod(s): global found module = __import__(s) found = [] return explmodr(module)
# detects calculator Python platform def get_pf(): c256 = True try: if chr(256)==chr(0): # Xcas/KhiCAS Python compatibility if "HP" in version(): return 13 # HP Prime else: if not white: return 12 # Graph 35+E II elif "Numworks" in version(): return 10 # NumWorks elif "Nspire" in version(): return 8 # Nspire else: # Graph 90+E return 11 except: c256 = False try: import sys try: if sys.platform == "nspire": try: # Nspire Ndless import graphic return 7 # KhiCAS Micropython except: # MicroPython return 6 elif sys.platform == "TI-Nspire": return 3 # Nspire CX II elif sys.platform == "numworks": return 9 # NumWorks KhiCAS Micropython elif sys.platform.startswith('TI-Python'): return 2 # 83P/84+ CE except: # Graph 35+E/USB / 75/85/95 return 5 except: pass if not c256: return 1 # Graph 90/35+E II try: import kandinsky return 0 # NumWorks except: try: # HP Prime import hpprime return 4 except: pass return -1
#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) def get_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 == 7 or 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 def shell_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 :
, 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 international / mode examen 1
(
fx-9860GII
,
fx-9750GIII
,
fx-9860GIII
,
fx-CG10
,
fx-CG20
,
fx-CG50
)
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
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é.
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
en édition limitée pour sa calculatrice, illustré tout en humour et talent sur le thème des Mathématiques.
Nous t'en faisons actuellement gagner quelques derniers exemples à notre concours de rentrée.
Dans le contexte sanitaire que tu connais cette année, la plupart des événements de l'automne sont annulés, entre autres l'
Oktoberfest
.
Mais
NumWorks
te propose de fêter malgré tout le mois d'Octobre avec un tout nouveau couvercle à gagner !
Cette édition limitée 2020 reste illustrée tout en références et talent autour du thème des Mathématiques.
Le couvercle te représente le roi de cœur usuellement surnommé
Charles
en référence à
Charlemagne
, ce sacré personnage qui selon la chanson populaire aurait inventé l'école.
Charles
n'est justement ici pas armé d'une épée, mais d'un compas à molette qu'il brandit fièrement, c'est ce qu'on appelle avoir le compas dans l'oeil, non ?
Mais ce qu'il y a de bien, c'est que ce couvercle se veut réversible et inclusif ! Selon tes préférences il te suffira de le retourner pour obtenir à la place
Judith
, la merveilleuse reine de cœur chère au mathématicien et écrivain anglais
Lewis Caroll
.
Judith
ne brandit ici ni une rose ni même une fleur, mais une règle graduée de
11 cm
, référence ratée ou alors qui nous échappe, la dame de cœur valant en fait 12 points dans le jeu. Après si on compte la graduation zéro, certes...
Bref
NumWorks
te propose de gagner par paires 10 de ces couvercles.
Pour cela c'est très simple, il te suffit depuis ton compte