Graph Paper

Format des documents de tracé

Un document de tracé est un objet JSON qui décrit un tracé de Graph Paper : ses formules, ses curseurs, ses points à déplacer et ses axes. Encodez-le dans un lien, et Graph Paper l'ouvre comme un document que le lecteur peut modifier. Cette page décrit chaque champ.
Cette page s'adresse aux programmes et aux agents d'IA qui écrivent des documents. Un programme qui veut donner un tracé à une personne commence par Pour les agents : le moyen le plus rapide est d'envoyer le document avec POST https://graph-paper.io/plot-link, ou avec GET https://graph-paper.io/plot-link?doc=<JSON encodé en pourcentage> depuis un outil qui peut seulement lire une adresse ; la réponse contient le lien, ou les erreurs. Pour ce qu'il faut écrire dans une formule, voir le Guide des tracés.
Chaque formule est en LaTeX. Dans une chaîne JSON, écrivez "\\sin(x)", pas "sin(x)", et "x^{2}", pas "x**2". Le validateur refuse un nom de fonction écrit en texte brut (exp(…), sqrt(…)) et dit quoi écrire. Un nombre en notation scientifique comme 2.312e-05 est accepté et lu comme le nombre, et Graph Paper l'affiche comme 2.312 × 10⁻⁵, la forme qu'obtient une personne qui le tape. Certains nombres sont affichés tels qu'ils sont écrits (2.312e − 05, qu'une personne peut lire comme la constante e et une soustraction), et le validateur donne un avertissement pour eux : un nombre avec une espace à l'intérieur, un nombre suivi de ^, _ ou d'un prime, un nombre dans un indice ou dans un groupe {…} seul, un nombre juste après } ou après une commande comme \frac, et un nombre dont la mantisse commence par un point (.5e3). Pour ceux-là, écrivez un décimal simple (0.00002312) ou a\cdot 10^{n} ("2.312\\cdot 10^{-5}" en JSON). Un point sans chiffre après lui (1.e5) ou un point dans l'exposant (1e3.5) n'est pas un nombre que Graph Paper peut lire, et le validateur le refuse.
Un programme doit lire la version Markdown de cette page, à l'adresse https://graph-paper.io/plot-document-format/fr/index.md, car un résumé de la page HTML peut perdre les tableaux. Chaque page de guide existe en Markdown : ajoutez index.md à son URL, ou envoyez Accept: text/markdown. Le fichier https://graph-paper.io/llms-full.txt contient à lui seul le texte anglais de cette page, de Pour les agents, du Guide des tracés et des Astuces et conseils.

Sommaire

Un document minimal

Un titre et une série :
json{ "title": "Sinusoïde", "series": [{ "type": "line", "fn": "\\sin(x)" }] }
Pour l'ouvrir, encodez le JSON en UTF-8, puis en base64url (RFC 4648 §5, sans remplissage), et ajoutez-le à https://graph-paper.io/new#doc=. Les exemples complets ci-dessous montrent les liens entiers. Un programme qui ne sait pas calculer de base64url peut écrire le JSON, encodé en pourcentage, après https://graph-paper.io/new#json=. Un lien n'a qu'une forme. Le service https://graph-paper.io/plot-link vérifie un document et renvoie son lien, sans compte. Voir Vérifier un document.

Règles et limites

Champs de premier niveau

ChampTypeObligatoireSignification
titlechaîneouiLe titre du document, en texte brut.
seriestableauouiLes lignes tracées, au moins une. Voir Séries.
variablestableaunonLes curseurs. Voir Variables.
pointstableaunonLes points que le lecteur déplace sur le tracé. Voir Points.
definitionstableaunonLes valeurs et fonctions nommées que les autres lignes utilisent. Voir Définitions.
actionstableaunonLes lignes qui changent des variables, une fois ou à intervalle régulier. Voir Actions.
markerstableaunonLes annotations sur le tracé : étiquettes, segments, droites, bandes. Voir Marqueurs.
domainobjetnonIntervalles des axes 2D, rapport d'aspect et système de coordonnées. Voir Axes et scène.
stageobjetnonApparence 2D : grille, axes, cadre.
domain3dobjetnonIntervalles des axes 3D et proportions.
stage3dobjetnonScène 3D : environnement, éclairage, caméra, projection.
presetobjetnonL'apparence du document : { "base": "basel" }. Bases : basel, vellum, academic, slides.
categorychaînenon"2d", "3d" ou "data". S'il est absent, Graph Paper le déduit des types de séries.
Le document s'ouvre avec ses lignes dans cet ordre : variables, points, définitions, actions, puis séries. Une ligne peut utiliser un nom qu'une ligne située au-dessus définit.
Le type de la première série décide si le document est un tracé 2D ou 3D. Ne mélangez pas des séries 2D et 3D dans un même document.

Variables

