Skip to content

A Ruby FITS I/O library for astronomers and astrophysicists

Notifications You must be signed in to change notification settings

sakuraisoki/RubyFits

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 

Repository files navigation

RubyFits

A Ruby FITS I/O library based on C++ sfitsio.

RubyFits is an easy-to-use Ruby library that can be used to manipulate files in the FITS format, the standard file format for astronomy and astrophysics.

The library uses the C++ sfitsio library by Chisato Yamauchi via the SWIG interface generator.

Install

To install this library, do the following:

  1. RubyFits needs sllib and sfitsio to be installed. These libraries can be installed via Homebrew, and execute the following if you are missing these nice libraries.
    cd /usr/local/Library/Formula
    wget --no-check-certificate https://galaxy.astro.isas.jaxa.jp/%7Eyuasa/documents/20130513/sllib.rb
    wget --no-check-certificate https://galaxy.astro.isas.jaxa.jp/%7Eyuasa/documents/20130513/sfitsio.rb
    brew install sfitsio
    
  2. Clone (download) from github.
    git clone https://github.com/yuasatakayuki/RubyFits.git
    
  3. Build with cmake.
    cd RubyFits/swig
    mkdir build
    cd build
    cmake ..
    make install
    
    Compiled library will be installed to $HOME/lib/ruby. If you do not like this, modify install prefix with --DCMAKE_INSTALL_PREFIX like:
    cmake . --DCMAKE_INSTALL_PREFIX=/usr/local
    
  4. In the ruby scritps, you can import RubyFits by doing like:
    require "RubyFits"
    include Fits
    
  5. Define RUBYLIB to direct "$HOME/lib/ruby" in your .zshrc for example.
    export RUBYLIB=$HOME/lib/ruby
    

Contact

  • Takayuki Yuasa - Japan Aerospace Exploration Agency (JAXA)
    • yuasa aaa astro.isas.jaxa.jp

API Reference

Usage

In the example/ folder, there are some scripts showing usages of RubyFits. "samplteTable.fits" can be used as a sample FITS file.

  • readTable.rb well describes how to read TableHDU in a FITS file.

Open/Save

See openSave.rb.

require "RubyFits"
include Fits

f=FitsFile.new("sampleTable.fits")
puts f
puts f[0].headerKeyValueComment(1)

You can open a file after constructing an empty instance first.

f=FitsFile.new
f.open("sampleTable.fits")

Save.

#save to file
f.saveAs("openSave.fits")

You can check the saved FITS file with fv for example (HEASOFT should be installed):

fv openSave.fits

FitsFile::saveAs() has some aliases:

  • writeToFile
  • saveToFile
  • writeToFile
  • write
  • save
  • writeTo
  • saveTo

Header access

See openSave.rb.

A FitsFile instance contains one or more HDU (header data unit, or sometimes called 'extension'). They can be accessed via one of the following accessors:

f=FitsFile.new("sampleTable.fits")
f.hdu(1)          # by index
f[1]              # by index
f.hdu("SPECTRUM") # by name

An HDU contains Header and Data (table or image). Key-value records in a header can be accesses as follows:

#dump the 1-st and 3-rd header key-value records
puts f[1].headerKeyValueComment(1)
puts f[1].headerKeyValueComment(3)
puts f[1].headerKeyValueComment("TELESCOP")

#dump some header key-value records
puts f[1].header("TELESCOP")
puts f[1].header("RA_PNT").to_f

#retrieve header key-value record
f[1].headers.each { |headerRecord|
 puts headerRecord.keyword
}

FitsFile::header(indexOrKeyword) returns header record object (an instance of FitsHeaderRecord class). Values of header record objects can be obtained via usual cast methods such as to_s(), to_f(), to_i(), and so on.

Header key-value record can be modified by assigning new value to the header record object. If no entry is found with a provided keyword, a new entry will be created with keyword and value (and comment if specified).

#modify header records
f[1].header("TELESCOP") << "ASTRO-H"
f[1].setHeader("INSTRUME","SXS")
f[1].addHeader("NEWKEY",3.14159, "COMMENT")
Type of record can be automatically changed depending on the assigned value.
#modify header record with comment
f[1].header("TELESCOP") << [3.141592,"PI"]

Read Table Contents

FitsTableHDU consists of one or more FitsTableColumn objects which represent each column of the table. Data in a column can be accessed like ones contained in an array.

See readTable.rb in the example/ folder.

puts "TableHDU access example1:"
puts "============================================"
tableHDU=f.getHDU("SPECTRUM")
puts "TableHDU #{tableHDU.getHDUName()} has #{tableHDU.nColumns()} columns and #{tableHDU.nRows} rows."
tableHDU.columns.each {|column|
  puts column
}
puts "============================================"

This will result (with sampleTable.fits):

> ruby readTable.rb

... omitted ...

TableHDU access example1:

============================================

TableHDU SPECTRUM has 2 columns and 256 rows.
Column named "CHANNEL" = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... (256 elements in total) ]
Column named "COUNTS" = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... (256 elements in total) ]

