diff --git a/lib/avm/controlled_vocabulary.rb b/lib/avm/controlled_vocabulary.rb new file mode 100644 index 0000000..cb11428 --- /dev/null +++ b/lib/avm/controlled_vocabulary.rb @@ -0,0 +1,18 @@ +module AVM + module ControlledVocabulary + class << self + def included(klass) + klass::TERMS.each do |type| + new_klass = Class.new do + def to_s + self.class.to_s.split('::').last + end + end + + klass.const_set(type.to_sym, new_klass) + end + end + end + end +end + diff --git a/lib/avm/coordinate_frame.rb b/lib/avm/coordinate_frame.rb new file mode 100644 index 0000000..376f94b --- /dev/null +++ b/lib/avm/coordinate_frame.rb @@ -0,0 +1,10 @@ +require 'avm/controlled_vocabulary' + +module AVM + module CoordinateFrame + TERMS = %w{ICRS FK5 FK4 ECL GAL SGAL} + + include ControlledVocabulary + end +end + diff --git a/lib/avm/coordinate_system_projection.rb b/lib/avm/coordinate_system_projection.rb new file mode 100644 index 0000000..217134c --- /dev/null +++ b/lib/avm/coordinate_system_projection.rb @@ -0,0 +1,10 @@ +require 'avm/controlled_vocabulary' + +module AVM + module CoordinateSystemProjection + TERMS = %w{TAN SIN ARC AIT CAR CEA} + + include ControlledVocabulary + end +end + diff --git a/lib/avm/image.rb b/lib/avm/image.rb index 112e285..0aa66c9 100644 --- a/lib/avm/image.rb +++ b/lib/avm/image.rb @@ -2,6 +2,9 @@ require 'avm/creator' require 'avm/xmp' require 'avm/image_type' require 'avm/image_quality' +require 'avm/spatial_quality' +require 'avm/coordinate_system_projection' +require 'avm/coordinate_frame' require 'avm/observation' module AVM @@ -16,7 +19,20 @@ module AVM 'Date', 'ID', 'Type', - 'Image.ProductQuality' + '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' ] AVM_SINGLE_METHODS = [ @@ -27,7 +43,20 @@ module AVM :date, :id, :type, - :quality + :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 ] AVM_SINGLE_MESSAGES = [ @@ -38,16 +67,50 @@ module AVM :string_date, :id, :image_type, - :image_quality + :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 ] AVM_SINGLES = AVM_SINGLE_FIELDS.zip(AVM_SINGLE_METHODS) + AVM_TO_FLOAT = [ + :spatial_rotation, + :spatial_cd_matrix, + :spatial_scale, + :reference_pixel, + :reference_dimension, + :reference_value + ] + attr_reader :creator, :observations def initialize(options = {}) @creator = AVM::Creator.new(self) @options = options + + 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 + @observations = [] end @@ -95,11 +158,23 @@ module AVM end def image_type - (AVM::ImageType.const_get(@options[:type].to_sym).new rescue nil) + cv_class_instance_for(AVM::ImageType, :type) end def image_quality - (AVM::ImageQuality.const_get(@options[:quality].to_sym).new rescue nil) + 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) end def date @@ -129,7 +204,11 @@ module AVM AVM_SINGLES.each do |tag, field| if node = refs[:avm].at_xpath("./avm:#{tag}") - options[field] = node.text + if !(list_items = node.search('.//rdf:li')).empty? + options[field] = list_items.collect(&:text) + else + options[field] = node.text + end end end @@ -168,6 +247,10 @@ module AVM def rdf_li(text) %{#{text}} end + + def cv_class_instance_for(mod, field) + (mod.const_get(@options[field].to_sym).new rescue nil) + end end end diff --git a/lib/avm/image_quality.rb b/lib/avm/image_quality.rb index ca1a7d9..c664d13 100644 --- a/lib/avm/image_quality.rb +++ b/lib/avm/image_quality.rb @@ -1,14 +1,10 @@ +require 'avm/controlled_vocabulary' + module AVM module ImageQuality - %w{Good Moderate Poor}.each do |type| - klass = Class.new do - def to_s - self.class.to_s.split('::').last - end - end + TERMS = %w{Good Moderate Poor} - AVM::ImageQuality.const_set(type.to_sym, klass) - end + include AVM::ControlledVocabulary end end diff --git a/lib/avm/image_type.rb b/lib/avm/image_type.rb index 5c6725c..fb379ec 100644 --- a/lib/avm/image_type.rb +++ b/lib/avm/image_type.rb @@ -1,14 +1,10 @@ +require 'avm/controlled_vocabulary' + module AVM module ImageType - %w{Observation Artwork Photographic Planetary Simulation Chart Collage}.each do |type| - klass = Class.new do - def to_s - self.class.to_s.split('::').last - end - end + TERMS = %w{Observation Artwork Photographic Planetary Simulation Chart Collage} - AVM::ImageType.const_set(type.to_sym, klass) - end + include ControlledVocabulary end end diff --git a/lib/avm/spatial_quality.rb b/lib/avm/spatial_quality.rb new file mode 100644 index 0000000..7c016d2 --- /dev/null +++ b/lib/avm/spatial_quality.rb @@ -0,0 +1,10 @@ +require 'avm/controlled_vocabulary' + +module AVM + module SpatialQuality + TERMS = %w{Full Position} + + include AVM::ControlledVocabulary + end +end + diff --git a/spec/avm/image_spec.rb b/spec/avm/image_spec.rb index 45ad06a..26dfd73 100644 --- a/spec/avm/image_spec.rb +++ b/spec/avm/image_spec.rb @@ -21,6 +21,21 @@ describe AVM::Image do let(:redshift) { 'Redshift' } let(:light_years) { 'Light years' } + let(:coordinate_frame) { 'ICRS' } + let(:equinox) { '100' } + let(:reference_value) { [ 100, 50 ] } + let(:reference_dimension) { [ 200, 150 ] } + let(:reference_pixel) { [ 25, 15 ] } + let(:spatial_scale) { [ 40, 35 ] } + let(:spatial_rotation) { 10 } + let(:coordinate_system_projection) { 'TAN' } + let(:spatial_quality) { 'Full' } + let(:spatial_notes) { 'Spatial Notes' } + let(:fits_header) { 'FITS header' } + let(:spatial_cd_matrix) { [ 1, 2, 3, 4 ] } + + it "should have spatial information" + def self.with_all_options let(:options) { { :title => title, @@ -35,7 +50,19 @@ describe AVM::Image do :type => type, :quality => image_quality, :redshift => redshift, - :light_years => light_years + :light_years => light_years, + :coordinate_frame => coordinate_frame, + :equinox => equinox, + :reference_value => reference_value, + :reference_dimension => reference_dimension, + :reference_pixel => reference_pixel, + :spatial_scale => spatial_scale, + :spatial_rotation => spatial_rotation, + :coordinate_system_projection => coordinate_system_projection, + :spatial_quality => spatial_quality, + :spatial_notes => spatial_notes, + :fits_header => fits_header, + :spatial_cd_matrix => spatial_cd_matrix, } } end @@ -52,6 +79,19 @@ describe AVM::Image do its(:id) { should == id } its(:image_type) { should be_a_kind_of eval("AVM::ImageType::#{type}") } its(:image_quality) { should be_a_kind_of eval("AVM::ImageQuality::#{image_quality}") } + + its(:coordinate_frame) { should be_a_kind_of eval("AVM::CoordinateFrame::#{coordinate_frame}") } + its(:equinox) { should == equinox } + its(:reference_value) { should == reference_value } + its(:reference_dimension) { should == reference_dimension } + its(:reference_pixel) { should == reference_pixel } + its(:spatial_scale) { should == spatial_scale } + its(:spatial_rotation) { should == spatial_rotation } + its(:coordinate_system_projection) { should be_a_kind_of eval("AVM::CoordinateSystemProjection::#{coordinate_system_projection}") } + its(:spatial_quality) { should be_a_kind_of eval("AVM::SpatialQuality::#{spatial_quality}") } + its(:spatial_notes) { should == spatial_notes } + its(:fits_header) { should == fits_header } + its(:spatial_cd_matrix) { should == spatial_cd_matrix } end describe '#initialize' do @@ -72,21 +112,18 @@ describe AVM::Image do context "nothing in it" do let(:file_path) { 'spec/sample_files/image/nothing.xmp' } - its(:title) { should be_nil } - its(:headline) { should be_nil } - its(:description) { should be_nil } - its(:distance_notes) { should be_nil } - its(:spectral_notes) { should be_nil } - its(:reference_url) { should be_nil } - its(:credit) { should be_nil } - its(:date) { should be_nil } - its(:id) { should be_nil } - its(:image_type) { should be_nil } - its(:image_quality) { should be_nil } - its(:redshift) { should be_nil } - its(:light_years) { should be_nil } + [ :title, :headline, :description, :distance_notes, + :spectral_notes, :reference_url, :credit, :date, + :id, :image_type, :image_quality, :redshift, + :light_years, :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 + ].each do |field| + its(field) { should be_nil } + end end - + context "image in it" do context "distance in light years" do let(:file_path) { 'spec/sample_files/image/light_years.xmp' } diff --git a/spec/sample_files/image/both.xmp b/spec/sample_files/image/both.xmp index cdcddd8..79f615c 100644 --- a/spec/sample_files/image/both.xmp +++ b/spec/sample_files/image/both.xmp @@ -39,6 +39,45 @@ Redshift + ICRS + 100 + + + 100 + 50 + + + + + 200 + 150 + + + + + 25 + 15 + + + + + 40 + 35 + + + 10 + TAN + Full + Spatial Notes + FITS header + + + 1 + 2 + 3 + 4 + + diff --git a/spec/sample_files/image/light_years.xmp b/spec/sample_files/image/light_years.xmp index aa7781d..01c25e0 100644 --- a/spec/sample_files/image/light_years.xmp +++ b/spec/sample_files/image/light_years.xmp @@ -12,7 +12,6 @@ Description - @@ -34,6 +33,45 @@ Observation Good Light years + ICRS + 100 + + + 100 + 50 + + + + + 200 + 150 + + + + + 25 + 15 + + + + + 40 + 35 + + + 10 + TAN + Full + Spatial Notes + FITS header + + + 1 + 2 + 3 + 4 + + diff --git a/spec/sample_files/image/redshift.xmp b/spec/sample_files/image/redshift.xmp index a48395c..0023b24 100644 --- a/spec/sample_files/image/redshift.xmp +++ b/spec/sample_files/image/redshift.xmp @@ -39,6 +39,45 @@ Redshift + ICRS + 100 + + + 100 + 50 + + + + + 200 + 150 + + + + + 25 + 15 + + + + + 40 + 35 + + + 10 + TAN + Full + Spatial Notes + FITS header + + + 1 + 2 + 3 + 4 + +