Skip to content

Commit 90aa1c2

Browse files
Merge pull request #24 from TristanHehnen/main
Added differential conversion computation
2 parents 7d0f337 + b3b670d commit 90aa1c2

1 file changed

Lines changed: 83 additions & 16 deletions

File tree

src/firescipy/pyrolysis/kinetics.py

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import numpy as np
99
import pandas as pd
1010

11+
from scipy.integrate import trapezoid, cumulative_trapezoid
1112
from scipy.interpolate import interp1d
1213
from scipy.optimize import curve_fit, minimize
1314
from typing import List, Dict, Union # for type hints in functions
@@ -293,42 +294,108 @@ def combine_repetitions(database, condition, temp_program="constant_heating_rate
293294
return df_combined
294295

295296

296-
def differential_conversion(differential_data, m_0=None, m_f=None):
297-
# TODO: add differential conversion computation
298-
raise ValueError(f" * Still under development.")
299-
return
297+
def differential_conversion(time, differential_data):
298+
"""
299+
Calculate the conversion (alpha) from differential experimental data.
300+
301+
This function computes the conversion (alpha) for a series of
302+
differential experimental data, such as heat flow (DSC) or heat
303+
release rate (MCC), by integrating the signal over time and
304+
normalizing by the total integrated value.
305+
306+
For DSC-type data, the idea can be written as:
307+
308+
.. math::
309+
310+
\\Delta H(t_i) = \\int_{t_0}^{t_i} \\frac{dH}{dt} \\, dt
311+
312+
\\Delta H_\\text{tot} = \\int_{t_0}^{t_f} \\frac{dH}{dt} \\, dt
313+
314+
\\alpha(t_i) = \\frac{\\Delta H(t_i)}{\\Delta H_\\text{tot}}
315+
316+
where:
317+
\\alpha = conversion,
318+
H = enthalpy (or another extensive quantity),
319+
t_0 = initial time,
320+
t_i = instantaneous time,
321+
t_f = final time.
322+
323+
Parameters
324+
----------
325+
time : pd.Series or np.ndarray
326+
Time series of the experiment in seconds.
327+
differential_data : pd.Series or np.ndarray
328+
Experimental data representing differential quantities
329+
(e.g., heat flow (DSC) or heat release rate (MCC))
330+
used to calculate the conversion.
331+
332+
Returns
333+
-------
334+
np.ndarray
335+
Array of alpha values representing the conversion.
336+
"""
337+
338+
# Convert the input data to NumPy arrays for calculations
339+
time = series_to_numpy(time)
340+
differential_data = series_to_numpy(differential_data)
341+
342+
# Check if proper data was provided
343+
if time.shape != differential_data.shape:
344+
raise ValueError(
345+
"time and differential_data must have the same shape "
346+
f"(got {time.shape} and {differential_data.shape})."
347+
)
348+
349+
# Compute the total H (integral over the full signal)
350+
Delta_H_total = trapezoid(differential_data, time)
351+
352+
# Prevent division by zero
353+
if Delta_H_total == 0:
354+
raise ValueError("Total integral of differential_data is zero; cannot compute conversion (division by zero).")
355+
356+
# Compute cumulative H over time (same length as input)
357+
Delta_H = cumulative_trapezoid(differential_data, time, initial=0.0)
358+
359+
# Compute the conversion
360+
alpha = Delta_H / Delta_H_total
361+
362+
return alpha
300363

301364

302365
def integral_conversion(integral_data, m_0=None, m_f=None):
303366
"""
304367
Calculate the conversion (alpha) from integral experimental data.
305368
306-
This function computes the conversion (alpha) for a series of
307-
integral experimental data, such as mass or concentration, based on the
308-
formula:
369+
This function computes the conversion (alpha) from a series of
370+
integral experimental data, such as sample mass (TGA) or concentrations,
371+
by normalizing the change in the quantity with respect to its
372+
initial and final values.
373+
374+
For TGA-type data, the idea can be written as:
309375
310376
.. math::
311377
312-
\\alpha = \\frac{m_0 - m_i}{m_0 - m_f}
378+
\\alpha(t_i) = \\frac{m_0 - m_i}{m_0 - m_f}
313379
314380
where:
315-
m_0 = initial mass/concentration,
316-
m_i = instantaneous mass/concentration,
317-
m_f = final mass/concentration.
381+
\\alpha = conversion,
382+
m_0 = initial mass ,
383+
m_i = instantaneous mass at time t_i,
384+
m_f = final mass (e.g., char or residue).
318385
319386
If `m_0` and `m_f` are not provided, they default to the first and last
320387
values of the `integral_data` series, respectively.
321388
322389
Parameters
323390
----------
324391
integral_data : pd.Series or np.ndarray
325-
Experimental data representing integral quantities
326-
(e.g., mass or concentration over time) to calculate the conversion.
392+
Experimental data representing an integral quantity
393+
(typically, mass over time in TGA, or concentration).
327394
m_0 : float, optional
328-
Initial mass/concentration. Defaults to the first
395+
Initial value (e.g., initial mass). Defaults to the first
329396
value of `integral_data`.
330397
m_f : float, optional
331-
Final mass/concentration. Defaults to the last
398+
Final value (e.g., residual mass). Defaults to the last
332399
value of `integral_data`.
333400
334401
Returns
@@ -337,7 +404,7 @@ def integral_conversion(integral_data, m_0=None, m_f=None):
337404
Array of alpha values representing the conversion.
338405
"""
339406

340-
# Convert the input data to a numpy array for calculations
407+
# Convert the input data to a NumPy array for calculations
341408
m_i = series_to_numpy(integral_data)
342409

343410
# Use the provided m_0 or default to the first value in the series

0 commit comments

Comments
 (0)