0
# Figures and Graphics
1
2
Figure environments, image inclusion, subfigures, and matplotlib integration for scientific and technical documents. PyLaTeX provides comprehensive support for incorporating graphics, from simple image inclusion to complex multi-panel figures and matplotlib plot integration.
3
4
## Capabilities
5
6
### Figure Environment
7
8
The Figure class creates floating figure environments that can be positioned automatically by LaTeX with captions and labels.
9
10
```python { .api }
11
class Figure(Float):
12
def __init__(self, position=None, **kwargs):
13
"""
14
Create a floating figure environment.
15
16
Parameters:
17
- position: str, float positioning ('h', 't', 'b', 'p', '!')
18
- 'h': here (at current position)
19
- 't': top of page
20
- 'b': bottom of page
21
- 'p': separate page
22
- '!': override LaTeX restrictions
23
"""
24
25
def add_image(self, filename, *, width=NoEscape(r"0.8\textwidth"),
26
placement=NoEscape(r"\centering")):
27
"""
28
Add an image to the figure.
29
30
Parameters:
31
- filename: str, path to image file
32
- width: str or NoEscape, image width specification
33
- placement: str or NoEscape, horizontal placement command
34
"""
35
36
def add_plot(self, *args, extension="pdf", **kwargs):
37
"""
38
Add current matplotlib plot to figure.
39
40
Parameters:
41
- *args: arguments passed to plt.savefig
42
- extension: str, image file format ('pdf', 'png', 'eps', 'svg')
43
- **kwargs: keyword arguments for plt.savefig and image placement
44
- width: image width in LaTeX
45
- placement: horizontal placement
46
"""
47
```
48
49
Usage example:
50
51
```python
52
from pylatex import Document, Section, NoEscape
53
from pylatex.figure import Figure
54
55
doc = Document()
56
57
with doc.create(Section('Results')):
58
# Basic figure with image
59
with doc.create(Figure(position='htbp')) as fig:
60
fig.add_image('path/to/image.png',
61
width=NoEscape(r'0.6\textwidth'))
62
fig.add_caption('Experimental results showing data trends.')
63
fig.append(Label('fig:results'))
64
65
# Figure with custom sizing
66
with doc.create(Figure(position='H')) as fig: # Force position with 'H'
67
fig.add_image('diagram.pdf',
68
width=NoEscape(r'12cm'))
69
fig.add_caption('System architecture diagram.')
70
```
71
72
### Matplotlib Integration
73
74
PyLaTeX seamlessly integrates with matplotlib for programmatic figure generation.
75
76
```python
77
import matplotlib.pyplot as plt
78
import numpy as np
79
from pylatex import Document, Section
80
from pylatex.figure import Figure
81
82
doc = Document()
83
84
# Generate matplotlib plot
85
x = np.linspace(0, 10, 100)
86
y = np.sin(x)
87
88
plt.figure(figsize=(8, 6))
89
plt.plot(x, y, 'b-', label='sin(x)')
90
plt.xlabel('x')
91
plt.ylabel('y')
92
plt.title('Sine Wave')
93
plt.legend()
94
plt.grid(True)
95
96
with doc.create(Section('Analysis')):
97
with doc.create(Figure(position='htbp')) as fig:
98
# Add current plot to figure
99
fig.add_plot(dpi=300, width=NoEscape(r'0.8\textwidth'))
100
fig.add_caption('Sine wave analysis.')
101
102
# Multiple plots
103
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
104
105
ax1.plot(x, np.sin(x))
106
ax1.set_title('Sine')
107
108
ax2.plot(x, np.cos(x))
109
ax2.set_title('Cosine')
110
111
plt.tight_layout()
112
113
with doc.create(Figure()) as fig:
114
fig.add_plot(bbox_inches='tight')
115
fig.add_caption('Comparison of sine and cosine functions.')
116
```
117
118
### SubFigure Environment
119
120
The SubFigure class enables creation of multi-panel figures with individual captions.
121
122
```python { .api }
123
class SubFigure(Figure):
124
def __init__(self, width=NoEscape(r"0.45\linewidth"), **kwargs):
125
"""
126
Create a subfigure within a figure environment.
127
128
Parameters:
129
- width: str or NoEscape, subfigure width
130
- **kwargs: additional arguments passed to Figure
131
132
Requires:
133
- subcaption package (automatically added)
134
"""
135
```
136
137
Usage example:
138
139
```python
140
from pylatex import Document, Section, NoEscape
141
from pylatex.figure import Figure, SubFigure
142
import matplotlib.pyplot as plt
143
import numpy as np
144
145
doc = Document()
146
147
with doc.create(Section('Comparative Analysis')):
148
with doc.create(Figure(position='htbp')) as fig:
149
# First subplot
150
with doc.create(SubFigure(width=NoEscape(r'0.45\textwidth'))) as subfig:
151
x = np.linspace(0, 10, 100)
152
plt.figure(figsize=(6, 4))
153
plt.plot(x, np.sin(x), 'r-')
154
plt.title('Function A')
155
subfig.add_plot()
156
subfig.add_caption('Sine wave')
157
158
# Add horizontal space
159
fig.append(NoEscape(r'\hfill'))
160
161
# Second subplot
162
with doc.create(SubFigure(width=NoEscape(r'0.45\textwidth'))) as subfig:
163
plt.figure(figsize=(6, 4))
164
plt.plot(x, np.cos(x), 'b-')
165
plt.title('Function B')
166
subfig.add_plot()
167
subfig.add_caption('Cosine wave')
168
169
# Overall caption
170
fig.add_caption('Comparison of trigonometric functions.')
171
172
# Three-panel figure
173
with doc.create(Figure(position='htbp')) as fig:
174
for i, (func, name, color) in enumerate([(np.sin, 'Sine', 'red'),
175
(np.cos, 'Cosine', 'blue'),
176
(np.tan, 'Tangent', 'green')]):
177
with doc.create(SubFigure(width=NoEscape(r'0.32\textwidth'))) as subfig:
178
plt.figure(figsize=(4, 3))
179
x = np.linspace(0, 2*np.pi, 100)
180
plt.plot(x, func(x), color=color)
181
plt.title(name)
182
subfig.add_plot()
183
subfig.add_caption(f'{name} function')
184
185
if i < 2: # Add space between subfigures
186
fig.append(NoEscape(r'\hfill'))
187
188
fig.add_caption('Trigonometric functions comparison.')
189
```
190
191
### Standalone Graphics
192
193
The StandAloneGraphic class provides direct image inclusion without float environments.
194
195
```python { .api }
196
class StandAloneGraphic(UnsafeCommand):
197
def __init__(self, filename, image_options=NoEscape(r"width=0.8\textwidth"),
198
extra_arguments=None):
199
"""
200
Include graphics directly without figure environment.
201
202
Parameters:
203
- filename: str, path to image file
204
- image_options: str or NoEscape, includegraphics options
205
- extra_arguments: additional command arguments
206
207
Requires:
208
- graphicx package (automatically added)
209
"""
210
```
211
212
Usage example:
213
214
```python
215
from pylatex import Document, Section, NoEscape
216
from pylatex.figure import StandAloneGraphic
217
218
doc = Document()
219
220
with doc.create(Section('Gallery')):
221
doc.append('Here is an inline image: ')
222
223
# Direct image inclusion
224
doc.append(StandAloneGraphic('logo.png',
225
image_options=NoEscape(r'width=2cm')))
226
227
doc.append(' within the text.')
228
229
# Centered image without float
230
doc.append(NoEscape(r'\begin{center}'))
231
doc.append(StandAloneGraphic('banner.jpg',
232
image_options=NoEscape(r'width=\textwidth')))
233
doc.append(NoEscape(r'\end{center}'))
234
```
235
236
## Advanced Figure Layouts
237
238
### Complex Multi-Panel Figures
239
240
```python
241
from pylatex import Document, Section, NoEscape, Command
242
from pylatex.figure import Figure, SubFigure
243
import matplotlib.pyplot as plt
244
import numpy as np
245
246
doc = Document()
247
248
with doc.create(Section('Experimental Results')):
249
with doc.create(Figure(position='htbp')) as fig:
250
# 2x2 grid of subfigures
251
data_sets = [
252
(lambda x: x**2, 'Quadratic', 'red'),
253
(lambda x: x**3, 'Cubic', 'blue'),
254
(lambda x: np.exp(x), 'Exponential', 'green'),
255
(lambda x: np.log(x), 'Logarithmic', 'orange')
256
]
257
258
for i, (func, name, color) in enumerate(data_sets):
259
width = NoEscape(r'0.48\textwidth')
260
261
with doc.create(SubFigure(width=width)) as subfig:
262
plt.figure(figsize=(5, 4))
263
x = np.linspace(0.1, 5, 100) if name == 'Logarithmic' else np.linspace(0, 5, 100)
264
y = func(x)
265
plt.plot(x, y, color=color, linewidth=2)
266
plt.title(f'{name} Function')
267
plt.xlabel('x')
268
plt.ylabel('f(x)')
269
plt.grid(True, alpha=0.3)
270
subfig.add_plot(bbox_inches='tight', dpi=300)
271
subfig.add_caption(f'{name} growth pattern')
272
273
# Add spacing and line breaks
274
if i % 2 == 0: # After first and third subfigures
275
fig.append(NoEscape(r'\hfill'))
276
elif i == 1: # After second subfigure
277
fig.append(NoEscape(r'\\[1em]'))
278
279
fig.add_caption('Comparison of different mathematical functions showing various growth patterns.')
280
```
281
282
### Figure with Annotations
283
284
```python
285
from pylatex import Document, Command, NoEscape
286
from pylatex.figure import Figure
287
288
doc = Document()
289
290
# Add tikz package for annotations
291
doc.packages.append(Package('tikz'))
292
doc.packages.append(Package('tikz', options=['remember picture', 'overlay']))
293
294
with doc.create(Figure(position='htbp')) as fig:
295
fig.add_image('schematic.png', width=NoEscape(r'0.8\textwidth'))
296
297
# Add tikz overlay for annotations
298
fig.append(NoEscape(r'\begin{tikzpicture}[remember picture, overlay]'))
299
fig.append(NoEscape(r'\node[red, font=\Large] at (2, 1) {Input};'))
300
fig.append(NoEscape(r'\node[blue, font=\Large] at (6, 1) {Output};'))
301
fig.append(NoEscape(r'\draw[red, thick, ->] (2, 0.5) -- (6, 0.5);'))
302
fig.append(NoEscape(r'\end{tikzpicture}'))
303
304
fig.add_caption('System schematic with flow annotations.')
305
```
306
307
## Image Format Support
308
309
### Supported File Types
310
311
PyLaTeX supports various image formats through LaTeX's graphicx package:
312
313
- **Vector formats**: PDF, EPS, SVG (with inkscape)
314
- **Raster formats**: PNG, JPG, TIFF
315
- **LaTeX native**: TikZ, PGF plots
316
317
```python
318
from pylatex import Document, Package
319
from pylatex.figure import Figure
320
321
doc = Document()
322
323
# Enable additional graphics support
324
doc.packages.append(Package('graphicx'))
325
doc.packages.append(Package('epstopdf')) # Automatic EPS to PDF conversion
326
327
with doc.create(Figure()) as fig:
328
# Vector graphics (recommended for scalability)
329
fig.add_image('plot.pdf') # PDF graphics
330
fig.add_image('diagram.eps') # EPS graphics
331
332
# Raster graphics
333
fig.add_image('photo.jpg', width=NoEscape(r'0.5\textwidth'))
334
fig.add_image('screenshot.png', width=NoEscape(r'10cm'))
335
```
336
337
### Image Path Management
338
339
```python
340
from pylatex import Document, Command, NoEscape
341
from pylatex.utils import fix_filename
342
343
doc = Document()
344
345
# Set graphics path for all images
346
doc.preamble.append(Command('graphicspath', arguments=NoEscape(r'{{./images/}}')))
347
348
# Fix problematic filenames
349
safe_filename = fix_filename('image with spaces & symbols.jpg')
350
351
with doc.create(Figure()) as fig:
352
fig.add_image(safe_filename)
353
fig.add_caption('Image with cleaned filename.')
354
```
355
356
## Figure Positioning and Control
357
358
### Positioning Options
359
360
```python
361
from pylatex import Document, Package
362
from pylatex.figure import Figure
363
364
doc = Document()
365
doc.packages.append(Package('float')) # For 'H' option
366
367
# Different positioning strategies
368
positions = [
369
('htbp', 'Standard float positioning'),
370
('H', 'Force exact position (requires float package)'),
371
('!htbp', 'Override LaTeX restrictions'),
372
('t', 'Top of page only'),
373
('b', 'Bottom of page only')
374
]
375
376
for pos, description in positions:
377
with doc.create(Figure(position=pos)) as fig:
378
fig.add_image('example.png')
379
fig.add_caption(f'{description} (position={pos})')
380
```
381
382
### Figure Spacing and Alignment
383
384
```python
385
from pylatex import Document, NoEscape, Command
386
from pylatex.figure import Figure
387
388
doc = Document()
389
390
# Adjust float parameters
391
doc.preamble.append(Command('setcounter', arguments=['topnumber', '3']))
392
doc.preamble.append(Command('renewcommand', arguments=[NoEscape(r'\topfraction'), '.75']))
393
doc.preamble.append(Command('setcounter', arguments=['bottomnumber', '2']))
394
doc.preamble.append(Command('renewcommand', arguments=[NoEscape(r'\bottomfraction'), '.75']))
395
396
with doc.create(Figure()) as fig:
397
# Custom alignment
398
fig.append(NoEscape(r'\centering'))
399
fig.add_image('centered.png')
400
401
# Adjust spacing around image
402
fig.append(NoEscape(r'\vspace{1em}'))
403
fig.add_caption('Figure with custom spacing.')
404
```
405
406
## Integration with Scientific Workflows
407
408
### Automated Figure Generation
409
410
```python
411
import matplotlib.pyplot as plt
412
import numpy as np
413
from pylatex import Document, Section
414
from pylatex.figure import Figure
415
416
def generate_analysis_plots(data_sets, output_doc):
417
"""Generate standardized analysis plots."""
418
419
with output_doc.create(Section('Data Analysis')) as section:
420
for i, (data, title) in enumerate(data_sets):
421
# Create matplotlib figure
422
plt.figure(figsize=(10, 6))
423
424
# Plot data
425
plt.subplot(1, 2, 1)
426
plt.plot(data['x'], data['y'], 'bo-')
427
plt.title(f'{title} - Raw Data')
428
plt.xlabel('X Values')
429
plt.ylabel('Y Values')
430
plt.grid(True)
431
432
# Plot analysis
433
plt.subplot(1, 2, 2)
434
plt.hist(data['y'], bins=20, alpha=0.7)
435
plt.title(f'{title} - Distribution')
436
plt.xlabel('Y Values')
437
plt.ylabel('Frequency')
438
439
plt.tight_layout()
440
441
# Add to document
442
with output_doc.create(Figure(position='htbp')) as fig:
443
fig.add_plot(dpi=300, bbox_inches='tight')
444
fig.add_caption(f'Analysis of {title.lower()} dataset.')
445
446
# Usage
447
doc = Document()
448
datasets = [
449
({'x': np.linspace(0, 10, 50), 'y': np.random.normal(0, 1, 50)}, 'Dataset A'),
450
({'x': np.linspace(0, 10, 50), 'y': np.random.exponential(2, 50)}, 'Dataset B')
451
]
452
453
generate_analysis_plots(datasets, doc)
454
```
455
456
## Package Dependencies
457
458
Figure-related functionality requires specific LaTeX packages:
459
460
- **Basic images**: `graphicx` package (automatically added)
461
- **Subfigures**: `subcaption` package (automatically added with SubFigure)
462
- **Force positioning**: `float` package (for 'H' option)
463
- **EPS support**: `epstopdf` package for automatic conversion
464
465
```python
466
from pylatex import Document, Package
467
468
doc = Document()
469
470
# Common figure packages
471
doc.packages.append(Package('graphicx'))
472
doc.packages.append(Package('float'))
473
doc.packages.append(Package('subcaption'))
474
doc.packages.append(Package('caption', options=['font=small', 'labelfont=bf']))
475
```
476
477
The figure system in PyLaTeX provides professional-quality image handling with seamless integration between programmatic plot generation and LaTeX document composition.