Une variable est un curseur. Chaque ligne de variables est un objet :
ChampTypeObligatoireSignification
namechaîneouiLe nom, tel que les formules l'utilisent : "a", "c_1", "omega" ou "\\omega" ; voir les règles de nommage ci-dessous.
valuechaîneouiLa valeur de départ, en LaTeX : "0.3", "\\frac{\\pi}{2}".
domainobjetouiLes valeurs que le curseur accepte. Voir ci-dessous.
playbackobjetnonL'animation de la variable : { "mode": "bounce", "direction": "forward", "duration": 5000 }. En son absence : "bounce", "forward", 4000 ms.
autoplaybooléennontrue démarre l'animation à l'ouverture du document. En son absence, ou avec false, la variable reste au repos.
notechaînenonUn texte affiché au-dessus de la ligne.
domain prend l'une de deux formes :
playback.mode vaut "once", "loop", "bounce" ou "all-at-once". "all-at-once" n'anime pas : il trace chaque série une fois pour chaque valeur d'un domaine values. direction vaut "forward" ou "reverse". duration est la durée d'un passage, en millisecondes.
N'utilisez pas x, y ni z comme nom de variable : ces noms sont les axes du tracé. N'utilisez pas non plus e, i ni pi : les formules les lisent comme des constantes.
t, u, v, r, theta et phi sont les noms que le tracé donne au paramètre d'une courbe paramétrique (t), d'une surface paramétrique (u, v), à un angle polaire (theta, phi) et au rayon polaire (r). Une variable peut avoir l'un de ces noms. Alors chaque formule du document qui utilise ce nom utilise la valeur de la variable. Par exemple, avec une variable t, la série paramétrique (\cos(t), \sin(t)) ne trace aucune courbe, car tous ses points utilisent la même valeur de t. Il y a une exception : à gauche d'une équation polaire, r est le rayon. Avec une variable r, la formule r = 2\cos(\theta) reste une courbe polaire dont le rayon est r.
Un nom est une lettre ("M", "s") ou le nom d'une lettre grecque ("omega", "epsilon"), avec un indice facultatif ("c_1"). Un indice entre accolades suit une seule lettre ("x_{max}") ; après un nom grec, écrivez "theta_0" ou "\\theta_{0}", et non "theta_{0}", que le validateur refuse. Écrits en clair, certains noms sont d'autres symboles dans une formule : nommez "\\zeta", "\\Pi", les variantes ("\\varphi", "\\vartheta", …) et "\\hbar" en LaTeX, pour que le curseur agisse sur la formule. Dans une formule, \delta avec un indice est le delta de Kronecker et \mu_0 est une constante : nommez une variable "d_1" plutôt que "delta_1", et écrivez \mu_{0}, avec des accolades, pour une variable "mu_0". Une formule lit un nom de plusieurs lettres latines, comme mass, comme un produit de lettres. Dans une formule, écrivez une lettre grecque avec sa commande LaTeX : la variable "epsilon" s'écrit \epsilon dans une formule, et "\\epsilon" dans le JSON de fn.
La ligne du curseur affiche un nom grec avec sa lettre : la variable "omega" s'affiche \omega. Nommez une lettre grecque par son nom simple ("epsilon", "rho"), et non par un nom de variante ("varepsilon"), que Graph Paper affiche comme un mot droit. Une majuscule qui ressemble à une lettre latine ("Alpha", "Mu") s'affiche aussi comme un mot droit.

Points

Un point est une paire de variables que le lecteur change en déplaçant un marqueur sur le tracé. Chaque ligne de points est un objet :
ChampTypeObligatoireSignification
xobjetouiLa première coordonnée : { "name": "c_x", "value": "0.5" }.
yobjetouiLa seconde coordonnée : { "name": "c_y", "value": "1" }.
dragchaînenon"x" ou "y" pour ne permettre que cette direction, "none" pour aucun déplacement. Par défaut, le point se déplace librement.
notechaînenonUn texte affiché au-dessus de la ligne.
Les formules utilisent les deux noms de coordonnées comme des variables ordinaires. Les points sont réservés aux documents 2D. Une action peut aussi changer les deux coordonnées.

Un point qui bouge

Une série scatter dont le fn est la formule d'un point trace un point qui bouge. La formule peut utiliser des variables et des définitions :
json{ "type": "scatter", "fn": "(L\\sin(a), -L\\cos(a))", "color": "#c62828", "marker": { "size": 14 } }
Quand un curseur, un déplacement ou une action change L ou a, Graph Paper trace à nouveau le point à sa nouvelle position. Le pendule utilise cette ligne pour sa masse.
Un point de points est différent. C'est une entrée : le lecteur le déplace, et le déplacement fixe deux variables que d'autres lignes lisent. Un point scatter est un résultat : sa formule fixe sa position. Utilisez points pour une valeur que le lecteur choisit, et une formule scatter pour une valeur que le document calcule.

Définitions

Une définition nomme une valeur ou une fonction. Les autres lignes utilisent ce nom. Chaque ligne de definitions est une chaîne LaTeX, ou un objet :
ChampTypeObligatoireSignification
latexchaîneouiLa définition : "m = 100", "f(x) = e^{-x}\\cos(x)".
hiddenbooléennontrue masque la courbe de la ligne. Voir ci-dessous.
notechaînenonUn texte affiché au-dessus de la ligne.
Une fonction d'une variable, comme f(x) = x^2, trace aussi sa propre courbe y = f(x). Mettez "hidden": true quand la fonction est un outil qui ne doit pas être tracé. Une définition masquée fonctionne toujours : les autres lignes peuvent l'utiliser.
Le paramètre d'une fonction appartient à la définition seule. Ce peut être une lettre, une lettre avec un indice, ou une lettre grecque écrite avec sa commande LaTeX : f(s) = s^2, p(t) = 2t, r(x) = x/3 et q(\sigma) = \sigma + 10 fonctionnent tous. Un paramètre peut avoir le même nom qu'une variable. Dans la définition, c'est le paramètre qui compte, pas la variable : avec un curseur s à 5, f(s) = s^2 donne f(3) = 9, et non 25.

