.. SPDX-FileCopyrightText: 1992-2026 NWO-I/SRON Space Research Organisation Netherlands .. .. SPDX-License-Identifier: CC-BY-4.0 File Operations (files) ======================== **Module**: ``utils_files`` Overview -------- Provides object-oriented file operations for SPEX, including opening, closing, reading, and writing files with comprehensive error handling. Supports various file formats used in X-ray astronomy. Key Features ------------ - Object-oriented file handling with ``type(files)`` - Comprehensive error checking and status reporting - Support for multiple file formats and types - Automatic file management and cleanup - Integration with SPEX file naming conventions File Type Codes --------------- .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Code - Description - Common Usage * - ``1`` - General data file - ASCII data, configuration files * - ``2`` - SPEX spectral file - .spo files * - ``3`` - SPEX response file - .res files * - ``4`` - FITS file - Astronomical data formats * - ``5`` - QDP file - Plotting data formats File Status Codes ----------------- .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Code - Description - Behavior * - ``1`` - OLD - Open existing file (read mode) * - ``2`` - NEW - Create new file (write mode) * - ``3`` - REPLACE - Overwrite existing file API Reference ------------- Type ~~~~ **files** File handling object with the following components: .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Component - Type - Description * - ``lu`` - integer - Logical unit number * - ``fits`` - logical - .true. if FITS format Methods ~~~~~~~ **open** .. function:: file_handler%open(runam, extension, itype, istat, ier) Open a file with specified parameters :param runam: Base filename (without extension) (character(*)) :param extension: File extension (character(*)) :param itype: File type code (integer) :param istat: File status code (integer) :param ier: Error status (integer, output) :return: None Opens file and sets logical unit. Returns error in ier. **close** .. function:: file_handler%close(ier) Close the currently open file :param ier: Error status (integer, output) :return: None Closes file and releases resources. **getlun** .. function:: file_handler%getlun(ier) Get the logical unit number :param ier: Error status (integer, output) :return: None Returns logical unit in file_handler%lu. **read** .. function:: file_handler%read(variables) Read data from file (generic interface) :param variables: Variables to read (various types) :return: None Supports multiple data types and formats. **write** .. function:: file_handler%write(variables) Write data to file (generic interface) :param variables: Variables to write (various types) :return: None Supports multiple data types and formats. Usage Examples -------------- **Basic File Operations** .. code-block:: fortran use utils_files type(files) :: file_handler integer :: status, file_type, file_status ! Open a new data file file_type = 1 ! General data file file_status = 2 ! NEW file call file_handler%open('mydata', 'dat', file_type, file_status, status) if (status /= 0) then write(*,*) 'Error opening file:', status else write(*,*) 'File opened successfully, LU:', file_handler%lu ! Close the file when done call file_handler%close(status) endif **Reading SPEX Spectral File** .. code-block:: fortran use utils_files type(files) :: spo_file integer :: status, file_type, file_status ! Open existing SPEX spectral file file_type = 2 ! SPEX spectral file file_status = 1 ! OLD file call spo_file%open('source1', 'spo', file_type, file_status, status) if (status == 0) then write(*,*) 'SPO file opened successfully' ! Read data... call spo_file%close(status) endif **Writing Response File** .. code-block:: fortran use utils_files type(files) :: res_file integer :: status, file_type, file_status ! Create new response file file_type = 3 ! SPEX response file file_status = 2 ! NEW file call res_file%open('rgs1', 'res', file_type, file_status, status) if (status == 0) then write(*,*) 'Response file created' ! Write data... call res_file%close(status) endif **File Type Detection** .. code-block:: fortran use utils_files type(files) :: auto_file integer :: status, file_type, file_status ! Open file with automatic type detection file_type = 1 ! Default to general file file_status = 1 ! OLD file ! Try different extensions call auto_file%open('data', 'fits', file_type, file_status, status) if (status == 0) then write(*,*) 'FITS file detected' auto_file%fits = .true. else call auto_file%open('data', 'spo', file_type, file_status, status) if (status == 0) then write(*,*) 'SPO file detected' endif endif **Error Handling Pattern** .. code-block:: fortran use utils_files use utils_message type(files) :: data_file type(message) :: mesg integer :: status, file_type, file_status ! Open file with comprehensive error handling file_type = 1 file_status = 1 call data_file%open('input', 'dat', file_type, file_status, status) if (status /= 0) then call mesg%sper('Failed to open input file') else ! Process file... call data_file%close(status) if (status /= 0) then call mesg%spwarn('Warning: File close error') endif endif **Batch File Processing** .. code-block:: fortran use utils_files use utils_list type(files) :: file_handler type(list) :: file_list character(len=80) :: filename integer :: i, status, file_type, file_status ! Add files to process call file_list%append('data1.spo') call file_list%append('data2.spo') ! Process each file file_type = 2 ! SPEX spectral files file_status = 1 ! OLD files do i = 1, file_list%nelements call file_list%get(i, filename) ! Extract base name and extension call file_handler%open(trim(filename), '', file_type, file_status, status) if (status == 0) then write(*,*) 'Processing:', trim(filename) ! Process file... call file_handler%close(status) endif enddo Notes ----- **File Naming Convention** - SPEX uses ``runam`` + ``extension`` naming - ``runam`` is the base name (e.g., 'source1') - ``extension`` is the file type (e.g., 'spo', 'res', 'fits') - Full filename: ``runam`` + '.' + ``extension`` **Error Handling** - Always check ``status`` after file operations - ``status = 0`` indicates success - Non-zero values indicate specific errors - Use message object for consistent error reporting **Memory Management** - Files object automatically manages resources - ``close()`` releases file handles and memory - No explicit deallocation needed **Performance Considerations** - File operations are I/O bound (disk speed) - Opening/closing files has overhead - For multiple operations, keep files open - Use appropriate file types for data **Best Practices** 1. **Always check error status** after file operations 2. **Use proper file types** for different data formats 3. **Close files explicitly** when done 4. **Use meaningful filenames** for debugging 5. **Handle errors gracefully** in production code 6. **Document file formats** in code comments **Common File Types in SPEX** .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Extension - Type Code - Description * - ``.spo`` - 2 - SPEX spectral data * - ``.res`` - 3 - Response matrices * - ``.fits`` - 4 - FITS format files * - ``.qdp`` - 5 - QDP plotting files * - ``.dat`` - 1 - General data files See Also -------- - :doc:`../core/messages` - Error handling for file operations - :doc:`../data/lists` - Managing lists of filenames - :doc:`fits` - FITS file specific operations - :doc:`qdp` - QDP file format details