This vignette introduces some of the development features of the isoreader package and is aimed primarily at code contributors interested in expanding its functionality or helping with bug fixes.

# copy an example file from the package with the new extension
#> [1] TRUE

#> Registered S3 method overwritten by 'R.oo':
#>   method        from
#>   throw.default R.methodsS3
#> Info: preparing to read 1 data files (all will be cached)...
#> Info: this is the new reader!
#> List of 7
#>  $version :Classes 'package_version', 'numeric_version' hidden list of 1 #> ..$ : int [1:3] 1 0 11
#>  $read_options :List of 4 #> ..$ file_info        : logi TRUE
#>   ..$method_info : logi TRUE #> ..$ raw_data         : logi TRUE
#>   ..$vendor_data_table: logi TRUE #>$ file_info        :Classes 'tbl_df', 'tbl' and 'data.frame':   1 obs. of  5 variables:
#>   ..$file_id : chr "example.new.did" #> ..$ file_root    : chr "."
#>   ..$file_path : chr "example.new.did" #> ..$ file_subpath : chr NA
#>   ..$file_datetime: int NA #>$ method_info      : list()
#>  $raw_data :Classes 'tbl_df', 'tbl' and 'data.frame': 0 obs. of 0 variables #>$ vendor_data_table:Classes 'tbl_df', 'tbl' and 'data.frame':   0 obs. of  0 variables
#>  $bgrd_data :Classes 'tbl_df', 'tbl' and 'data.frame': 0 obs. of 0 variables #> - attr(*, "class")= chr [1:2] "dual_inlet" "iso_file" #> - attr(*, "problems")=Classes 'tbl_df', 'tbl' and 'data.frame': 0 obs. of 3 variables: #> ..$ type   : chr(0)
#>   ..$func : chr(0) #> ..$ details: chr(0)
#> Info: finished reading 1 files in 0.31 secs
#> Dual inlet iso file 'example.new.did': 0 cycles, 0 ions ()
file.remove("example.new.did")
#> [1] TRUE

If you have designed and tested a new reader, please consider contributing it to the isoreader github repository via pull request.

# Processing hooks

The best way to start debugging an isoreader call is to switch the package into debug mode. This is done using the internal iso_turn_debug_on() function. This enables debug messags, turns caching off by default so files are always read anew, and makes the package keep more information in the isofile objects. It continues to catch errors inside file readers (keeping track of them in the problems) unless you set iso_turn_debug_on(catch_errors = FALSE), in which case no errors are caught and stop the processing so you get the full traceback and debugging options of your IDE.

## Debugging binary file reads (Isodat)

Errors during the binary file reads usually indicate the approximate position in the file where the error was encountered. The easiest way to get started on figuring out what the file looks like at that position is to use a binary file editor and jump to the position. For a sense of the interpreted structure around that position, one can use the internal function map_binary_structure which tries to apply all frequently occuring binary patterns recognized by isoreader. The binary representation of the source file is only available if in debug mode but if debug mode is ON, it can be accessed as follows:

This structure representation shows recognized control elements in <...> and data elements in {...} which are converted to text or numeric representation if the interpretation is unambiguous, or plain hexadecimal characters if the nature of the data cannot be determined with certainty. Because this function tries all possible control elements and data interpretations, it is quite slow and may take a while if run for large stretches of binary code (i.e. if the length parameter is very long).

For an overview of all the control elements that are currently consider, use the internal get_ctrl_blocks_config_df() function.

Additional information can be gleaned from the so-called control blocks, which are larger structural elements of Isodat binary files and are kept in a data frame wihin the binary object (again only available in debug mode).

Same as for specific byte positions, one can use the control blocks to navigate the file and map_binary_structure.