Amorphous Si area detectors manufactured by GE are currently used at APS and CHESS to acquire far-field high-energy X-ray diffraction data. The data from such detectors is stored in multi-frame, 16-bit depth binary images with 8192 bytes of header data. The data files typically have an extension .ge2. Since ImageMagick is able to deal with raw binary images like any other image format, it is possible to easily manipulate ge2 files using the convert command-line utility. I have written a gist that shows some simple ways of processing GE2 images using ImageMagick.
# Miscellaneous Diffraction Image Processing Commands # This file defines aliases for several common image processing # functions for GE2 diffraction images. This uses ImageMagick # program, which is typically available on all Linux and Mac # systems - http://www.imagemagick.org/script/index.php # USAGE: # Copy the contents of this file to the bottom of ~/.bashrc # Run from terminal: source ~/.bashrc # After this, following commands should be available # 1. Convert TIFF to GE. Saves input.ge2 # tiff2ge input.tiff # 2. Convert GE to TIFF. Saves input.tiff (Note: The produced TIFF may seem to have very low # intensity. That is because, GE2 has 16-bit depth. So the intensity # can go from 0 to 65000. Detectors at APS and CHESS generally max out # at 16000 counts. So even high intensity points have only 25% intensity. # You can stretch the intensity range of the TIFF using ImageMagick - # convert -normalize original.tiff bright_output.tiff). If the GE2 file has # multiple frames, TIFF is multipage. You can split TIFF into individual frames # using - convert multipage.tiff frame_%05d.tiff # ge2tiff input.ge2 # 3. Maximum over frames (saves a single frame with maximum intensity. Name: input-max.[ge2 | tiff]) # max_over_frames input.[ge2 | tiff] # 4. Mean over frames (saves a single frame with mean intensity. # Good for creating a dark frame from a sequence. Name: input-mean.[ge2 | tiff]) # mean_over_frames input.[ge2 | tiff] # 5. Extract a single frame from a multi-frame image. Saves multiframe_frame_num.[ge2 | tiff] # extract_frame multiframe.[ge2 | tiff] frame_num # 6. Subtract dark frame from a (single or multi-frame) image. Saves input-dark-subtracted.[ge2 | tiff] # subtract_dark input.[ge2 | tiff] dark_image.[ge2 | tiff] # 7. Show FF data in a parent directory. This lists all ge2 files inside # subdirectories. The output format is such that the GE2 list can be # used e.g. in a heXRD config file. # show_ff_data path/to/parent/directory # # Convert TIFF/PNG etc to GE2 (single or multi frame, works on multiple files) function tiff2ge() { for var in "$@" do echo "Processing : tiff2ge : $var" filename=$(basename "$var") extension="${filename##*.}" filename="${filename%.*}" convert "$var" -endian LSB -depth 16 -size 2048x2048 gray:"$filename".ge2.tmp dd if="$filename".ge2.tmp of="$filename".ge2 obs=8192 seek=1 rm -f "$filename.ge2.tmp" done } # Convert GE2 image to tiff function ge2tiff() { for var in "$@" do echo "Processing : ge2tiff : $var" filename=$(basename "$var") extension="${filename##*.}" filename="${filename%.*}" convert -endian LSB -depth 16 -size 2048x2048+8192 gray:"$var" "$filename".tiff done } # Max over all frames function max_over_frames() { for var in "$@" do filename=$(basename "$var") extension="${filename##*.}" filename="${filename%.*}" if [ ${extension^^} == "TIF" ] || [ ${extension^^} == "TIFF" ] then echo "Processing : max over : $extension : $var" convert "$var" -evaluate-sequence max "$filename"-max."$extension" elif [ ${extension^^} == "GE2" ] then echo "Processing : max over : $extension : $var" convert -endian LSB -depth 16 -size 2048x2048+8192 gray:"$var" \ -endian LSB -depth 16 -size 2048x2048 -evaluate-sequence max gray:"$filename"."$extension".max dd if="$filename"."$extension".max of="$filename"-max."$extension" obs=8192 seek=1 rm -f "$filename"."$extension".max fi done } # Mean over all frames function mean_over_frames() { for var in "$@" do filename=$(basename "$var") extension="${filename##*.}" filename="${filename%.*}" if [ ${extension^^} == "TIF" ] || [ ${extension^^} == "TIFF" ] then echo "Processing : max over : $extension : $var" convert "$var" -evaluate-sequence mean "$filename"-mean."$extension" elif [ ${extension^^} == "GE2" ] then echo "Processing : max over : $extension : $var" convert -endian LSB -depth 16 -size 2048x2048+8192 gray:"$var" \ -endian LSB -depth 16 -size 2048x2048 -evaluate-sequence mean gray:"$filename"."$extension".mean dd if="$filename"."$extension".mean of="$filename"-mean."$extension" obs=8192 seek=1 rm -f "$filename"."$extension".mean fi done } # Extract a specific frame from multi-frame image function extract_frame() { filename=$(basename "$1") extension="${filename##*.}" filename="${filename%.*}" if [ ${extension^^} == "TIF" ] || [ ${extension^^} == "TIFF" ] then echo "Processing : extract frame $2 : $extension : $1" convert "$1"[$2] "$filename"_"$2"."$extension" elif [ ${extension^^} == "GE2" ] then echo "Processing : extract frame $2 : $extension : $1" convert -endian LSB -depth 16 -size 2048x2048+8192 gray:"$1"["$2"] \ -endian LSB -depth 16 -size 2048x2048 -evaluate-sequence max gray:"$filename"_"$2"."$extension".tmp dd if="$filename"_"$2"."$extension".tmp of="$filename"_"$2"."$extension" obs=8192 seek=1 rm -f "$filename"_"$2"."$extension".tmp fi } # Subtract a dark frame from an image (not tested for multiframe) function subtract_dark() { filename=$(basename "$1") extension="${filename##*.}" filename="${filename%.*}" if [ ${extension^^} == "TIF" ] || [ ${extension^^} == "TIFF" ] then echo "Processing : subtract dark : $extension : $2 from $1" convert $1 null: $2 -compose difference -layers composite "$filename"-dark-subtracted."$extension" #composite -compose difference $1 $2 "$filename"-dark-subtracted."$extension" elif [ ${extension^^} == "GE2" ] then echo "Processing : subtract dark : $extension : $2 from $1" convert -endian LSB -depth 16 -size 2048x2048+8192 gray:$1 \ -endian LSB -depth 16 -size 2048x2048+8192 null: gray:$2 \ -compose difference -layers composite -endian LSB -depth 16 -size 2048x2048+8192 "$filename"-dark-subtracted."$extension".tmp #composite -compose difference -endian LSB -depth 16 -size 2048x2048+8192 gray:"$1" \ # -endian LSB -depth 16 -size 2048x2048+8192 gray:"$2" \ # -endian LSB -depth 16 -size 2048x2048+8192 "$filename"-dark-subtracted."$extension".tmp dd if="$filename"-dark-subtracted."$extension".tmp of="$filename"-dark-subtracted."$extension" obs=8192 seek=1 rm -f "$filename"-dark-subtracted."$extension".tmp fi } # Display file numbers from an ff directory function show_ff_data() { # Find all directories with name ff and loop over them find "$@" -not -empty -name "ff" -print | while read f; do # Show directory name echo "$f" # Get size of all contents in the directory (in bytes) tot_byte_size=$(du -b "$f") # By default du prints the folder name too. Strip that. tot_byte_size=($tot_byte_size) tot_byte_size=${tot_byte_size[0]} # Estimate number of FF frames assuming one frame = 2048*2048*2 bytes num_frames_estimate=$( echo $tot_byte_size / 8388608 | bc ) # Get size of all contents in a human readable unit (M, G, T) tot_file_size=$(du -h "$f") tot_file_size=($tot_file_size) # Print total size and frame number estimate echo Total size = ${tot_file_size[0]}, Estimated frames = $num_frames_estimate # List the contents of the folders filenames1=$(eval ls \'"$f"\' | tr '\n' ' ') filelist='' # Clean up the filenames assuming ff_%5d.ge2 format for filename in $filenames1 do filenum1=${filename:3:5} filenum=$(echo $filenum1 | sed 's/^0*//') filelist+=", $filenum" done filelist1=${filelist:2} # Print comma separated list of file numbers echo $filelist1 done }