Class: Ephem::SPK

Inherits:
Object
  • Object
show all
Defined in:
lib/ephem/spk.rb

Overview

The SPK class represents a SPICE Kernel (SPK) file, which contains ephemeris data for solar system bodies. It manages segments of trajectory data and provides methods to access and manipulate this data.

SPK files contain segments of ephemeris data, where each segment represents the motion of one body (target) with respect to another body (center) over a specific time period.

Examples:

Opening and using an SPK file

spk = Ephem::SPK.open("de421.bsp")
segment = spk[0, 10]
spk.close

Constant Summary collapse

TYPES =
[
  INPOP = "IMCCE INPOP",
  JPL_DE = "JPL DE"
].freeze
INPOP_REGEXP =
/^\s+\d{4}\.\d{5}0+$/
DE_REGEXP =
/^[A-Z]E-(\d{4})LE-\1$/
DE_FILENAME =
"NIO2SPK"
DATA_TYPE_IDENTIFIER =
5

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(daf:) ⇒ SPK

Creates a new SPK instance with the given DAF.

Parameters:

  • daf (Ephem::IO::DAF)

    The DAF (Double precision Array File) containing SPK data

Raises:

  • (ArgumentError)

    If the DAF is nil



36
37
38
39
40
41
42
# File 'lib/ephem/spk.rb', line 36

def initialize(daf:)
  raise ArgumentError, "DAF cannot be nil" if daf.nil?

  @daf = daf
  @segments = load_segments
  @pairs = build_pairs
end

Instance Attribute Details

#dafObject (readonly)

Returns the value of attribute daf.



29
30
31
# File 'lib/ephem/spk.rb', line 29

def daf
  @daf
end

#pairsObject (readonly)

Returns the value of attribute pairs.



29
30
31
# File 'lib/ephem/spk.rb', line 29

def pairs
  @pairs
end

#segmentsObject (readonly)

Returns the value of attribute segments.



29
30
31
# File 'lib/ephem/spk.rb', line 29

def segments
  @segments
end

Class Method Details

.open(path) ⇒ SPK

Opens an SPK file at the specified path.

Parameters:

  • path (String)

    Path to the SPK file

Returns:

  • (SPK)

    A new SPK instance

Raises:

  • (ArgumentError)

    If the file cannot be accessed due to permissions



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ephem/spk.rb', line 49

def self.open(path)
  daf = IO::DAF.new(File.open(path, "rb"))
  if daf.file_type == :pck
    raise ArgumentError, "#{path} is a binary PCK file, use Ephem::PCK.open"
  end

  new(daf: daf)
rescue Errno::EACCES => e
  raise ArgumentError, "File permission denied: #{path} (#{e.message})"
rescue
  daf&.close
  raise
end

Instance Method Details

#[](center, target) ⇒ Segments::Segment, Segments::PositionGroup

Retrieves the segment for a specific center-target pair.

Parameters:

  • center (Integer)

    NAIF ID of the center body

  • target (Integer)

    NAIF ID of the target body

Returns:

Raises:

  • (KeyError)

    If no segment is found for the given center-target pair



90
91
92
93
94
95
# File 'lib/ephem/spk.rb', line 90

def [](center, target)
  @pairs.fetch([center, target]) do
    raise KeyError,
      "No segment found for center: #{center}, target: #{target}"
  end
end

#closevoid

This method returns an undefined value.

Closes the SPK file and cleans up resources. This method should be called when you’re done using the SPK file.



67
68
69
70
# File 'lib/ephem/spk.rb', line 67

def close
  @daf&.close
  @segments&.each(&:clear_data)
end

#commentsString

Returns the comments stored in the SPK file.

Returns:

  • (String)

    The comments from the DAF file



112
113
114
# File 'lib/ephem/spk.rb', line 112

def comments
  @daf.comments
end

#each_segment {|segment| ... } ⇒ Enumerator, void

Iterates through all segments in the SPK file.

Yields:

  • (segment)

    Gives each segment to the block

Yield Parameters:

Returns:

  • (Enumerator)

    If no block is given

  • (void)

    If a block is given



122
123
124
125
126
# File 'lib/ephem/spk.rb', line 122

def each_segment(&block)
  return enum_for(:each_segment) unless block_given?

  @segments.each(&block)
end

#excerpt(output_path:, start_jd:, end_jd:, target_ids: nil, debug: false) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ephem/spk.rb', line 128

def excerpt(output_path:, start_jd:, end_jd:, target_ids: nil, debug: false)
  Excerpt
    .new(self)
    .extract(
      output_path: output_path,
      start_jd: start_jd,
      end_jd: end_jd,
      target_ids: target_ids,
      debug: debug
    )
end

#to_sString

Returns a string representation of the SPK file.

Returns:

  • (String)

    A description of the SPK file and its segments



75
76
77
78
79
80
# File 'lib/ephem/spk.rb', line 75

def to_s
  <<~DESCRIPTION
    SPK file with #{@segments.size} segments:
    #{@segments.join("\n")}
  DESCRIPTION
end

#typeString?

Type of SPK file to make the difference between JPL DE and IMCCE INPOP

Returns:

  • (String, nil)

    The type of the SPK file



100
101
102
103
104
105
106
107
# File 'lib/ephem/spk.rb', line 100

def type
  @type ||= if @daf.record_data.internal_filename.match?(INPOP_REGEXP)
    INPOP
  elsif @daf.record_data.internal_filename == DE_FILENAME ||
      segments.first&.source&.match?(DE_REGEXP)
    JPL_DE
  end
end