A comprehensive Python library for programmatically creating and compiling LaTeX documents and snippets.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
The Quantity class converts Python quantity objects into properly formatted LaTeX output using the siunitx package.
class Quantity(Command):
def __init__(self, quantity, *, options=None, format_cb=None):
"""
Create properly formatted physical quantities with units.
Parameters:
- quantity: quantities.Quantity, UncertainQuantity, or numeric value
- options: dict, str, list, or Options, siunitx formatting options
- format_cb: callable, custom number formatting function (default: numpy.array_str)
Requires:
- siunitx package (automatically added)
- quantities Python package for quantity objects
Examples:
- Simple quantity: Quantity(3.14159 * meter / second)
- With uncertainty: Quantity(UncertainQuantity(16.0, meter, 0.3))
- Plain number: Quantity(6.022e23)
"""Usage example:
from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
with doc.create(Section('Physical Measurements')):
# Basic quantities with units
speed = 299792458 * pq.meter / pq.second
doc.append('Speed of light: ')
doc.append(Quantity(speed, options={'round-precision': 4, 'round-mode': 'figures'}))
# Force measurement
force = 9.81 * pq.newton
doc.append(' Force: ')
doc.append(Quantity(force))
# Energy calculation
mass = 2.5 * pq.kilogram
energy = 0.5 * mass * (10 * pq.meter/pq.second)**2
doc.append(' Kinetic energy: ')
doc.append(Quantity(energy))Automatic formatting of measurements with uncertainties using proper scientific notation.
from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
with doc.create(Section('Experimental Results')):
# Measurements with uncertainties
length = pq.UncertainQuantity(16.0, pq.meter, 0.3)
width = pq.UncertainQuantity(12.5, pq.meter, 0.2)
doc.append('Length: ')
doc.append(Quantity(length))
doc.append(' Width: ')
doc.append(Quantity(width))
# Calculated quantities with error propagation
area = length * width
doc.append(' Area: ')
doc.append(Quantity(area))
# Temperature measurements
temp = pq.UncertainQuantity(23.5, pq.celsius, 0.1)
doc.append(' Temperature: ')
doc.append(Quantity(temp))Format large numbers and scientific notation without units.
from pylatex import Document, Section
from pylatex.quantities import Quantity
doc = Document()
with doc.create(Section('Scientific Constants')):
# Avogadro's number
avogadro = 6.022140857e23
doc.append('Avogadro constant: ')
doc.append(Quantity(avogadro, options={'round-precision': 4}))
# Planck constant
planck = 6.62607015e-34
doc.append(' Planck constant: ')
doc.append(Quantity(planck, options={'scientific-notation': True}))
# Very small number
small_number = 1.234e-12
doc.append(' Small measurement: ')
doc.append(Quantity(small_number, options={'round-precision': 3, 'round-mode': 'figures'}))Control the appearance of quantities using siunitx options.
from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
with doc.create(Section('Formatting Examples')):
value = 1234.5678 * pq.meter
# Different rounding modes
doc.append('Default: ')
doc.append(Quantity(value))
doc.append(' Rounded to 2 places: ')
doc.append(Quantity(value, options={'round-precision': 2, 'round-mode': 'places'}))
doc.append(' 3 significant figures: ')
doc.append(Quantity(value, options={'round-precision': 3, 'round-mode': 'figures'}))
# Scientific notation control
large_value = 123456789 * pq.joule
doc.append(' Scientific notation: ')
doc.append(Quantity(large_value, options={'scientific-notation': True}))
doc.append(' Fixed notation: ')
doc.append(Quantity(large_value, options={'scientific-notation': False}))Handle complex unit combinations and formatting preferences.
from pylatex import Document, Section, Package
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
# Configure siunitx options globally
doc.packages.append(Package('siunitx', options=[
'per-mode=symbol',
'group-separator={,}',
'output-decimal-marker={.}'
]))
with doc.create(Section('Complex Units')):
# Velocity
velocity = 15.5 * pq.meter / pq.second
doc.append('Velocity: ')
doc.append(Quantity(velocity))
# Acceleration
acceleration = 9.81 * pq.meter / (pq.second**2)
doc.append(' Acceleration: ')
doc.append(Quantity(acceleration))
# Power
power = 750 * pq.watt
doc.append(' Power: ')
doc.append(Quantity(power))
# Pressure
pressure = 101325 * pq.pascal
doc.append(' Pressure: ')
doc.append(Quantity(pressure, options={'per-mode': 'fraction'}))
# Density
density = 1000 * pq.kilogram / (pq.meter**3)
doc.append(' Density: ')
doc.append(Quantity(density))Implement custom formatting functions for specialized number presentation.
from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
import numpy as np
doc = Document()
def engineering_format(value):
"""Format numbers in engineering notation (powers of 1000)."""
if value == 0:
return "0"
exponent = int(np.floor(np.log10(abs(value)) / 3) * 3)
mantissa = value / (10 ** exponent)
if exponent == 0:
return f"{mantissa:.3f}"
else:
return f"{mantissa:.3f}e{exponent:+d}"
def percent_format(value):
"""Format as percentage with 1 decimal place."""
return f"{value:.1f}"
with doc.create(Section('Custom Formatting')):
# Engineering notation
resistance = 47000 * pq.ohm
doc.append('Resistance: ')
doc.append(Quantity(resistance, format_cb=engineering_format))
# Percentage format for efficiency
efficiency = 0.856
doc.append(' Efficiency: ')
doc.append(Quantity(efficiency * 100, format_cb=percent_format))
doc.append('%')
# Custom precision for angles
angle = np.pi / 4 * pq.radian
doc.append(' Angle: ')
doc.append(Quantity(angle, format_cb=lambda x: f"{x:.4f}"))from pylatex import Document, Section, Subsection
from pylatex.quantities import Quantity
from pylatex.table import Tabular, Table
import quantities as pq
import numpy as np
doc = Document()
with doc.create(Section('Experimental Analysis')):
# Sample experimental data
measurements = [
pq.UncertainQuantity(12.3, pq.meter, 0.1),
pq.UncertainQuantity(12.5, pq.meter, 0.1),
pq.UncertainQuantity(12.1, pq.meter, 0.1),
pq.UncertainQuantity(12.4, pq.meter, 0.1),
pq.UncertainQuantity(12.2, pq.meter, 0.1)
]
with doc.create(Subsection('Raw Data')):
with doc.create(Table(position='htbp')) as table:
table.add_caption('Length Measurements')
with table.create(Tabular('cc')) as tabular:
tabular.add_row(['Trial', 'Length'])
tabular.add_hline()
for i, measurement in enumerate(measurements, 1):
tabular.add_row([str(i), Quantity(measurement)])
with doc.create(Subsection('Statistical Analysis')):
# Calculate statistics
values = [m.magnitude for m in measurements]
mean_value = np.mean(values)
std_value = np.std(values, ddof=1)
mean_quantity = pq.UncertainQuantity(mean_value, pq.meter, std_value/np.sqrt(len(values)))
doc.append('Mean length: ')
doc.append(Quantity(mean_quantity, options={'round-precision': 3}))
doc.append(' Standard deviation: ')
doc.append(Quantity(std_value * pq.meter, options={'round-precision': 3}))from pylatex import Document, Section
from pylatex.quantities import Quantity
from pylatex.math import Math
import quantities as pq
doc = Document()
with doc.create(Section('Physics Calculations')):
# Kinematic calculation
initial_velocity = 0 * pq.meter / pq.second
acceleration = 9.81 * pq.meter / (pq.second**2)
time = 3.5 * pq.second
# Calculate final velocity: v = v₀ + at
final_velocity = initial_velocity + acceleration * time
doc.append('Initial velocity: ')
doc.append(Quantity(initial_velocity))
doc.append(' Acceleration: ')
doc.append(Quantity(acceleration))
doc.append(' Time: ')
doc.append(Quantity(time))
doc.append(' Final velocity: ')
doc.append(Quantity(final_velocity))
# Distance calculation: s = v₀t + ½at²
distance = initial_velocity * time + 0.5 * acceleration * (time**2)
doc.append(' Distance traveled: ')
doc.append(Quantity(distance))
# Energy calculations
mass = 2.5 * pq.kilogram
kinetic_energy = 0.5 * mass * (final_velocity**2)
potential_energy = mass * acceleration * distance
doc.append(' Kinetic energy: ')
doc.append(Quantity(kinetic_energy))
doc.append(' Potential energy: ')
doc.append(Quantity(potential_energy))from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
with doc.create(Section('Unit Systems Comparison')):
# Same quantity in different units
distance_m = 1000 * pq.meter
distance_km = distance_m.rescale(pq.kilometer)
distance_mile = distance_m.rescale(pq.mile)
doc.append('Distance in meters: ')
doc.append(Quantity(distance_m))
doc.append(' In kilometers: ')
doc.append(Quantity(distance_km))
doc.append(' In miles: ')
doc.append(Quantity(distance_mile, options={'round-precision': 2}))
# Temperature conversions
temp_c = 25 * pq.celsius
temp_f = temp_c.rescale(pq.fahrenheit)
temp_k = temp_c.rescale(pq.kelvin)
doc.append(' Temperature in Celsius: ')
doc.append(Quantity(temp_c))
doc.append(' Fahrenheit: ')
doc.append(Quantity(temp_f))
doc.append(' Kelvin: ')
doc.append(Quantity(temp_k))Configure siunitx package options for consistent formatting throughout the document.
from pylatex import Document, Package, NoEscape, Command
from pylatex.quantities import Quantity
doc = Document()
# Configure siunitx globally
doc.packages.append(Package('siunitx', options=[
'separate-uncertainty=true',
'multi-part-units=single',
'bracket-numbers=false',
'per-mode=symbol',
'group-separator={,}',
'group-minimum-digits=4',
'round-mode=figures',
'round-precision=3'
]))
# Add custom units
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\rpm'), 'rpm']))
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\ppm'), 'ppm']))
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(r'\year'), 'year']))Handle unit name differences between Python quantities and siunitx.
# The UNIT_NAME_TRANSLATIONS dictionary in quantities.py handles conversions:
UNIT_NAME_TRANSLATIONS = {
"Celsius": "celsius",
"revolutions_per_minute": "rpm",
"v": "volt",
# Add custom translations as needed
}
# Custom units can be added to the document
from pylatex import Document, Command, NoEscape
doc = Document()
# Define custom units in preamble
custom_units = [
(r'\rpm', 'rpm'),
(r'\ppm', 'ppm'),
(r'\percent', r'\%'),
(r'\year', 'year'),
(r'\bit', 'bit'),
(r'\byte', 'B')
]
for unit_command, unit_name in custom_units:
doc.preamble.append(Command('DeclareSIUnit', arguments=[NoEscape(unit_command), unit_name]))from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
try:
# This might fail if the unit isn't recognized
custom_measurement = 42 * pq.meter # This should work
doc.append(Quantity(custom_measurement))
except Exception as e:
doc.append(f"Error formatting quantity: {e}")
# Fallback for unsupported units
def safe_quantity(value, unit=None, **options):
"""Safely create quantity with fallback formatting."""
try:
if unit is not None:
return Quantity(value * unit, **options)
else:
return Quantity(value, **options)
except Exception:
# Fallback to plain number
return str(value) + (f" {unit}" if unit else "")from pylatex import Document, Section
from pylatex.quantities import Quantity
import quantities as pq
# Define standard formatting options
STANDARD_OPTIONS = {
'round-precision': 3,
'round-mode': 'figures',
'scientific-notation': False
}
SCIENTIFIC_OPTIONS = {
'round-precision': 3,
'round-mode': 'figures',
'scientific-notation': True
}
doc = Document()
with doc.create(Section('Consistent Formatting')):
# Use consistent options throughout
speed = 299792458 * pq.meter / pq.second
doc.append('Speed of light: ')
doc.append(Quantity(speed, options=SCIENTIFIC_OPTIONS))
charge = 1.602176634e-19 * pq.coulomb
doc.append(' Elementary charge: ')
doc.append(Quantity(charge, options=SCIENTIFIC_OPTIONS))from pylatex import Document, Section, Subsection
from pylatex.quantities import Quantity
import quantities as pq
doc = Document()
with doc.create(Section('Material Properties')):
# Always include uncertainties when available
density_steel = pq.UncertainQuantity(7850, pq.kilogram/(pq.meter**3), 50)
doc.append('Steel density: ')
doc.append(Quantity(density_steel))
# Use appropriate significant figures
youngs_modulus = 200e9 * pq.pascal
doc.append(' Young\'s modulus: ')
doc.append(Quantity(youngs_modulus, options={
'round-precision': 3,
'scientific-notation': True
}))
# Include measurement conditions when relevant
doc.append(' (measured at room temperature)')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.
Install with Tessl CLI
npx tessl i tessl/pypi-pylatex