Actions

Une action change des variables quand elle s'exécute. Le lecteur l'exécute une fois avec son bouton ⚡, ou une minuterie l'exécute encore et encore. Chaque ligne de actions est un objet :
ChampTypeObligatoireSignification
latexchaîneouiL'action : "a \\to a + 1". Voir Astuces et conseils.
intervalchaînenonExécuter l'action à nouveau toutes les N millisecondes (en LaTeX : "100").
autoplaybooléennontrue démarre la minuterie à l'ouverture du document. Demande interval.
notechaînenonUn texte affiché au-dessus de la ligne.
Une action peut changer une variable, une coordonnée d'un point de points, ou une liste ou un point qu'une définition donne par sa valeur, comme S = [2.5, 0]. Elle ne peut pas changer un nom qu'une formule définit, comme b = 2a. Séparez plusieurs changements par des virgules. L'action calcule d'abord toutes les nouvelles valeurs à partir des anciennes, puis les écrit ensemble. Pour une minuterie qui fait avancer un état, voir Une simulation avec une minuterie.

Séries

Une série est une ligne tracée. Chaque série a un type. La plupart des types prennent une formule dans fn : voir le Guide des tracés pour ce qu'une formule peut contenir, ainsi que pour la clause where et les restrictions entre accolades qui limitent ce qui est tracé.
fn est du LaTeX. Les commandes comme \frac{a}{b}, \sqrt{x}, \sin(x), \ln(x) et \pi fonctionnent. Le texte brut n'est pas du LaTeX : Graph Paper lit sqrt(x) comme les lettres s, q, r et t, et non comme une racine carrée.
Champs que la plupart des types de séries acceptent :
ChampTypeSignification
typechaîneLe type de série. Obligatoire. Voir les tableaux ci-dessous.
fnchaîneLa formule, en LaTeX.
domaintableau ou objetL'intervalle des variables de la formule. Sa forme dépend du type.
colorchaîne ou objetUne couleur ("#c62828"), un nom de la palette ("red-700") ou un nom de carte de couleurs ("viridis").
namechaîneL'étiquette dans la légende.
idchaîneUn nom auquel une autre série peut faire référence, par exemple dans "fill": { "to": { "series": "lower" } }.
Comment Graph Paper enregistre chaque série dans le document :
Chaque série du document est enregistrée comme une ligne.

Types de séries 2D

typeTraceObligatoiredomain
liney = f(x)fn, ou x et y[min, max] de x
parametricune courbe (x(t), y(t))fn[min, max] de t
polarr = f(\theta)fn, ou theta et r[min, max] de \theta
implicitune courbe F(x, y) = 0, ou une région d'après une inéquationfn{ "x": [a, b], "y": [c, d] }
heatmapune couleur pour chaque point de f(x, y)fn, ou x, y et z{ "x": [a, b], "y": [c, d] }
domainColoringune fonction complexe de zfn{ "x": [a, b], "y": [c, d] }
vector-fielddes flèches (P(x, y), Q(x, y))fn{ "x": [a, b], "y": [c, d] }
scatterdes pointsfn, ou x et y—
polygon-listdes polygones remplisfn, ou polygons—
barun diagramme en barresx (étiquettes), y—
histogramles effectifs par classe d'une liste de valeursvalues—
candlestickouverture, haut, bas et clôture pour chaque xdata—
boxplotdes boîtes à moustachesdata—
derivedune droite de tendance, une moyenne, une courbe lissée, une dérivée ou une intégrale d'une autre sériesource, transform—
Remarques sur certains types :
Une série minimale de chaque type, une par ligne :
json{ "type": "line", "fn": "x^2 - 1", "domain": [-3, 3] } { "type": "parametric", "fn": "(\\cos(3t), \\sin(2t))", "domain": [0, 6.283185307179586] } { "type": "polar", "fn": "1 + \\cos(\\theta)", "domain": [0, 6.283185307179586] } { "type": "implicit", "fn": "x^2 + y^2 \\le 1", "domain": { "x": [-2, 2], "y": [-2, 2] } } { "type": "heatmap", "fn": "\\sin(x)\\cos(y)", "domain": { "x": [-6, 6], "y": [-6, 6] }, "color": "viridis" } { "type": "domainColoring", "fn": "z^2 - 1", "domain": { "x": [-3, 3], "y": [-3, 3] } } { "type": "vector-field", "fn": "(-y, x)", "domain": { "x": [-4, 4], "y": [-4, 4] }, "gridSize": 16 } { "type": "scatter", "x": [1, 2, 3, 4], "y": [2.1, 3.9, 6.2, 7.8] } { "type": "polygon-list", "fn": "[\\operatorname{polygon}((0,0), (1,0), (0,1))]" } { "type": "bar", "x": ["A", "B", "C"], "y": [23, 45, 12] } { "type": "histogram", "values": [1.2, 0.4, -0.3, 0.8, 1.9, -1.1, 0.2] } { "type": "candlestick", "data": [{ "x": 1, "open": 10, "high": 15, "low": 8, "close": 13 }] } { "type": "boxplot", "data": [{ "min": 2, "q1": 5, "median": 7, "q3": 9, "max": 14 }], "x": ["A"] }
Il n'y a pas de type distinct pour les lignes de niveau : utilisez un heatmap avec "contours": true, ou une équation implicit pour une seule courbe de niveau.

