Basic Usage
This guide covers the fundamental concepts and workflows in nbragg.
Quick Example
Here’s a complete example showing the basic workflow:
import nbragg
# 1. Load your data
data = nbragg.Data.from_transmission("my_transmission.csv")
# 2. Define your material
xs = nbragg.CrossSection(iron="Fe_sg229_Iron-alpha.ncmat")
# 3. Create a model
model = nbragg.TransmissionModel(
xs,
vary_background=True,
vary_response=True
)
# 4. Fit the data
result = model.fit(data, wlmin=1.0, wlmax=6.0)
# 5. Plot the results
result.plot()
Data Loading
nbragg supports two main data formats:
From Transmission Data
If you have pre-calculated transmission data (wavelength, transmission, error):
data = nbragg.Data.from_transmission("transmission.csv")
Expected CSV format:
wavelength,trans,err
1.0,0.95,0.01
1.1,0.94,0.01
...
From Counts Data
If you have raw counts (signal and open beam):
data = nbragg.Data.from_counts(
signal="sample_counts.csv",
openbeam="openbeam_counts.csv",
L=10.0, # Flight path length in meters
tstep=10e-6 # Time step in seconds
)
Expected CSV format:
tof,counts,err
0,1000,31.6
1,1050,32.4
...
With empty region correction for background subtraction:
data = nbragg.Data.from_counts(
signal="sample_counts.csv",
openbeam="openbeam_counts.csv",
empty_signal="empty_sample.csv",
empty_openbeam="empty_openbeam.csv",
L=10.0,
tstep=10e-6
)
Using DataFrames Instead of Files
Both from_counts and from_transmission accept pandas DataFrames in addition to file paths:
import pandas as pd
import nbragg
# Create or load a DataFrame
df = pd.DataFrame({
'wavelength': [1.0, 1.1, 1.2],
'trans': [0.95, 0.94, 0.93],
'err': [0.01, 0.01, 0.01]
})
data = nbragg.Data.from_transmission(df)
This is useful when data is already in memory or needs preprocessing.
Time-of-Flight Corrections
If you’ve optimized L0 and t0 parameters using vary_tof, you can apply these corrections when loading data:
# After optimizing with vary_tof=True, you get L0 and t0 values
data = nbragg.Data.from_counts(
signal="sample_counts.csv",
openbeam="openbeam_counts.csv",
L=10.0,
tstep=10e-6,
L0=1.05, # Flight path scale factor (default 1.0)
t0=5.0 # Time offset correction (tof units)
)
The corrections are applied as:
L0 is a scale factor (default 1.0):
L0 > 1.0: longer flight path → TOF is reduced
L0 < 1.0: shorter flight path → TOF is increased
t0 is an additive time offset in TOF units
Formula:
corrected_tof = tof + (1.0 - L0) * tof + t0
Use the same L0 and t0 values you obtained from fitting with vary_tof=True.
Handling NaN Values
Remove rows with NaN values during data loading:
# Remove NaN values when loading
data = nbragg.Data.from_transmission("data.csv", dropna=True)
Or remove them after loading:
# Load data
data = nbragg.Data.from_transmission("data.csv")
# Remove NaN values in place
data.dropna(inplace=True)
# Or create a new Data object without NaN
clean_data = data.dropna()
Defining Materials
Single Phase
For a single crystalline phase:
xs = nbragg.CrossSection(iron="Fe_sg229_Iron-alpha.ncmat")
Using the materials registry:
xs = nbragg.CrossSection(
iron=nbragg.materials["Fe_sg229_Iron-alpha.ncmat"]
)
Multi-Phase
For samples with multiple phases:
xs = nbragg.CrossSection(
alpha="Fe_sg229_Iron-alpha.ncmat",
gamma="Fe_sg225_Iron-gamma.ncmat"
)
With initial weight fractions:
xs = nbragg.CrossSection(alpha="Fe_sg229_Iron-alpha.ncmat") * 0.7 + \
nbragg.CrossSection(gamma="Fe_sg225_Iron-gamma.ncmat") * 0.3
Creating Models
The TransmissionModel class is the core of nbragg fitting.
Basic Model
Simplest model with default parameters:
model = nbragg.TransmissionModel(xs)
Controlling Parameters
Use vary_* flags to control what parameters can vary during fitting:
model = nbragg.TransmissionModel(
xs,
vary_basic=True, # thickness, norm
vary_weights=True, # phase fractions
vary_background=True, # background parameters
vary_response=True, # instrument response
vary_orientation=False # keep orientations fixed
)
See Model Parameters for complete details.
Fitting Data
Basic Fit
Fit over a wavelength range:
result = model.fit(data, wlmin=1.0, wlmax=6.0)
The fitting uses the Rietveld method by default, which accumulates parameters across stages for optimal convergence.
Custom Stages
You can define custom fitting stages:
model.stages = {
'scale': ['norm', 'thickness'],
'background': 'background',
'weights': 'weights',
'response': 'response'
}
result = model.fit(data, wlmin=1.0, wlmax=6.0)
Or pass stages directly to fit:
custom_stages = {
'basic': ['norm', 'thickness'],
'all': 'all'
}
result = model.fit(data, wlmin=1.0, wlmax=6.0, stages=custom_stages)
Analyzing Results
The fit result contains all the information about the fit:
Parameter Values
# Print fit report
print(result.fit_report())
# Access parameters
thickness = result.params['thickness'].value
thickness_err = result.params['thickness'].stderr
# Check if fit succeeded
if result.success:
print(f"Chi-squared: {result.chisqr}")
print(f"Reduced chi-squared: {result.redchi}")
Stage Summary
For multi-stage fits, view the progression:
# Display stage summary (HTML table)
result.stages_summary
# Or as plain text
print(result.stages_summary.to_html())
Visualization
# Plot fit result
result.plot()
# Plot specific stage
result.plot_stage_progression('thickness')
# Plot residuals
result.plot(plot_residuals=True)
Setting Parameter Values
You can set initial values and bounds before fitting:
# Set value and bounds
model.params['thickness'].set(value=2.0, min=0.1, max=10.0)
# Fix a parameter
model.params['norm'].set(vary=False)
# Set with stderr
model.params['thickness'].set(value=2.0, vary=True)
Next Steps
Learn about Model Parameters for fine-grained control
Explore Crystal Orientation in nBragg for oriented materials
See MTEX Integration for texture analysis
Check Advanced Fitting for complex scenarios