0
# Physical Quantities and Units
1
2
Scientific notation and unit handling with SIunits integration for proper typesetting of measurements and quantities. PyLaTeX provides seamless integration with Python's quantities package and LaTeX's siunitx package for professional scientific notation, unit formatting, and uncertainty representation.
3
4
## Capabilities
5
6
### Quantity Class
7
8
The Quantity class converts Python quantity objects into properly formatted LaTeX output using the siunitx package.
9
10
```python { .api }
11
class Quantity(Command):
12
def __init__(self, quantity, *, options=None, format_cb=None):
13
"""
14
Create properly formatted physical quantities with units.
15
16
Parameters:
17
- quantity: quantities.Quantity, UncertainQuantity, or numeric value
18
- options: dict, str, list, or Options, siunitx formatting options
19
- format_cb: callable, custom number formatting function (default: numpy.array_str)
20
21
Requires:
22
- siunitx package (automatically added)
23
- quantities Python package for quantity objects
24
25
Examples:
26
- Simple quantity: Quantity(3.14159 * meter / second)
27
- With uncertainty: Quantity(UncertainQuantity(16.0, meter, 0.3))
28
- Plain number: Quantity(6.022e23)
29
"""
30
```
31
32
Usage example:
33
34
```python
35
from pylatex import Document, Section
36
from pylatex.quantities import Quantity
37
import quantities as pq
38
39
doc = Document()
40
41
with doc.create(Section('Physical Measurements')):
42
# Basic quantities with units
43
speed = 299792458 * pq.meter / pq.second
44
doc.append('Speed of light: ')
45
doc.append(Quantity(speed, options={'round-precision': 4, 'round-mode': 'figures'}))
46
47
# Force measurement
48
force = 9.81 * pq.newton
49
doc.append(' Force: ')
50
doc.append(Quantity(force))
51
52
# Energy calculation
53
mass = 2.5 * pq.kilogram
54
energy = 0.5 * mass * (10 * pq.meter/pq.second)**2
55
doc.append(' Kinetic energy: ')
56
doc.append(Quantity(energy))
57
```
58
59
### Uncertainty Handling
60
61
Automatic formatting of measurements with uncertainties using proper scientific notation.
62
63
```python
64
from pylatex import Document, Section
65
from pylatex.quantities import Quantity
66
import quantities as pq
67
68
doc = Document()
69
70
with doc.create(Section('Experimental Results')):
71
# Measurements with uncertainties
72
length = pq.UncertainQuantity(16.0, pq.meter, 0.3)
73
width = pq.UncertainQuantity(12.5, pq.meter, 0.2)
74
75
doc.append('Length: ')
76
doc.append(Quantity(length))
77
doc.append(' Width: ')
78
doc.append(Quantity(width))
79
80
# Calculated quantities with error propagation
81
area = length * width
82
doc.append(' Area: ')
83
doc.append(Quantity(area))
84
85
# Temperature measurements
86
temp = pq.UncertainQuantity(23.5, pq.celsius, 0.1)
87
doc.append(' Temperature: ')
88
doc.append(Quantity(temp))
89
```
90
91
### Scientific Notation for Numbers
92
93
Format large numbers and scientific notation without units.
94
95
```python
96
from pylatex import Document, Section
97
from pylatex.quantities import Quantity
98
99
doc = Document()
100
101
with doc.create(Section('Scientific Constants')):
102
# Avogadro's number
103
avogadro = 6.022140857e23
104
doc.append('Avogadro constant: ')
105
doc.append(Quantity(avogadro, options={'round-precision': 4}))
106
107
# Planck constant
108
planck = 6.62607015e-34
109
doc.append(' Planck constant: ')
110
doc.append(Quantity(planck, options={'scientific-notation': True}))
111
112
# Very small number
113
small_number = 1.234e-12
114
doc.append(' Small measurement: ')
115
doc.append(Quantity(small_number, options={'round-precision': 3, 'round-mode': 'figures'}))
116
```
117
118
## Advanced Quantity Formatting
119
120
### Custom Formatting Options
121
122
Control the appearance of quantities using siunitx options.
123
124
```python
125
from pylatex import Document, Section
126
from pylatex.quantities import Quantity
127
import quantities as pq
128
129
doc = Document()
130
131
with doc.create(Section('Formatting Examples')):
132
value = 1234.5678 * pq.meter
133
134
# Different rounding modes
135
doc.append('Default: ')
136
doc.append(Quantity(value))
137
doc.append(' Rounded to 2 places: ')
138
doc.append(Quantity(value, options={'round-precision': 2, 'round-mode': 'places'}))
139
doc.append(' 3 significant figures: ')
140
doc.append(Quantity(value, options={'round-precision': 3, 'round-mode': 'figures'}))
141
142
# Scientific notation control
143
large_value = 123456789 * pq.joule
144
doc.append(' Scientific notation: ')
145
doc.append(Quantity(large_value, options={'scientific-notation': True}))
146
doc.append(' Fixed notation: ')
147
doc.append(Quantity(large_value, options={'scientific-notation': False}))
148
```
149
150
### Unit Formatting and Combinations
151
152
Handle complex unit combinations and formatting preferences.
153
154
```python
155
from pylatex import Document, Section, Package
156
from pylatex.quantities import Quantity
157
import quantities as pq
158
159
doc = Document()
160
161
# Configure siunitx options globally
162
doc.packages.append(Package('siunitx', options=[
163
'per-mode=symbol',
164
'group-separator={,}',
165
'output-decimal-marker={.}'
166
]))
167
168
with doc.create(Section('Complex Units')):
169
# Velocity
170
velocity = 15.5 * pq.meter / pq.second
171
doc.append('Velocity: ')
172
doc.append(Quantity(velocity))
173
174
# Acceleration
175
acceleration = 9.81 * pq.meter / (pq.second**2)
176
doc.append(' Acceleration: ')
177
doc.append(Quantity(acceleration))
178
179
# Power
180
power = 750 * pq.watt
181
doc.append(' Power: ')
182
doc.append(Quantity(power))
183
184
# Pressure
185
pressure = 101325 * pq.pascal
186
doc.append(' Pressure: ')
187
doc.append(Quantity(pressure, options={'per-mode': 'fraction'}))
188
189
# Density
190
density = 1000 * pq.kilogram / (pq.meter**3)
191
doc.append(' Density: ')
192
doc.append(Quantity(density))
193
```
194
195
### Custom Number Formatting
196
197
Implement custom formatting functions for specialized number presentation.
198
199
```python
200
from pylatex import Document, Section
201
from pylatex.quantities import Quantity
202
import quantities as pq
203
import numpy as np
204
205
doc = Document()
206
207
def engineering_format(value):
208
"""Format numbers in engineering notation (powers of 1000)."""
209
if value == 0:
210
return "0"
211
212
exponent = int(np.floor(np.log10(abs(value)) / 3) * 3)
213
mantissa = value / (10 ** exponent)
214
215
if exponent == 0:
216
return f"{mantissa:.3f}"
217
else:
218
return f"{mantissa:.3f}e{exponent:+d}"
219
220
def percent_format(value):
221
"""Format as percentage with 1 decimal place."""
222
return f"{value:.1f}"
223
224
with doc.create(Section('Custom Formatting')):
225
# Engineering notation
226
resistance = 47000 * pq.ohm
227
doc.append('Resistance: ')
228
doc.append(Quantity(resistance, format_cb=engineering_format))
229
230
# Percentage format for efficiency
231
efficiency = 0.856
232
doc.append(' Efficiency: ')
233
doc.append(Quantity(efficiency * 100, format_cb=percent_format))
234
doc.append('%')
235
236
# Custom precision for angles
237
angle = np.pi / 4 * pq.radian
238
doc.append(' Angle: ')
239
doc.append(Quantity(angle, format_cb=lambda x: f"{x:.4f}"))
240
```
241
242
## Integration with Calculations
243
244
### Experimental Data Analysis
245
246
```python
247
from pylatex import Document, Section, Subsection
248
from pylatex.quantities import Quantity
249
from pylatex.table import Tabular, Table
250
import quantities as pq
251
import numpy as np
252
253
doc = Document()
254
255
with doc.create(Section('Experimental Analysis')):
256
# Sample experimental data
257
measurements = [
258
pq.UncertainQuantity(12.3, pq.meter, 0.1),
259
pq.UncertainQuantity(12.5, pq.meter, 0.1),
260
pq.UncertainQuantity(12.1, pq.meter, 0.1),
261
pq.UncertainQuantity(12.4, pq.meter, 0.1),
262
pq.UncertainQuantity(12.2, pq.meter, 0.1)
263
]
264
265
with doc.create(Subsection('Raw Data')):
266
with doc.create(Table(position='htbp')) as table:
267
table.add_caption('Length Measurements')
268
269
with table.create(Tabular('cc')) as tabular:
270
tabular.add_row(['Trial', 'Length'])
271
tabular.add_hline()
272
273
for i, measurement in enumerate(measurements, 1):
274
tabular.add_row([str(i), Quantity(measurement)])
275
276
with doc.create(Subsection('Statistical Analysis')):
277
# Calculate statistics
278
values = [m.magnitude for m in measurements]
279
mean_value = np.mean(values)
280
std_value = np.std(values, ddof=1)
281
282
mean_quantity = pq.UncertainQuantity(mean_value, pq.meter, std_value/np.sqrt(len(values)))
283
284
doc.append('Mean length: ')
285
doc.append(Quantity(mean_quantity, options={'round-precision': 3}))
286
287
doc.append(' Standard deviation: ')
288
doc.append(Quantity(std_value * pq.meter, options={'round-precision': 3}))
289
```
290
291
### Unit Conversions and Calculations
292
293
```python
294
from pylatex import Document, Section
295
from pylatex.quantities import Quantity
296
from pylatex.math import Math
297
import quantities as pq
298
299
doc = Document()
300
301
with doc.create(Section('Physics Calculations')):
302
# Kinematic calculation
303
initial_velocity = 0 * pq.meter / pq.second
304
acceleration = 9.81 * pq.meter / (pq.second**2)
305
time = 3.5 * pq.second
306
307
# Calculate final velocity: v = v₀ + at
308
final_velocity = initial_velocity + acceleration * time
309
310
doc.append('Initial velocity: ')
311
doc.append(Quantity(initial_velocity))
312
doc.append(' Acceleration: ')
313
doc.append(Quantity(acceleration))
314
doc.append(' Time: ')
315
doc.append(Quantity(time))
316
doc.append(' Final velocity: ')
317
doc.append(Quantity(final_velocity))
318
319
# Distance calculation: s = v₀t + ½at²
320
distance = initial_velocity * time + 0.5 * acceleration * (time**2)
321
doc.append(' Distance traveled: ')
322
doc.append(Quantity(distance))
323
324
# Energy calculations
325
mass = 2.5 * pq.kilogram
326
kinetic_energy = 0.5 * mass * (final_velocity**2)
327
potential_energy = mass * acceleration * distance
328
329
doc.append(' Kinetic energy: ')
330
doc.append(Quantity(kinetic_energy))
331
doc.append(' Potential energy: ')
332
doc.append(Quantity(potential_energy))
333
```
334
335
### Multi-Unit Systems
336
337
```python
338
from pylatex import Document, Section
339
from pylatex.quantities import Quantity
340
import quantities as pq
341
342
doc = Document()
343
344
with doc.create(Section('Unit Systems Comparison')):
345
# Same quantity in different units
346
distance_m = 1000 * pq.meter
347
distance_km = distance_m.rescale(pq.kilometer)
348
distance_mile = distance_m.rescale(pq.mile)
349
350
doc.append('Distance in meters: ')
351
doc.append(Quantity(distance_m))
352
doc.append(' In kilometers: ')
353
doc.append(Quantity(distance_km))
354
doc.append(' In miles: ')
355
doc.append(Quantity(distance_mile, options={'round-precision': 2}))
356
357
# Temperature conversions
358
temp_c = 25 * pq.celsius
359
temp_f = temp_c.rescale(pq.fahrenheit)
360
temp_k = temp_c.rescale(pq.kelvin)
361
362
doc.append(' Temperature in Celsius: ')
363
doc.append(Quantity(temp_c))
364
doc.append(' Fahrenheit: ')
365
doc.append(Quantity(temp_f))
366
doc.append(' Kelvin: ')
367
doc.append(Quantity(temp_k))
368
```
369
370
## Package Configuration
371
372
### Global SIunitx Settings
373
374
Configure siunitx package options for consistent formatting throughout the document.
375
376
```python
377
from pylatex import Document, Package, NoEscape, Command
378
from pylatex.quantities import Quantity
379
380
doc = Document()
381
382
# Configure siunitx globally
383
doc.packages.append(Package('siunitx', options=[
384
'separate-uncertainty=true',
385
'multi-part-units=single',
386
'bracket-numbers=false',
387
'per-mode=symbol',
388
'group-separator={,}',
389
'group-minimum-digits=4',
390
'round-mode=figures',
391
'round-precision=3'
392
]))
393
394
# Add custom units
395
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\rpm'), 'rpm']))
396
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\ppm'), 'ppm']))
397
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\year'), 'year']))
398
```
399
400
### Unit Name Translations
401
402
Handle unit name differences between Python quantities and siunitx.
403
404
```python
405
# The UNIT_NAME_TRANSLATIONS dictionary in quantities.py handles conversions:
406
UNIT_NAME_TRANSLATIONS = {
407
"Celsius": "celsius",
408
"revolutions_per_minute": "rpm",
409
"v": "volt",
410
# Add custom translations as needed
411
}
412
413
# Custom units can be added to the document
414
from pylatex import Document, Command, NoEscape
415
416
doc = Document()
417
418
# Define custom units in preamble
419
custom_units = [
420
(r'\rpm', 'rpm'),
421
(r'\ppm', 'ppm'),
422
(r'\percent', r'\%'),
423
(r'\year', 'year'),
424
(r'\bit', 'bit'),
425
(r'\byte', 'B')
426
]
427
428
for unit_command, unit_name in custom_units:
429
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(unit_command), unit_name]))
430
```
431
432
## Error Handling and Validation
433
434
### Handling Invalid Units
435
436
```python
437
from pylatex import Document, Section
438
from pylatex.quantities import Quantity
439
import quantities as pq
440
441
doc = Document()
442
443
try:
444
# This might fail if the unit isn't recognized
445
custom_measurement = 42 * pq.meter # This should work
446
doc.append(Quantity(custom_measurement))
447
448
except Exception as e:
449
doc.append(f"Error formatting quantity: {e}")
450
451
# Fallback for unsupported units
452
def safe_quantity(value, unit=None, **options):
453
"""Safely create quantity with fallback formatting."""
454
try:
455
if unit is not None:
456
return Quantity(value * unit, **options)
457
else:
458
return Quantity(value, **options)
459
except Exception:
460
# Fallback to plain number
461
return str(value) + (f" {unit}" if unit else "")
462
```
463
464
## Best Practices
465
466
### Consistent Formatting
467
468
```python
469
from pylatex import Document, Section
470
from pylatex.quantities import Quantity
471
import quantities as pq
472
473
# Define standard formatting options
474
STANDARD_OPTIONS = {
475
'round-precision': 3,
476
'round-mode': 'figures',
477
'scientific-notation': False
478
}
479
480
SCIENTIFIC_OPTIONS = {
481
'round-precision': 3,
482
'round-mode': 'figures',
483
'scientific-notation': True
484
}
485
486
doc = Document()
487
488
with doc.create(Section('Consistent Formatting')):
489
# Use consistent options throughout
490
speed = 299792458 * pq.meter / pq.second
491
doc.append('Speed of light: ')
492
doc.append(Quantity(speed, options=SCIENTIFIC_OPTIONS))
493
494
charge = 1.602176634e-19 * pq.coulomb
495
doc.append(' Elementary charge: ')
496
doc.append(Quantity(charge, options=SCIENTIFIC_OPTIONS))
497
```
498
499
### Documentation Standards
500
501
```python
502
from pylatex import Document, Section, Subsection
503
from pylatex.quantities import Quantity
504
import quantities as pq
505
506
doc = Document()
507
508
with doc.create(Section('Material Properties')):
509
# Always include uncertainties when available
510
density_steel = pq.UncertainQuantity(7850, pq.kilogram/(pq.meter**3), 50)
511
doc.append('Steel density: ')
512
doc.append(Quantity(density_steel))
513
514
# Use appropriate significant figures
515
youngs_modulus = 200e9 * pq.pascal
516
doc.append(' Young\'s modulus: ')
517
doc.append(Quantity(youngs_modulus, options={
518
'round-precision': 3,
519
'scientific-notation': True
520
}))
521
522
# Include measurement conditions when relevant
523
doc.append(' (measured at room temperature)')
524
```
525
526
The quantities system in PyLaTeX enables professional scientific notation and unit handling with automatic formatting, uncertainty propagation, and seamless integration between Python calculations and LaTeX typesetting.