Un segment entre deux points

La 2D n'a pas de type segment. Pour tracer un segment de P = (p_x, p_y) à Q = (q_x, q_y), utilisez une série parametric de (1 - t)P + tQ pour 0 \le t \le 1, écrite avec les coordonnées :
json{ "type": "parametric", "fn": "((1 - t)p_x + tq_x, (1 - t)p_y + tq_y)", "domain": [0, 1], "stroke": { "width": 3 } }
Les extrémités peuvent être des formules, et le segment bouge alors avec elles.
Une série scatter de deux points reliés par une ligne trace aussi un segment. Son fn est une liste des deux points. La tige du pendule va de (0, 0) à la masse, qui suit l'angle a :
json{ "type": "scatter", "fn": "[(0, 0), (L\\sin(a), -L\\cos(a))]", "line": true, "points": false }
N'utilisez pas polygon-list pour un segment : ses polygones sont remplis.

Types de séries 3D

typeTraceObligatoiredomain
surfacez = f(x, y)fn, ou z{ "x": [a, b], "y": [c, d] }
parametric-surfaceune surface (x(u, v), y(u, v), z(u, v))fn{ "u": [a, b], "v": [c, d] }
parametric-curveune courbe (x(t), y(t), z(t))fn[min, max] de t
implicit-surfaceune surface F(x, y, z) = 0fn{ "x": [a, b], "y": [c, d], "z": [e, f] }
scatter3ddes points dans l'espacefn, ou x, y et z—
analyticLandscapela hauteur et la phase d'une fonction complexefn{ "x": [a, b], "y": [c, d] }
primitives3ddes sphères, des segments, des flèches et des trianglesfn, ou items—
meshdes triangles entre des points donnésvertices, faces—
Remarques sur certains types :
Une série minimale de chaque type, une par ligne :
json{ "type": "surface", "fn": "x^2 - y^2", "domain": { "x": [-3, 3], "y": [-3, 3] }, "color": "coolwarm" } { "type": "parametric-surface", "fn": "(\\sin(u)\\cos(v), \\sin(u)\\sin(v), \\cos(u))", "domain": { "u": [0, 3.141592653589793], "v": [0, 6.283185307179586] } } { "type": "parametric-curve", "fn": "(\\cos(t), \\sin(t), t / (2\\pi))", "domain": [0, 12.566370614359172] } { "type": "implicit-surface", "fn": "x^2 + y^2 + z^2 = 4", "predicate": "=0", "domain": { "x": [-3, 3], "y": [-3, 3], "z": [-3, 3] } } { "type": "scatter3d", "x": [1, 2, 3], "y": [2, 3, 1], "z": [3, 1, 4] } { "type": "analyticLandscape", "fn": "z^3 - 1", "domain": { "x": [-2, 2], "y": [-2, 2] }, "heightMode": "log-magnitude" } { "type": "primitives3d", "fn": "[\\operatorname{segment}((0,0,0), (1,1,1))]" }

Données sans formule

Une série peut donner ses valeurs sous forme de données littérales au lieu d'une formule dans fn. Graph Paper enregistre chacune de ces séries comme une ligne du document.
typeDonnéesLigne
scatterx, ytableau
scatter3dx, y, ztableau
linex, ytableau
polartheta, rtableau
barx (étiquettes), ytableau
histogramvaluestableau
candlestickdatatableau
boxplotdata, x (étiquettes)tableau
heatmapx, y, zligne de données
surfacezligne de données
polygon-listpolygons, fillColors (facultatif)ligne de données
meshvertices, faces, normals (facultatif)ligne de données
primitives3ditemsligne de données
Le lecteur peut modifier les nombres d'un tableau. Une ligne de données garde ses données telles quelles : le lecteur peut changer son style, la masquer, la copier ou la supprimer, mais pas modifier ses nombres.
Les formes des données :
shapeChamps
spherecenter, radius
cubecenter, size (un nombre, ou [largeur, profondeur, hauteur])
cylinder, cone, tubefrom, to, radius
linefrom, to, width (facultatif)
arrowfrom, to, et les champs facultatifs radius, headRadius et headLength
trianglevertices : trois points
Une série de chaque type de ligne de données, une par ligne :
json{ "type": "line", "x": [0, 1, 2, 3], "y": [1, 3, 2, 4] } { "type": "polar", "theta": [0, 1.5708, 3.1416, 4.7124], "r": [1, 2, 1, 2] } { "type": "heatmap", "x": [0, 1, 2], "y": [0, 1], "z": [[1, 2, 3], [4, 5, 6]] } { "type": "polygon-list", "polygons": [{ "x": [0, 1, 0], "y": [0, 0, 1] }], "fillColors": ["#1e88e5"] } { "type": "surface", "z": [[0, 1, 0], [1, 2, 1], [0, 1, 0]], "domain": { "x": [-1, 1], "y": [-1, 1] } } { "type": "mesh", "vertices": [[0, 0, 0], [1, 0, 0], [0, 1, 0]], "faces": [[0, 1, 2]] } { "type": "primitives3d", "items": [{ "shape": "sphere", "center": [0, 0, 0], "radius": 1 }] }