============================================

Another example is to use array accessor of FitsTableColumn. Index or range can be specified, e.g.

puts "TableHDU access example3:"
puts "============================================"
tableHDU=f.getHDU("SPECTRUM")
puts tableHDU["COUNTS"][100]
puts tableHDU["COUNTS"][100...120].join(",")
puts "============================================"
The above means "retrieve data of 101th-120th entries from the 'COUNTS' column contained in the 'SPECTRUM' HDU".

This will result:

============================================

115
115,109,115,84,87,95,79,111,76,71,93,102,93,81,88,77,73,86,71,78

============================================

Length of TableHDU (i.e. number of entries or number of rows) can be retrieved via FitsTableColumn.length() or its aliases:

  • nEntries
  • nRows
  • getNEntries
  • getNRows

Write Table Contents/Create New FITS File

See createNewTable.fits.

require "RubyFits"
include Fits

#create an empty column
column=FitsTableColumn.new

#set column name and format
column.initializeWithNameAndFormat("COUNTS","1J")

#set number of entries
column.resize(128)

#fill rows with (row number * 2).
for i in 0...column.nRows
	column[i]=i*2
end

#another example of filling rows
column[1..3]=[10,11,12]

#append the created column to a TableHDU
tableHDU=FitsTableHDU.new
tableHDU.resize(128)
tableHDU.appendColumn(column)
puts tableHDU

#append the create TableHDU to a FitsFile
f=FitsFile.new
f.append tableHDU

#Write to a file
f.saveAs("createNewTable.fits")

This will create a TableHDU with a column named "COUNTS" with a type of "1J" (i.e. 1 integer per row). Following the assignment, rows[1], row[2], and row[3] will have 10, 11, and 12, respectively.

Reading an Image HDU

FitsImageHDU handles access to ImageHDUs.

In the following example (copied from readImage.rb in the example/ folder), pHDU is the PrimarHDU os the "sampleTable.fits" file and its type is Image HDU (Primary HDU should be always ImageHDU). Although this sample FITS file does not contain meaningful values in the Primary HDU image, we can retrieve some pieces of information such as width, height, and pixel values.

require "RubyFits"
include Fits
f=FitsFile.new("sampleTable.fits")

#Primary HDU
pHDU=f.hdu(0)

puts pHDU
puts "Image type = #{pHDU.getTypeAsString()}"
puts "Image size = #{pHDU.getXSize} x #{pHDU.getYSize}"
puts "Pixel value:"
puts " (1,2) = #{pHDU.getPixelValue(1,2)}"
puts " (3,3) = #{pHDU.getPixelValue(3,3)}"
puts " (15,2) = #{pHDU.getPixelValue(15,2)}"
puts " (100,100) = #{pHDU.getPixelValue(100,100)} # <= this should be NaN because the pixel is outside the define size."

croppedImage=pHDU.section(1,2)

Creating an new Image HDU

The example code copied from newImage.rb shows how to create a new ImageHDU.

Note: In the current version of RubyFits, users have to call FitsImageHDU::imageHDU.constructImage(x,y,z,type) to actually construct an image with buffer allocated not only new() which creates an empty instance. This restriction is due to some limitation of SWIG related to the %rename attribute, and might be resolved in the future releases.

Type: type parameter should be one of the following values.

  • Fits::DOUBLE_T (64-bit double precision floating value)
  • Fits::FLOAT_T (32-bit single precision floating value)
  • Fits::LONG_T (32-bit signed integer)
  • Fits::LONGLONG_T (64-bit signed integer)
  • Fits::BYTE_T (8-bit signed integer)
  • Fits::SHORT_T (16-bit signed integer)
require "RubyFits"
include Fits

#Create an image HDU whose size is 100x100, and has type of DOUBLE_T 

puts Fits::DOUBLE_T
imageHDU=FitsImageHDU.new
imageHDU.constructImage(100,100,0,Fits::DOUBLE_T)
puts imageHDU.getHDUName
imageHDU.setHDUName("SampleImage")

puts imageHDU
puts "Image type = #{imageHDU.getTypeAsString()}"
puts "Image size = #{imageHDU.getXSize} x #{imageHDU.getYSize}"
puts "Setting a value to (50,50)"
imageHDU.setDouble(3.14159,50,50)
puts " (50,50) = #{imageHDU.getValue(50,50)}"

f=FitsFile.new
f.appendHDU(imageHDU)
f.saveAs("newImage.fits")
puts "Created image was saved to newImage.fits"

Comment and Questions, misc

Comments, suggestions, and questions are welcome. Please send them to yuasa aaa astro.isas.jaxa.jp.

If you are interested in SpaceWire, see my another project "The open-source SpaceWire project" and "SpaceWire RMAP Library.

About

A Ruby FITS I/O library for astronomers and astrophysicists

Resources

Stars

Watchers

Forks

Packages

 
 
 

Languages

  • Ruby 97.9%
  • C++ 1.5%
  • Shell 0.6%