prefig 0.3.8.dev20250725054648__py3-none-any.whl → 0.3.9.dev20250726054209__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -80,6 +80,17 @@ def rotate(v, theta):
80
80
  def deriv(f, a):
81
81
  return calculus.derivative(f, a)
82
82
 
83
+ def grad(f, a):
84
+ a = list(a)
85
+ grad = []
86
+ for j in range(len(a)):
87
+ def f_trace(x):
88
+ b = a[:]
89
+ b[j] = x
90
+ return f(*b)
91
+ grad.append(calculus.derivative(f_trace, a[j]))
92
+ return np.array(grad)
93
+
83
94
  def zip_lists(a, b):
84
95
  return list(zip(a, b))
85
96
 
prefig/core/polygon.py CHANGED
@@ -188,6 +188,9 @@ def spline(element, diagram, parent, outline_status):
188
188
 
189
189
  cs = CubicSpline(t_vals, points, bc_type=bc)
190
190
 
191
+ if element.get('name', None) is not None:
192
+ un.enter_function(element.get('name'), cs)
193
+
191
194
  N = un.valid_eval(element.get('N', '100'))
192
195
  domain = element.get('domain', None)
193
196
  if domain is not None:
@@ -11,6 +11,7 @@ from . import math_utilities as math_util
11
11
  from . import calculus
12
12
 
13
13
  log = logging.getLogger('prefigure')
14
+ np.seterr(divide="ignore", invalid="ignore")
14
15
 
15
16
  # Add a graphical element for slope fields
16
17
  def slope_field(element, diagram, parent, outline_status):
@@ -140,52 +141,87 @@ def vector_field(element, diagram, parent, outline_status):
140
141
  else:
141
142
  line_template.set('stroke', element.get('stroke', 'blue'))
142
143
  line_template.set('thickness', element.get('thickness', '2'))
143
- if element.get('arrows', 'yes') == 'yes':
144
- line_template.set('arrows', '1')
144
+ line_template.set('arrows', '1')
145
145
 
146
146
  if element.get('arrow-width', None) is not None:
147
147
  line_template.set('arrow-width', element.get('arrow-width'))
148
148
  if element.get('arrow-angles', None) is not None:
149
149
  line_template.set('arrow-angles', element.get('arrow-angles'))
150
150
 
151
- spacings = element.get('spacings', None)
152
- if spacings is not None:
151
+ field_data = []
152
+ if element.get('curve', None) is not None:
153
+ curve = un.valid_eval(element.get('curve'))
153
154
  try:
154
- spacings = un.valid_eval(spacings)
155
- rx, ry = spacings
155
+ domain = un.valid_eval(element.get('domain'))
156
156
  except:
157
- log.error(f"Error parsing slope-field attribute @spacings={element.get('spacings')}")
157
+ log.error('A @domain is needed if adding a vector field to a curve')
158
+ return
159
+ try:
160
+ N = un.valid_eval(element.get('N'))
161
+ except:
162
+ log.error('A @N is needed if adding a vector field to a curve')
158
163
  return
159
- else:
160
- rx = grid_axes.find_gridspacing((bbox[0], bbox[2]))
161
- ry = grid_axes.find_gridspacing((bbox[1], bbox[3]))
162
164
 
163
- # we will go through and generate the vectors first
164
- # since we'll need to scale them
165
- field_data = []
166
- max_scale = 0
167
- x = rx[0]
168
- while x <= rx[2]:
169
- y = ry[0]
170
- while y <= ry[2]:
171
- f_value = f(x, y)
165
+ t = domain[0]
166
+ # if "f" a function of t or (x,y)?
167
+ one_variable = True
168
+ try:
169
+ f(t)
170
+ except TypeError:
171
+ one_variable = False
172
+
173
+ dt = (domain[1]-domain[0])/(N-1)
174
+ for _ in range(N):
175
+ position = curve(t)
176
+ if one_variable:
177
+ field_data.append([position, f(t)])
178
+ else:
179
+ field_data.append([position, f(*position)])
180
+ t += dt
181
+ scale_factor = un.valid_eval(element.get('scale', '1'))
182
+
183
+ else:
184
+ spacings = element.get('spacings', None)
185
+ if spacings is not None:
172
186
  try:
173
- if len(f_value) != 2:
174
- log.error("Only two-dimensional vector fields are supported")
175
- return;
187
+ spacings = un.valid_eval(spacings)
188
+ rx, ry = spacings
176
189
  except:
177
- pass
178
- max_scale = max(max_scale,
179
- abs((f_value[0])/rx[1]),
180
- abs((f_value[1])/ry[1]))
181
- field_data.append([np.array([x,y]), f_value])
182
- y += ry[1]
183
- x += rx[1]
190
+ log.error(f"Error parsing slope-field attribute @spacings={element.get('spacings')}")
191
+ return
192
+ else:
193
+ rx = grid_axes.find_gridspacing((bbox[0], bbox[2]))
194
+ ry = grid_axes.find_gridspacing((bbox[1], bbox[3]))
195
+
196
+ # we will go through and generate the vectors first
197
+ # since we'll need to scale them
198
+ max_scale = 0
199
+ x = rx[0]
200
+ while x <= rx[2]:
201
+ y = ry[0]
202
+ while y <= ry[2]:
203
+ f_value = f(x, y)
204
+ if any(np.isnan(f_value)):
205
+ y += ry[1]
206
+ continue
184
207
 
185
- scale_factor = min(1, 0.75 / max_scale)
186
- if element.get('scale') is not None:
187
- scale = un.valid_eval(element.get('scale'))
188
- scale_factor = scale
208
+ try:
209
+ if len(f_value) != 2:
210
+ log.error("Only two-dimensional vector fields are supported")
211
+ return;
212
+ except:
213
+ pass
214
+ max_scale = max(max_scale,
215
+ abs((f_value[0])/rx[1]),
216
+ abs((f_value[1])/ry[1]))
217
+ field_data.append([np.array([x,y]), f_value])
218
+ y += ry[1]
219
+ x += rx[1]
220
+
221
+ scale_factor = min(1, 0.75 / max_scale)
222
+ if element.get('scale') is not None:
223
+ scale = un.valid_eval(element.get('scale'))
224
+ scale_factor = scale
189
225
 
190
226
  for datum in field_data:
191
227
  p, v = datum
@@ -205,18 +241,3 @@ def vector_field(element, diagram, parent, outline_status):
205
241
 
206
242
  group.group(element, diagram, parent, outline_status)
207
243
 
208
- def gradient(element, diagram, parent, outline_status):
209
- try:
210
- f = un.valid_eval(element.get("function"))
211
- except:
212
- log.error("Error retrieving function in gradient element")
213
- return
214
-
215
- def grad(a, b):
216
- f_x_trace = lambda x: f(x, b)
217
- f_y_trace = lambda y: f(a, y)
218
- return np.array([calculus.derivative(f_x_trace, a),
219
- calculus.derivative(f_y_trace, b)])
220
- un.enter_namespace("__grad", grad)
221
- element.set("function", "__grad")
222
- vector_field(element, diagram, parent, outline_status)
prefig/core/tags.py CHANGED
@@ -45,7 +45,6 @@ tag_dict = {
45
45
  'definition': definition.definition,
46
46
  'derivative': definition.derivative,
47
47
  'ellipse': circle.ellipse,
48
- 'gradient': slope_field.gradient,
49
48
  'graph': graph.graph,
50
49
  'grid': grid_axes.grid,
51
50
  'grid-axes': grid_axes.grid_axes,
@@ -170,6 +170,11 @@ def derivative(f, name):
170
170
  functions.add(name)
171
171
  variables.add(name)
172
172
 
173
+ def enter_function(name, f):
174
+ globals()[name] = f
175
+ functions.add(name)
176
+ variables.add(name)
177
+
173
178
  def enter_namespace(name, value):
174
179
  globals()[name] = value
175
180
  variables.add(name)
@@ -314,6 +314,7 @@ GraphicalElements =
314
314
  Axes* &
315
315
  Circle* &
316
316
  Ellipse* &
317
+ Gradient* &
317
318
  Graph* &
318
319
  Grid* &
319
320
  Grid-Axes* &
@@ -337,7 +338,8 @@ GraphicalElements =
337
338
  Tick-Mark* &
338
339
  Tangent-line* &
339
340
  Triangle* &
340
- Vector*
341
+ Vector* &
342
+ Vector-Field*
341
343
  )