Séries dérivées

Une série derived trace un calcul sur une autre série du document : une droite de tendance, une moyenne mobile, une courbe lissée, une dérivée ou une intégrale. source est l'id de cette série, et transform dit ce qu'il faut calculer. Graph Paper l'enregistre comme une ligne dérivée, qui suit la source quand le lecteur la modifie.
transformChampsSource
{ "kind": "trendline", "model": "linear" }model : "linear", "quadratic", "polynomial" (avec degree, de 1 à 10), "exponential", "power" ou "logarithmic"données
{ "kind": "sma", "window": 5 }window : le nombre de points, 1 ou plusdonnées, points, dérivée
{ "kind": "ema", "alpha": 0.2 }alpha : plus de 0, au plus 1données, points, dérivée
{ "kind": "smooth", "tension": 0.5 }tension (facultatif) : de 0 à 1données, points, dérivée
{ "kind": "derivative" }—formule
{ "kind": "integral" }—formule
Les types de source :
source doit nommer l'id d'une seule autre série, et la transformation doit être une de celles que la source accepte : Graph Paper ne change pas une transformation pour l'adapter à sa source, donc une incompatibilité est une erreur. Sur une droite de tendance, "legendEquation": true affiche l'équation ajustée dans la légende, et "legendShowR2": true ajoute R^2. Les champs de style sont color, stroke, legend et legendLabel ; name est le texte de l'entrée de légende. Sans color, la série prend la couleur de sa source.
Il n'y a pas de type derived-marker. Pour l'équation d'un ajustement, utilisez une droite de tendance avec "legendEquation": true.

Marqueurs

Les marqueurs sont des annotations sur le tracé : une étiquette, un segment avec une flèche, une droite qui traverse le tracé, une bande, un rectangle, une ellipse. Le tableau markers de premier niveau les contient. Graph Paper donne son identifiant à chaque marqueur, et le lecteur peut le déplacer, changer son style et le supprimer, comme un marqueur placé à la main. Les données vont dans les lignes de séries ; les annotations vont dans les marqueurs. Un segment entre deux points de données est une série line, pas un marqueur.
Les coordonnées d'un marqueur sont des nombres, pas des formules : un marqueur ne bouge pas quand le lecteur change un curseur. Pour un point qui suit une variable, utilisez une ligne scatter avec une formule de point, par exemple "fn": "(0, A)". Pour un segment qui suit une variable, utilisez une ligne scatter dont le fn est une liste des deux points, avec "line": true et "points": false :
json{ "type": "scatter", "fn": "[(0, 0), (L\\sin(a), -L\\cos(a))]", "line": true, "points": false }
kindChampsDimension
pointx, y (et z en 3D)2D, 3D
labelx, y (et z en 3D), text2D, 3D
linex0, y0, x1, y1 (et z0, z1 en 3D) : un segment2D, 3D
ruleaxis ("x" ou "y"), value : une droite qui traverse le tracé2D
bandaxis ("x" ou "y"), from, to2D
rectx0, y0, x1, y12D
ellipsecx, cy, rx, ry (rayons, plus de 0), angle (facultatif, en degrés)2D
plane-bandaxis ("x", "y" ou "z"), from, to3D
Une droite avec "axis": "x" est une droite verticale en x = value. Une bande avec "axis": "x" couvre les valeurs de x de from à to. Les bornes d'une bande et d'un rectangle sont triées. Un marqueur d'un document 3D donne ses coordonnées z ; un marqueur d'un document 2D n'en donne aucune.
style (facultatif) règle l'aspect :
kindChamps de style
pointsymbol ("circle", "square", "diamond", "cross", "plus", "triangle"), size (pixels), fill, stroke (color, width)
labelcolor, fontSizeOffset (de −3 à 3), background
linestroke, arrowFrom, arrowTo (booléens : une pointe de flèche au début ou à la fin)
rulestroke
band, rect, ellipse, plane-bandfill, stroke (présent, même {} : un contour)
Un stroke est { "color", "width", "dash" }, tous facultatifs : width en pixels, dash une liste de longueurs comme [4, 4]. Une couleur est une couleur hexadécimale ("#1e88e5", ou "#1e88e533" avec de la transparence) ou "transparent".
Le text d'une étiquette a au plus 500 caractères. C'est du texte brut, avec du Markdown en ligne (**gras**, *italique*) et des maths en ligne entre $…$ ; un texte qui est un seul $…$ est une formule.
Règles :
json{ "title": "Annotated parabola", "series": [{ "type": "line", "fn": "x^2", "domain": [-2, 2] }], "markers": [ { "kind": "label", "x": 0, "y": 0.4, "text": "Vertex" }, { "kind": "line", "x0": 1, "y0": 3, "x1": 1.4, "y1": 2.1, "style": { "arrowTo": true, "stroke": { "width": 2 } } }, { "kind": "rule", "axis": "x", "value": 1.5 }, { "kind": "band", "axis": "y", "from": 1, "to": 2, "style": { "fill": "#1e88e533" } } ] }

