ruby-avm-library/lib/avm/image.rb

287 lines
7.1 KiB
Ruby
Raw Normal View History

2011-03-07 17:39:47 +00:00
require 'avm/creator'
2011-03-10 22:45:21 +00:00
require 'avm/xmp'
2011-03-15 14:55:09 +00:00
require 'avm/image_type'
require 'avm/image_quality'
2011-03-16 19:32:50 +00:00
require 'avm/spatial_quality'
require 'avm/coordinate_system_projection'
require 'avm/coordinate_frame'
2011-03-16 14:41:01 +00:00
require 'avm/observation'
2011-03-07 17:39:47 +00:00
module AVM
class Image
2011-03-15 14:55:09 +00:00
DUBLIN_CORE_FIELDS = [ :title, :description ]
2011-03-16 14:54:56 +00:00
PHOTOSHOP_SINGLES = {
'Headline' => :headline,
'DateCreated' => :date
}
2011-03-16 14:54:56 +00:00
AVM_SINGLE_FIELDS = [
'Distance.Notes',
'Spectral.Notes',
'ReferenceURL',
'Credit',
'ID',
'Type',
2011-03-16 19:32:50 +00:00
'Image.ProductQuality',
'Spatial.Equinox',
'Spatial.Rotation',
'Spatial.Notes',
'Spatial.FITSheader',
'Spatial.Quality',
'Spatial.CoordsystemProjection',
'Spatial.CDMatrix',
'Spatial.Scale',
'Spatial.ReferencePixel',
'Spatial.ReferenceDimension',
'Spatial.ReferenceValue',
'Spatial.Equinox',
'Spatial.CoordinateFrame'
2011-03-16 14:54:56 +00:00
]
AVM_SINGLE_METHODS = [
:distance_notes,
:spectral_notes,
:reference_url,
:credit,
:id,
:type,
2011-03-16 19:32:50 +00:00
:quality,
:spatial_equinox,
:spatial_rotation,
:spatial_notes,
:fits_header,
:spatial_quality,
:coordinate_system_projection,
:spatial_cd_matrix,
:spatial_scale,
:reference_pixel,
:reference_dimension,
:reference_value,
:equinox,
:coordinate_frame
2011-03-16 14:54:56 +00:00
]
AVM_SINGLE_MESSAGES = [
:distance_notes,
:spectral_notes,
:reference_url,
:credit,
:id,
:image_type,
2011-03-16 19:32:50 +00:00
:image_quality,
:spatial_equinox,
:spatial_rotation,
:spatial_notes,
:fits_header,
:spatial_quality,
:coordinate_system_projection,
:spatial_cd_matrix,
:spatial_scale,
:reference_pixel,
:reference_dimension,
:reference_value,
:equinox,
:coordinate_frame
2011-03-16 14:54:56 +00:00
]
2011-03-16 14:41:01 +00:00
AVM_SINGLES = AVM_SINGLE_FIELDS.zip(AVM_SINGLE_METHODS)
2011-03-16 21:09:49 +00:00
AVM_SINGLES_FOR_MESSAGES = AVM_SINGLE_FIELDS.zip(AVM_SINGLE_MESSAGES)
2011-03-15 14:55:09 +00:00
2011-03-16 19:32:50 +00:00
AVM_TO_FLOAT = [
:spatial_rotation,
:spatial_cd_matrix,
:spatial_scale,
:reference_pixel,
:reference_dimension,
:reference_value
]
HASH_FIELDS = [ :title, :headline, :description, :distance_notes,
:spectral_notes, :reference_url, :credit, :date,
:id, :image_type, :image_quality, :coordinate_frame,
:equinox, :reference_value, :reference_dimension, :reference_pixel,
:spatial_scale, :spatial_rotation, :coordinate_system_projection, :spatial_quality,
:spatial_notes, :fits_header, :spatial_cd_matrix, :distance
]
2011-03-15 20:56:27 +00:00
attr_reader :creator, :observations
2011-03-07 17:39:47 +00:00
2011-03-11 18:59:34 +00:00
def initialize(options = {})
2011-03-10 22:45:21 +00:00
@creator = AVM::Creator.new(self)
2011-03-11 18:59:34 +00:00
@options = options
2011-03-16 19:32:50 +00:00
AVM_TO_FLOAT.each do |field|
if @options[field]
case @options[field]
when Array
@options[field].collect!(&:to_f)
else
@options[field] = @options[field].to_f
end
end
end
2011-03-15 20:56:27 +00:00
@observations = []
end
def create_observation(options)
observation = Observation.new(self, options)
@observations << observation
observation
2011-03-07 17:39:47 +00:00
end
2011-03-09 15:14:31 +00:00
def to_xml
2011-03-10 22:45:21 +00:00
document = AVM::XMP.new
2011-03-09 15:14:31 +00:00
2011-03-10 22:45:21 +00:00
creator.add_to_document(document)
2011-03-15 20:56:27 +00:00
Observation.add_to_document(document, observations)
2011-03-09 15:14:31 +00:00
2011-03-14 16:35:29 +00:00
document.get_refs do |refs|
2011-03-15 14:55:09 +00:00
DUBLIN_CORE_FIELDS.each do |field|
2011-03-14 16:35:29 +00:00
refs[:dublin_core].add_child(%{<dc:#{field}>#{alt_li_tag(send(field))}</dc:#{field}>})
end
refs[:photoshop].add_child(%{<photoshop:Headline>#{headline}</photoshop:Headline>})
refs[:photoshop].add_child(%{<photoshop:DateCreated>#{string_date}</photoshop:DateCreated>})
2011-03-14 16:35:29 +00:00
2011-03-16 21:09:49 +00:00
AVM_SINGLES_FOR_MESSAGES.each do |tag, message|
if value = send(message)
case value
when Array
value = '<rdf:Seq>' + value.collect { |v| "<rdf:li>#{v.to_s}</rdf:li>" }.join + '</rdf:Seq>'
else
value = value.to_s
end
refs[:avm].add_child(%{<avm:#{tag}>#{value}</avm:#{tag}>})
end
2011-03-15 14:55:09 +00:00
end
distance_nodes = []
distance_nodes << rdf_li(light_years) if light_years
if redshift
distance_nodes << rdf_li('-') if distance_nodes.empty?
distance_nodes << rdf_li(redshift)
end
if !distance_nodes.empty?
refs[:avm].add_child(%{<avm:Distance><rdf:Seq>#{distance_nodes.join}</rdf:Seq></avm:Distance>})
2011-03-14 16:35:29 +00:00
end
end
2011-03-10 22:45:21 +00:00
document.doc
2011-03-09 15:14:31 +00:00
end
2011-03-11 18:27:17 +00:00
2011-03-11 18:59:34 +00:00
def id
@options[:id]
end
def image_type
2011-03-16 19:32:50 +00:00
cv_class_instance_for(AVM::ImageType, :type)
2011-03-15 14:55:09 +00:00
end
def image_quality
2011-03-16 19:32:50 +00:00
cv_class_instance_for(AVM::ImageQuality, :quality)
end
def spatial_quality
cv_class_instance_for(AVM::SpatialQuality, :spatial_quality)
end
def coordinate_frame
cv_class_instance_for(AVM::CoordinateFrame, :coordinate_frame)
end
def coordinate_system_projection
cv_class_instance_for(AVM::CoordinateSystemProjection, :coordinate_system_projection)
2011-03-11 18:59:34 +00:00
end
def date
2011-03-14 16:35:29 +00:00
(Time.parse(@options[:date]) rescue nil)
end
def string_date
return nil if !date
date.strftime('%Y-%m-%d')
2011-03-11 18:59:34 +00:00
end
2011-03-11 19:04:50 +00:00
def distance
[ light_years, redshift ]
end
2011-03-11 18:27:17 +00:00
def self.from_xml(string)
document = AVM::XMP.from_string(string)
2011-03-15 14:55:09 +00:00
options = {}
document.get_refs do |refs|
DUBLIN_CORE_FIELDS.each do |field|
if node = refs[:dublin_core].at_xpath(".//dc:#{field}//rdf:li[1]")
options[field] = node.text
end
end
2011-03-16 14:41:01 +00:00
AVM_SINGLES.each do |tag, field|
2011-03-15 14:55:09 +00:00
if node = refs[:avm].at_xpath("./avm:#{tag}")
2011-03-16 19:32:50 +00:00
if !(list_items = node.search('.//rdf:li')).empty?
options[field] = list_items.collect(&:text)
else
options[field] = node.text
end
2011-03-15 14:55:09 +00:00
end
end
PHOTOSHOP_SINGLES.each do |tag, field|
if node = refs[:photoshop].at_xpath("./photoshop:#{tag}")
options[field] = node.text
end
2011-03-15 14:55:09 +00:00
end
if node = refs[:avm].at_xpath('./avm:Distance')
2011-03-15 15:16:10 +00:00
list_values = node.search('.//rdf:li').collect { |li| li.text }
2011-03-15 14:55:09 +00:00
case list_values.length
when 0
options[:light_years] = node.text
2011-03-15 14:55:09 +00:00
when 1
options[:light_years] = list_values.first
when 2
options[:light_years] = (list_values.first == '-') ? nil : list_values.first
2011-03-15 15:16:10 +00:00
options[:redshift] = list_values.last
2011-03-15 14:55:09 +00:00
end
end
end
image = new(options)
2011-03-11 18:27:17 +00:00
image.creator.from_xml(self, document)
2011-03-16 14:22:59 +00:00
Observation.from_xml(image, document)
2011-03-11 18:27:17 +00:00
image
end
2011-03-11 18:59:34 +00:00
def to_h
hash = Hash[HASH_FIELDS.collect { |key| [ key, send(key) ] }]
hash[:creator] = creator.to_a
hash
end
2011-03-11 18:59:34 +00:00
def method_missing(method)
@options[method]
end
2011-03-14 16:35:29 +00:00
private
def alt_li_tag(text)
%{<rdf:Alt><rdf:li xml:lang="x-default">#{text}</rdf:li></rdf:Alt>}
end
2011-03-15 14:55:09 +00:00
def rdf_li(text)
%{<rdf:li>#{text}</rdf:li>}
end
2011-03-16 19:32:50 +00:00
def cv_class_instance_for(mod, field)
(mod.const_get(@options[field].to_sym).new rescue nil)
end
2011-03-07 17:39:47 +00:00
end
end