342
344
 
343
345
  Angle-Marker = element angle-marker {
@@ -420,6 +422,34 @@ Axes = element axes {
420
422
  YLabel?
421
423
  }
422
424
 
425
+ Gradient = element gradient {
426
+ attribute at {text}?,
427
+ attribute function {text}?,
428
+ attribute spacings {text}?,
429
+ attribute scale {text}?,
430
+ attribute curve {text}?,
431
+ attribute domain {text}?,
432
+ attribute N {text}?,
433
+ attribute arrow-width {text}?,
434
+ attribute arrow-angles {text?}?,
435
+ StrokeAttributes,
436
+ CommonAttributes
437
+ }
438
+
439
+ Vector-Field = element vector-field {
440
+ attribute at {text}?,
441
+ attribute function {text}?,
442
+ attribute spacings {text}?,
443
+ attribute scale {text}?,
444
+ attribute curve {text}?,
445
+ attribute domain {text}?,
446
+ attribute N {text}?,
447
+ attribute arrow-width {text}?,
448
+ attribute arrow-angles {text?}?,
449
+ StrokeAttributes,
450
+ CommonAttributes
451
+ }
452
+
423
453
  Grid = element grid {
424
454
  attribute at {text}?,
425
455
  attribute spacings {text}?,
@@ -433,6 +463,7 @@ Grid = element grid {
433
463
  attribute coordinates {text}?,
434
464
  attribute spacing-degrees {"yes"|"no"}?,
435
465
  attribute scales {"linear"|"semilogx"|"semilogy"|"loglog"}?,
466
+ Stroke-Attributes,
436
467
  CommonAttributes
437
468
  }
438
469
 
@@ -457,6 +488,7 @@ Grid-Axes = element grid-axes {
457
488
  attribute h-zero-label {"yes"|"no"}?,
458
489
  attribute v-zero-label {"yes"|"no"}?,
459
490
  attribute label-commas {"yes"|"no"}?,
491
+ StrokeAttributes,
460
492
  CommonAttributes,
461
493
  XLabel?,
462
494
  YLabel?
@@ -469,6 +501,7 @@ Tick-Mark = element tick-mark {
469
501
  attribute stroke {text}?,
470
502
  attribute size {text}?,
471
503
  attribute thickness {text}?,
504
+ StrokeAttributes,
472
505
  LabelAttributes,
473
506
  LabelText?
474
507
  }
@@ -744,6 +777,7 @@ Spline = element spline {
744
777
  attribute closed {"yes"|"no"}?,
745
778
  attribute arrow-width {text}?,
746
779
  attribute arrow-angles {text}?,
780
+ attribute name {text}?,
747
781
  FillAttributes,
748
782
  CommonAttributes
749
783
  }
@@ -765,6 +765,9 @@
765
765
  <zeroOrMore>
766
766
  <ref name="Ellipse"/>
767
767
  </zeroOrMore>
768
+ <zeroOrMore>
769
+ <ref name="Gradient"/>
770
+ </zeroOrMore>
768
771
  <zeroOrMore>
769
772
  <ref name="Graph"/>
770
773
  </zeroOrMore>
@@ -837,6 +840,9 @@
837
840
  <zeroOrMore>
838
841
  <ref name="Vector"/>
839
842
  </zeroOrMore>
843
+ <zeroOrMore>
844
+ <ref name="Vector-Field"/>
845
+ </zeroOrMore>
840
846
  </interleave>
841
847
  </define>
842
848
  <define name="Angle-Marker">
@@ -1116,6 +1122,80 @@
1116
1122
  </optional>
1117
1123
  </element>
1118
1124
  </define>
1125
+ <define name="Gradient">
1126
+ <element name="gradient">
1127
+ <optional>
1128
+ <attribute name="at"/>
1129
+ </optional>
1130
+ <optional>
1131
+ <attribute name="function"/>
1132
+ </optional>
1133
+ <optional>
1134
+ <attribute name="spacings"/>
1135
+ </optional>
1136
+ <optional>
1137
+ <attribute name="scale"/>
1138
+ </optional>
1139
+ <optional>
1140
+ <attribute name="curve"/>
1141
+ </optional>
1142
+ <optional>
1143
+ <attribute name="domain"/>
1144
+ </optional>
1145
+ <optional>
1146
+ <attribute name="N"/>
1147
+ </optional>
1148
+ <optional>
1149
+ <attribute name="arrow-width"/>
1150
+ </optional>
1151
+ <optional>
1152
+ <attribute name="arrow-angles">
1153
+ <optional>
1154
+ <text/>
1155
+ </optional>
1156
+ </attribute>
1157
+ </optional>
1158
+ <ref name="StrokeAttributes"/>
1159
+ <ref name="CommonAttributes"/>
1160
+ </element>
1161
+ </define>
1162
+ <define name="Vector-Field">
1163
+ <element name="vector-field">
1164
+ <optional>
1165
+ <attribute name="at"/>
1166
+ </optional>
1167
+ <optional>
1168
+ <attribute name="function"/>
1169
+ </optional>
1170
+ <optional>
1171
+ <attribute name="spacings"/>
1172
+ </optional>
1173
+ <optional>
1174
+ <attribute name="scale"/>
1175
+ </optional>
1176
+ <optional>
1177
+ <attribute name="curve"/>
1178
+ </optional>
1179
+ <optional>
1180
+ <attribute name="domain"/>
1181
+ </optional>
1182
+ <optional>
1183
+ <attribute name="N"/>
1184
+ </optional>
1185
+ <optional>
1186
+ <attribute name="arrow-width"/>
1187
+ </optional>
1188
+ <optional>
1189
+ <attribute name="arrow-angles">
1190
+ <optional>
1191
+ <text/>
1192
+ </optional>
1193
+ </attribute>
1194
+ </optional>
1195
+ <ref name="StrokeAttributes"/>
1196
+ <ref name="CommonAttributes"/>
1197
+ </element>
1198
+ </define>
1119
1199
  <define name="Grid">
1120
1200
  <element name="grid">
1121
1201
  <optional>
@@ -1176,6 +1256,7 @@
1176
1256
  </choice>
1177
1257
  </attribute>
1178
1258
  </optional>
1259
+ <ref name="Stroke-Attributes"/>
1179
1260
  <ref name="CommonAttributes"/>
1180
1261
  </element>
1181
1262
  </define>
@@ -1291,6 +1372,7 @@
1291
1372
  </choice>
1292
1373
  </attribute>
1293
1374
  </optional>
1375
+ <ref name="StrokeAttributes"/>
1294
1376
  <ref name="CommonAttributes"/>
1295
1377
  <optional>
1296
1378
  <ref name="XLabel"/>
@@ -1318,6 +1400,7 @@
1318
1400
  <optional>
1319
1401
  <attribute name="thickness"/>
1320
1402
  </optional>
1403
+ <ref name="StrokeAttributes"/>
1321
1404
  <ref name="LabelAttributes"/>
1322
1405
  <optional>
1323
1406
  <ref name="LabelText"/>
@@ -2029,6 +2112,9 @@
2029
2112
  <optional>
2030
2113
  <attribute name="arrow-angles"/>
2031
2114
  </optional>
2115
+ <optional>
2116
+ <attribute name="name"/>
2117
+ </optional>
2032
2118
  <ref name="FillAttributes"/>
2033
2119
  <ref name="CommonAttributes"/>
2034
2120
  </element>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prefig
3
- Version: 0.3.8.dev20250725054648
3
+ Version: 0.3.9.dev20250726054209
4
4
  Summary: An authoring system for mathematical diagrams
5
5
  Home-page: https://prefigure.org
6
6
  License: GPL-3.0-or-later
@@ -22,23 +22,23 @@ prefig/core/label.py,sha256=e_gOd2kcdOtcJay1VyRstP66SiDNxK2UK2-obkxQnOc,24746
22
22
  prefig/core/label_tools.py,sha256=jOawiyrKC5iQs0vq7133xNXqrkJbMqDZVHflT-hOruo,9167
23
23
  prefig/core/legend.py,sha256=0mVfyU3LvqgDCYUOlCeBD04maV-rj2h0fs1aOEBBt6c,13340
24
24
  prefig/core/line.py,sha256=HBB9cvJawKAtdubISn5maRrzFFzV0NQuBgwoQoxeXcw,6055
25
- prefig/core/math_utilities.py,sha256=HyPUmCGhPYPaL52t4uOwLkY8bfTjwDIcDU8J6z7aW38,5644
25
+ prefig/core/math_utilities.py,sha256=nQV8RiZRvGgqAeatWwHKOHb107ZcLRgwa77CaXvUmCg,5892
26
26
  prefig/core/network.py,sha256=1izAX2AKvnj2knElrdLeojE_0Q0zO0aQM-EsEwor0Os,27217
27
27
  prefig/core/parametric_curve.py,sha256=ftxdg3gs0M0ME5iPJo3iEX7jT8PHQEMYpx8psr8Cm-w,3046
28
28
  prefig/core/parse.py,sha256=plLmR0KKrUjYx0PmHHo5HZonaaT3tW4qjiDOtzuhSkQ,4542
29
29
  prefig/core/path.py,sha256=ZWKUNgVU4qeU98Vp4WKpQoy7DehH1UmnyXA4DKRhpGo,19365
30
30
  prefig/core/point.py,sha256=a97N1soBcmYn3StZ60HBmaBi3pB1abA7sL0LNJ2nxR0,8341
31
- prefig/core/polygon.py,sha256=fh9l3XN4qxXGq9ZRskZv8yIXzGdHltIT8cI5ne_uf4o,11203
31
+ prefig/core/polygon.py,sha256=8NVdWSUVXuNE4GiPQ4MySSmLy8aCNwKUqCcfHukizME,11301
32
32
  prefig/core/read.py,sha256=Q1Nsluwysg3M5wtUmwIirfNo-Rw9-dFJPEeM4pDCpyo,1988
33
33
  prefig/core/rectangle.py,sha256=T0EMtRdLtmG1uY7Bu8kXmxQ81IGG_102g5fLCg9RuzE,3387
34
34
  prefig/core/repeat.py,sha256=DAO5w4BxUMGU-8ymsv8EwsifI0zPa_cgIRUcWWS8BWU,2755
35
35
  prefig/core/riemann_sum.py,sha256=T2dQgJIY17QuuPDOB8XWIP8HYmg5jOQ-LroFH7tiGAU,3012
36
36
  prefig/core/shape.py,sha256=Qb_-upbSHwEoYrrAnbCoFFFuVIb3JgJLdyP9ckD5evc,8675
37
- prefig/core/slope_field.py,sha256=ctkMFQ34ZFk-Hr9a8HkmKN-CUjWuZ0yutM4pN515wXk,7560
37
+ prefig/core/slope_field.py,sha256=MQgqwfsBNL4bZYqcpEif64gj7Xz6a1SSfcJPAYBZAE8,8231
38
38
  prefig/core/statistics.py,sha256=5qN_-ABN0EFVG12ZP95uSPk82INbWRqI3w2fUdR3wsw,3458
39
- prefig/core/tags.py,sha256=vsaoRMBuxWcTF6o2xlHFCu55EhGTcuJX3jEi6-N64T8,4086
39
+ prefig/core/tags.py,sha256=Y3LdH8KSEqIbjTrQLBOV56WMqGbjII-kEhtlEEIKSTQ,4048
40
40
  prefig/core/tangent_line.py,sha256=I9wf9VAqhnmmsh8Lzynwi7_Z1DonHXqHf8ym7eO40tk,3400
41
- prefig/core/user_namespace.py,sha256=t5D_diLDPQpfek8w7al_DWI6OlAMedgHoMg45DhPJAI,6878
41
+ prefig/core/user_namespace.py,sha256=73rV4iXICoh84xHCqBMTcIXNXGPQcPvTUEE8qFiSivM,6980
42
42
  prefig/core/utilities.py,sha256=R1fBrzj-abXHG4Bh-sS0pZNC8vc9fIt6yJBcuztCVho,2905
43
43
  prefig/core/vector.py,sha256=lTw-y9mt6jqmbFxdPwQB4PYBQ9y4pGrQRcpRp9lBIbY,2917
44
44
  prefig/engine.py,sha256=Zz7j2sFxeMwPN1f3GFTpaBihqguzMNJD5iBONOVL7eQ,11972
@@ -55,13 +55,13 @@ prefig/resources/examples/tangent.xml,sha256=FLZaNz0iFoTLX6gB4pfLZFtu_TWeCug4Dda
55
55
  prefig/resources/fonts/Braille29.ttf,sha256=T4hosDvaUGMVK0Wh0BmBgWeT7sQQmLXyA3gRUR-a0oE,55880
56
56
  prefig/resources/js/mj-sre-page.js,sha256=LHVeI4dCH13bTv56nz3SKNo3JGRXa6joPM3D3wpKV40,9251
57
57
  prefig/resources/js/package.json,sha256=hwKDg76_GzkhX72T7DRiF3FoMLokCv9PSLQvnW5Ovok,116
58
- prefig/resources/schema/pf_schema.rnc,sha256=K9CY2wKcsKEQo9S480Mnt7f-qckhUWt9AFRA7-PYNi8,19104
59
- prefig/resources/schema/pf_schema.rng,sha256=24kDLnXSWgBE1_I4TM5RR1I30XJo6Cq59rVC5ygSG_8,51821
58
+ prefig/resources/schema/pf_schema.rnc,sha256=33E_zj90OVa9xU6QXfBgJZwlPzaoNgtTYrAcp2uBEdk,19954
59
+ prefig/resources/schema/pf_schema.rng,sha256=YC9BYvLNa1OgHs3Y5fV_99NwbQaXTfKnAAhjE3L8tAE,53903
60
60
  prefig/resources/template/pf_publication.xml,sha256=eEv8HACv610Apw5DSVNy0reLfELYqHlNy9Oq0GH7C_c,200
61
61
  prefig/scripts/__init__.py,sha256=qJcPi1WRh9UAwu4zIFJbmxWalAMilMYqgi6LxRkF7bI,25
62
62
  prefig/scripts/install_mj.py,sha256=5A6-oc1xbIXka5mkFE70vlp9-Rh_QoxOxGMrQi9Hkio,1219
63
- prefig-0.3.8.dev20250725054648.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
64
- prefig-0.3.8.dev20250725054648.dist-info/METADATA,sha256=T3jXMcdrLim_prFihqU2ZP468zTdn_OLa1xOMG5PdTc,8728
65
- prefig-0.3.8.dev20250725054648.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
- prefig-0.3.8.dev20250725054648.dist-info/entry_points.txt,sha256=OP4ZQT71q2b0Zfbie-oM2Z1HlxpkuX7qaxJnzwsBOVQ,42
67
- prefig-0.3.8.dev20250725054648.dist-info/RECORD,,
63
+ prefig-0.3.9.dev20250726054209.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
64
+ prefig-0.3.9.dev20250726054209.dist-info/METADATA,sha256=dagV-ujiU-KtJOZKABw4eolGUmoOyUDvKI5O6uwmTvE,8728
65
+ prefig-0.3.9.dev20250726054209.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
+ prefig-0.3.9.dev20250726054209.dist-info/entry_points.txt,sha256=OP4ZQT71q2b0Zfbie-oM2Z1HlxpkuX7qaxJnzwsBOVQ,42
67
+ prefig-0.3.9.dev20250726054209.dist-info/RECORD,,