Axes et scène

Ces champs sont tous facultatifs. S'ils sont absents, Graph Paper ajuste la vue aux séries.
domain (2D) :
ChampSignification
x.range, y.rangeL'intervalle visible d'un axe : { "x": { "range": [-5, 5] } }. Un axe n'a pas de champs min et max.
x.scale, y.scale"linear", "log", "symlog" ou "asinh".
aspect"equal" pour la même échelle sur les deux axes, "auto", ou un nombre.
coordinateSystem"cartesian" ou "polar".
Graph Paper garde l'intervalle de x et en déduit celui de y : l'étendue visible de y vaut l'étendue de x × aspect × (hauteur du tracé ÷ largeur du tracé), et y.range n'est que le minimum affiché, donc une fenêtre haute montre une plus grande partie de l'axe y. Pour montrer une plus petite partie de l'axe y, donnez à aspect un nombre plus petit, de 0,2 à 5 ("auto" vaut environ 0,618 pour une courbe et 1 pour un tracé implicite ou une carte de chaleur, "equal" vaut 1) ; avec un nombre, si y.range ne tient pas, c'est l'intervalle de x qui s'élargit.
stage (2D) : gridStyle vaut true, false, "lines", "dots" ou "isometric" ; frame vaut true ou false.
domain3d (3D) : x.range, y.range, z.range comme en 2D, et aspectMode, qui fixe la forme du cadre. "auto" (la valeur par défaut) et "cube" mettent chaque axe à l'échelle pour que le cadre soit un cube. "data" trace les trois axes à la même échelle, donc le cadre a les proportions des intervalles des axes (ou des séries, si aucun intervalle n'est donné).
stage3d (3D) : environment vaut "abstract", "outdoor" ou "paper" ; projection vaut "perspective" ou "orthographic" ; axes vaut true ou false ; camera vaut { "position": [x, y, z], "target": [x, y, z], "up": [0, 0, 1] }.
Les types de tracés acceptent plus de champs que cette page n'en décrit. Les champs ci-dessus sont ceux dont un document a le plus souvent besoin.

Modèles

Chaque modèle ci-dessous est un document complet et court. Partez de celui qui est le plus proche de ce que vous voulez. Les textes des exemples sont en anglais ; les liens sont les mêmes que sur la page anglaise.

Un point qui se déplace sur une courbe

Une ligne scatter avec une formule de point du curseur a trace un point sur la courbe, et le point bouge quand le lecteur fait glisser le curseur.
json{ "title": "A point on a parabola", "variables": [{ "name": "a", "value": "1", "domain": { "type": "range", "min": "-2", "max": "2" } }], "series": [ { "type": "line", "fn": "x^2", "domain": [-2.5, 2.5] }, { "type": "scatter", "fn": "(a, a^2)", "marker": { "size": 10 } } ] }

Un segment qui suit une variable

Une ligne scatter dont le fn est une liste de deux points, avec "line": true et "points": false, trace un segment, et ses extrémités peuvent être des formules.
json{ "title": "A segment that turns", "variables": [{ "name": "a", "value": "0.8", "domain": { "type": "range", "min": "0", "max": "6.28" } }], "series": [ { "type": "scatter", "fn": "[(0, 0), (\\cos(a), \\sin(a))]", "line": true, "points": false }, { "type": "scatter", "fn": "(\\cos(a), \\sin(a))" } ], "domain": { "aspect": "equal", "x": { "range": [-1.5, 1.5] }, "y": { "range": [-1.5, 1.5] } } }

Une fonction auxiliaire

Une définition avec des arguments, comme E_1(s) = …, est une fonction qu'une série peut appeler. E_1 et E_{1} sont le même nom. Une définition de fonction trace aussi sa courbe : "hidden": true la cache ici.
json{ "title": "A helper function", "variables": [{ "name": "c", "value": "0.5", "domain": { "type": "range", "min": "0", "max": "1" } }], "definitions": [{ "latex": "E_1(s) = e^{-cs}\\cos(4s)", "hidden": true }], "series": [{ "type": "line", "fn": "E_1(x)", "domain": [0, 10] }] }

Une famille de courbes à partir d'une liste

Une liste dans une définition, comme k = [1, 2, 3], donne une courbe pour chacune de ses valeurs.
json{ "title": "A family of sine curves", "definitions": ["k = [1, 2, 3]"], "series": [{ "type": "line", "fn": "\\sin(kx)", "domain": [0, 6.28] }] }

Une somme dont le nombre de termes vient d'un curseur

\sum_{k=0}^{n-1} additionne n termes, et n peut être un curseur. Un curseur qui compte des termes a besoin de "step": "1". Ici, la somme est la série de Fourier d'un signal carré, et la ligne en tirets est le signal carré.
json{ "title": "Square wave partial sum", "variables": [{ "name": "n", "value": "3", "domain": { "type": "range", "min": "1", "max": "25", "step": "1" } }], "series": [ { "type": "line", "fn": "\\frac{4}{\\pi}\\sum_{k=0}^{n-1}\\frac{\\sin((2k+1)x)}{2k+1}" }, { "type": "line", "fn": "\\operatorname{sign}(\\sin(x))", "stroke": { "dash": [4, 4] } } ], "domain": { "x": { "range": [-6.283, 6.283] }, "y": { "range": [-2, 2] } } }

