Hello pyFAI team,
We are a team of researchers in Institute of Chemistry, Chinese Academy of Sciences (ICCAS), specializing in polymer fiber crystals analysis. We are writing to contribute several enhancements to pyFAI-integrate and to express our deep gratitude for this world-class library.
The Power of pyFAI in Our Research
The advanced integration algorithms and the flexible architecture of pyFAI have been instrumental in our work. It has significantly reduced the amount of boilerplate code we needed to write, allowing us to focus on high-level crystallographic analysis. Specifically, pyFAI serves as one of the critical preprocessing engines for our developed tools:
PolymCrystIndex: A method for indexing fiber diffraction.[Ma, T., Hu, W., Wang, D. & Liu, G. (2025). J. Appl. Cryst. 58, 759-767.]
PolymCrystRefine: Our upcoming polymer fiber crystal refinement suite.
1. Bug Fix: Cross-Regional Compatibility for 'µ' Character
The Problem: In Windows environments with a Chinese locale (defaulting to GBK encoding), pyFAI-integrate crashes when writing metadata headers. This is triggered by the µ symbol typically present in .poni files generated via calib2. Since the default open() function is locale-dependent, it fails to handle these UTF-8 characters on GBK systems.
The Solution: We updated the I/O logic to explicitly use encoding="utf-8", ensuring a robust, crash-free experience for users worldwide.
File: pyFAI/io/init.py (around line 800)
with open(filename, "w", encoding="utf-8") as f:
f.write(self.make_headers(has_mask=has_mask, has_dark=has_dark,
has_flat=has_flat,
polarization_factor=polarization_factor,
normalization_factor=normalization_factor,
metadata=metadata))
try:
f.write(f"\n# --> {filename}\n")
except UnicodeError:
f.write(f"\n# --> {filename.encode('utf8')}\n")
2. New Feature: Aggregated CSV/Excel Export with Metadata Headers
The Requirement: When performing 1D integration using the same .poni calibration file, the resulting datasets often share high similarity in experimental context. To streamline post-processing and downstream analysis, there was a need to consolidate these results.
The Solution: We implemented a SingleTabularWriter class in app/integrate.py. This allows users to aggregate multiple 1D integration results into a single CSV or Excel (.xlsx) file, complete with integrated metadata headers for better data traceability.
File: pyFAI/app/integrate.py
This class consolidates 1D results into a single file while maintaining scientific metadata traceability. It uses utf-8-sig to ensure Windows Excel compatibility and prevents blank row issues.
class SingleTabularWriter(io.Writer):
"""
Aggregates all 1D integration results into a single CSV or XLSX file.
Includes metadata header similar to .dat files.
"""
def __init__(self, output_path, format="csv"):
super(SingleTabularWriter, self).__init__()
self._output_path, self._format = output_path, format
self._radial_axis, self._data_dict = None, {}
def init(self, fai_cfg=None, lima_cfg=None):
self._is_2d = fai_cfg.get("do_2D", False) if isinstance(fai_cfg, dict) else getattr(fai_cfg, "do_2D", False)
if self._is_2d:
raise ValueError("Aggregated export supports 1D integration only!")
def prepare_write(self, data_info, engine):
name = os.path.splitext(os.path.basename(data_info.source_filename))[0] if data_info.source_filename else f"array_{data_info.data_id}"
if data_info.frame_id is not None:
name = f"{name}_{data_info.frame_id:04d}"
self._current_name, self._ai = name, engine
def write(self, data):
if self._radial_axis is None:
self._radial_axis = data.radial
self._unit = getattr(data, "unit", "unknown")
self._data_dict[self._current_name] = data.intensity
def close(self):
if not self._data_dict: return
df = pd.DataFrame({f"radial_{str(getattr(self, '_unit', 'unknown'))}": self._radial_axis})
for name, intensity in self._data_dict.items(): df[name] = intensity
header_lines = [
f"# Integrated using pyFAI version {pyFAI_version}",
f"# Date: {time.ctime()}",
f"# Detector: {getattr(self._ai.detector, 'name', 'unknown')}",
f"# Distance: {self._ai.dist} m",
f"# Wavelength: {self._ai.wavelength} m",
"#"
]
if self._format == "csv":
with open(self._output_path, 'w', encoding='utf-8-sig', newline='') as f:
for line in header_lines: f.write(line + "\n")
df.to_csv(f, index=False, lineterminator='\n')
elif self._format == "xlsx":
with pd.ExcelWriter(self._output_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='Integration Results', index=False)
meta_df = pd.DataFrame({"Property": [l.split(':')[0].strip('# ') for l in header_lines if ':' in l],
"Value": [l.split(':', 1)[1].strip() for l in header_lines if ':' in l]})
meta_df.to_excel(writer, sheet_name='Metadata', index=False)
We added a user-friendly selection dialog that appears when 1D integration is chosen, allowing researchers to choose their preferred output format at runtime.
Writer Initialization (within process):
Integrated the logic to switch from standard MultiFileWriter or HDF5Writer to the new SingleTabularWriter when CSV/XLSX is requested.
if format_ in ("csv", "xlsx"):
if output and os.path.isdir(output):
out_path = os.path.join(output, f"merged_results.{format_}")
elif output:
out_path = output if output.endswith(f".{format_}") else f"{output}.{format_}"
else:
out_path = f"merged_results.{format_}"
writer = SingleTabularWriter(out_path, format=format_)
AI Assistance Disclosure
The implementation of the tabular writer and the refinement of this documentation were prepared with the help of generative AI. All AI-generated code has been rigorously reviewed and tested in our laboratory to ensure its scientific accuracy and reliability.
Environment Details:
Version: 2025.12.1
OS: Windows 11 and Windows 10 with a Chinese locale.
Collaborative Outreach
We believe pyFAI is exceptionally efficient and deserves broader recognition. We request your permission to create and publish Chinese video tutorials to promote pyFAI's capabilities within the Chinese scientific community.
We would be extremely grateful if you could take a look at our approach. We hope our code might serve as a useful reference for the future evolution of the project.
Thank you for your time and consideration!
Best regards,
Tianyi Ma
Email:tyma507@iccas.ac.cn
Hello pyFAI team,
We are a team of researchers in Institute of Chemistry, Chinese Academy of Sciences (ICCAS), specializing in polymer fiber crystals analysis. We are writing to contribute several enhancements to pyFAI-integrate and to express our deep gratitude for this world-class library.
The Power of pyFAI in Our Research
The advanced integration algorithms and the flexible architecture of pyFAI have been instrumental in our work. It has significantly reduced the amount of boilerplate code we needed to write, allowing us to focus on high-level crystallographic analysis. Specifically, pyFAI serves as one of the critical preprocessing engines for our developed tools:
PolymCrystIndex: A method for indexing fiber diffraction.[Ma, T., Hu, W., Wang, D. & Liu, G. (2025). J. Appl. Cryst. 58, 759-767.]
PolymCrystRefine: Our upcoming polymer fiber crystal refinement suite.
1. Bug Fix: Cross-Regional Compatibility for 'µ' Character
The Problem: In Windows environments with a Chinese locale (defaulting to GBK encoding), pyFAI-integrate crashes when writing metadata headers. This is triggered by the µ symbol typically present in .poni files generated via calib2. Since the default open() function is locale-dependent, it fails to handle these UTF-8 characters on GBK systems.
The Solution: We updated the I/O logic to explicitly use encoding="utf-8", ensuring a robust, crash-free experience for users worldwide.
File: pyFAI/io/init.py (around line 800)
2. New Feature: Aggregated CSV/Excel Export with Metadata Headers
The Requirement: When performing 1D integration using the same .poni calibration file, the resulting datasets often share high similarity in experimental context. To streamline post-processing and downstream analysis, there was a need to consolidate these results.
The Solution: We implemented a SingleTabularWriter class in app/integrate.py. This allows users to aggregate multiple 1D integration results into a single CSV or Excel (.xlsx) file, complete with integrated metadata headers for better data traceability.
File: pyFAI/app/integrate.py
Dependency Addition:
We used pandas for tabular data handling. If the team prefers to avoid new dependencies, we are happy to rewrite this part using Python’s built-in csv module.
import pandas as pdImplementation of SingleTabularWriter:
This class consolidates 1D results into a single file while maintaining scientific metadata traceability. It uses utf-8-sig to ensure Windows Excel compatibility and prevents blank row issues.
We added a user-friendly selection dialog that appears when 1D integration is chosen, allowing researchers to choose their preferred output format at runtime.
Writer Initialization (within process):
Integrated the logic to switch from standard MultiFileWriter or HDF5Writer to the new SingleTabularWriter when CSV/XLSX is requested.
AI Assistance Disclosure
The implementation of the tabular writer and the refinement of this documentation were prepared with the help of generative AI. All AI-generated code has been rigorously reviewed and tested in our laboratory to ensure its scientific accuracy and reliability.
Environment Details:
Version: 2025.12.1
OS: Windows 11 and Windows 10 with a Chinese locale.
Collaborative Outreach
We believe pyFAI is exceptionally efficient and deserves broader recognition. We request your permission to create and publish Chinese video tutorials to promote pyFAI's capabilities within the Chinese scientific community.
We would be extremely grateful if you could take a look at our approach. We hope our code might serve as a useful reference for the future evolution of the project.
Thank you for your time and consideration!
Best regards,
Tianyi Ma
Email:tyma507@iccas.ac.cn