Une simulation

Une action avec un interval et "autoplay": true change une variable avec une minuterie ; ici, le point fait le tour du cercle. Le pendule est un exemple plus long.
json{ "title": "A point that goes around", "variables": [{ "name": "a", "value": "0", "domain": { "type": "range", "min": "0", "max": "6.28" } }], "actions": [{ "latex": "a \\to \\operatorname{mod}(a + 0.05, 6.28)", "interval": "50", "autoplay": true }], "series": [ { "type": "parametric", "fn": "(\\cos(t), \\sin(t))", "domain": [0, 6.28] }, { "type": "scatter", "fn": "(\\cos(a), \\sin(a))", "marker": { "size": 10 } } ], "domain": { "aspect": "equal", "x": { "range": [-1.5, 1.5] }, "y": { "range": [-1.5, 1.5] } } }

Des données annotées

Une ligne line avec des données x et y trace les mesures, un marqueur label nomme un point, et un marqueur band colore un intervalle de x.
json{ "title": "Readings with notes", "series": [{ "type": "line", "x": [0, 1, 2, 3, 4], "y": [1, 3, 2, 5, 4] }], "markers": [ { "kind": "label", "x": 3, "y": 5.4, "text": "Peak" }, { "kind": "band", "axis": "x", "from": 1, "to": 2, "style": { "fill": "#1e88e533" } } ] }

Exemples complets

Les textes de ces exemples sont en anglais ; les liens sont les mêmes que sur la page anglaise.

Une courbe avec un curseur

Une oscillation amortie. La variable c est un curseur au repos, avec une note. La définition f est masquée, pour qu'elle ne trace pas une seconde courbe. La courbe en pointillés est l'enveloppe.
json{ "title": "Damped oscillation", "variables": [ { "name": "c", "value": "0.3", "domain": { "type": "range", "min": "0.05", "max": "1" }, "playback": { "mode": "bounce", "direction": "forward", "duration": 5000 }, "note": "The damping coefficient $c$. Drag the slider to change it." } ], "definitions": [{ "latex": "f(x) = e^{-c x} \\cos(6 x)", "hidden": true }], "series": [ { "type": "line", "fn": "f(x)", "domain": [0, 10] }, { "type": "line", "fn": "e^{-c x}", "domain": [0, 10], "stroke": { "dash": [4, 4] } } ], "domain": { "x": { "range": [0, 10] }, "y": { "range": [-1.2, 1.2] } } }

Une région implicite

Un disque que le lecteur déplace, sur la région située au-dessus d'une parabole. Le point (c_x, c_y) est le centre du disque.
json{ "title": "A disk above a parabola", "points": [ { "x": { "name": "c_x", "value": "0.5" }, "y": { "name": "c_y", "value": "1" }, "note": "The center of the disk. Drag it on the plot." } ], "series": [ { "type": "implicit", "fn": "y \\ge x^2 - 2", "domain": { "x": [-3, 3], "y": [-3, 3] }, "fill": "#90caf9" }, { "type": "implicit", "fn": "(x - c_x)^2 + (y - c_y)^2 \\le 1", "domain": { "x": [-3, 3], "y": [-3, 3] }, "color": "#c62828" } ], "domain": { "aspect": "equal" } }

Des mesures avec une droite de tendance

Six mesures, sous forme de données, et un ajustement linéaire avec son équation dans la légende. La série scatter a un id, et la série dérivée le nomme dans source.
json{ "title": "Readings with a trendline", "series": [ { "type": "scatter", "id": "readings", "x": [1, 2, 3, 4, 5, 6], "y": [2.1, 3.9, 6.2, 7.8, 10.1, 12.2], "name": "Readings" }, { "type": "derived", "source": "readings", "transform": { "kind": "trendline", "model": "linear" }, "legendEquation": true } ] }

Un champ mesuré

Une carte de chaleur de valeurs mesurées : 3 lignes (y = 0, 1, 2) de 4 valeurs (x = 0, 1, 2, 3). La valeur null est une case sans mesure, tracée comme un trou.
json{ "title": "Measured field", "series": [ { "type": "heatmap", "x": [0, 1, 2, 3], "y": [0, 1, 2], "z": [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, null, 6]], "color": "viridis", "name": "Temperature" } ] }

Une surface paramétrique 3D

Un tore.
json{ "title": "Torus", "series": [ { "type": "parametric-surface", "fn": "((2 + \\cos(v))\\cos(u), (2 + \\cos(v))\\sin(u), \\sin(v))", "domain": { "u": [0, 6.283185307179586], "v": [0, 6.283185307179586] }, "color": "viridis" } ], "stage3d": { "environment": "outdoor" }, "domain3d": { "aspectMode": "data" } }
"aspectMode": "data" trace les trois axes à la même échelle, donc le tore garde sa forme. Sans ce champ, le cadre est un cube, et le tore, haut de 2 unités et large de 6, est étiré en tonneau.

Une simulation avec une minuterie

Graph Paper n'a pas de ligne qui résout une équation différentielle. Un document peut tout de même simuler un mouvement : une action fait avancer l'état sur une minuterie.
Les limites :

Exemple : un pendule

Un pendule à grandes oscillations. L'équation du mouvement est a'' = -\frac{g}{L}\sin(a), où a est l'angle avec la verticale. L'état est l'angle a, la vitesse angulaire w et le temps T. La minuterie s'exécute toutes les 20 ms, et chaque exécution est un pas de h = 0.02 s :
w \to w - h\frac{g}{L}\sin(a), \quad a \to a + h\left(w - h\frac{g}{L}\sin(a)\right), \quad T \to T + h
La seconde action remet le pendule à l'angle de départ A, au repos. Le point rouge est la masse, le segment sombre est la tige (une ligne scatter de deux points reliés par une ligne), et le marqueur de point sombre est le pivot. Les curseurs ne bougent pas seuls : seule la minuterie change a, w et T. Le point gris suit la formule des petits angles a = A\cos(\sqrt{g/L}\,T), pour comparaison. Une grande oscillation dure plus longtemps que ne le prévoit la formule : avec un angle de départ de 2,5 radians, le point gris prend tout de suite de l'avance sur la masse.
Les textes de cet exemple sont en anglais ; le lien est le même que sur la page anglaise.
json{ "title": "Pendulum", "variables": [ { "name": "L", "value": "2", "domain": { "type": "range", "min": "0.5", "max": "3" }, "note": "The length $L$ of the rod, in meters." }, { "name": "A", "value": "2.5", "domain": { "type": "range", "min": "0.1", "max": "3.1" }, "note": "The start angle $A$, in radians from the vertical. Run **Reset** after you change it." }, { "name": "a", "value": "2.5", "domain": { "type": "range", "min": "-3.2", "max": "3.2" }, "note": "The state: the angle $a$, the angular velocity $w$ and the time $T$. The timer changes them." }, { "name": "w", "value": "0", "domain": { "type": "range", "min": "-8", "max": "8" } }, { "name": "T", "value": "0", "domain": { "type": "range", "min": "0", "max": "60" } } ], "definitions": [ { "latex": "g = 9.81", "note": "The gravity $g$, in m/s²." }, { "latex": "h = 0.02", "note": "The time step $h$, in seconds." } ], "actions": [ { "latex": "w \\to w - h\\frac{g}{L}\\sin(a), a \\to a + h\\left(w - h\\frac{g}{L}\\sin(a)\\right), T \\to T + h", "interval": "20", "autoplay": true, "note": "One step of the motion every 20 ms: first the new $w$, then the new $a$ from the new $w$." }, { "latex": "a \\to A, w \\to 0, T \\to 0", "note": "Reset: back to the start angle, at rest." } ], "series": [ { "type": "parametric", "fn": "(L\\cos(t), L\\sin(t))", "domain": [0, 6.283185307179586], "color": "#b0bec5", "stroke": { "dash": [4, 4] } }, { "type": "scatter", "fn": "[(0, 0), (L\\sin(a), -L\\cos(a))]", "line": true, "points": false, "color": "#455a64" }, { "type": "scatter", "fn": "(L\\sin(A\\cos(\\sqrt{g/L}T)), -L\\cos(A\\cos(\\sqrt{g/L}T)))", "color": "#90a4ae", "marker": { "size": 10 } }, { "type": "scatter", "fn": "(L\\sin(a), -L\\cos(a))", "color": "#c62828", "marker": { "size": 14 } } ], "markers": [ { "kind": "point", "x": 0, "y": 0, "style": { "fill": "#455a64", "size": 8 } } ], "domain": { "aspect": "equal", "x": { "range": [-3.5, 3.5] }, "y": { "range": [-3.5, 3.5] } } }

Vérifier un document

Un programme peut vérifier un document sans navigateur et sans compte :
La réponse est le lien qui ouvre le document, ou chaque erreur avec le chemin de son champ, comme series[0].fn. Les avertissements nomment les clés ignorées. La page Pour les agents montre les requêtes et les réponses.
La vérification porte sur les champs, leurs types et les limites de cette page. Elle ne trace pas le tracé. Une formule en LaTeX valide peut quand même ne rien tracer. Dites à la personne que vous n'avez pas vu le tracé, et préférez les formes de lignes que cette page montre.
Le service de liens vérifie seulement la structure. Graph Paper vérifie les formules à l'ouverture du lien, et signale les lignes qui ne fonctionnent pas : voir Quand la personne ouvre le lien sur la page Pour les agents.

Apprendre avec la Vitrine

Chaque page de la Vitrine contient son document sous la même forme, dans une balise <script type="application/graph-paper+json" id="gallery-entry">. Quand le document est grand, la balise ne contient que { "id": … } et un attribut data-payload-href qui donne l'URL du JSON complet.
Une entrée de la Vitrine n'est pas un document à envoyer tel quel. Elle a un id et pas de title, et ses valeurs note sont les noms de textes traduits, pas les textes. Pour en réutiliser une, retirez id, ajoutez un title, et remplacez ou retirez chaque note.

Les carnets

Graph Paper a aussi des carnets : des sections de texte, de formules, de calculs et de figures. C'est un autre format, et un lien /new ne peut pas les ouvrir. Leur référence est le format de fichier des carnets (en anglais), avec des schémas JSON pour le fichier d'export et le contenu du carnet.