bio-publisci 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/Gemfile +1 -1
  2. data/Rakefile +1 -1
  3. data/features/orm_steps.rb +4 -4
  4. data/features/reader.feature +3 -3
  5. data/features/reader_steps.rb +1 -0
  6. data/features/writer.feature +7 -2
  7. data/features/writer_steps.rb +8 -1
  8. data/lib/bio-publisci.rb +3 -1
  9. data/lib/bio-publisci/datacube_model.rb +46 -20
  10. data/lib/bio-publisci/dataset/ORM/data_cube_orm.rb +196 -194
  11. data/lib/bio-publisci/dataset/ORM/observation.rb +15 -13
  12. data/lib/bio-publisci/dataset/data_cube.rb +3 -3
  13. data/lib/bio-publisci/dataset/dataset_for.rb +25 -4
  14. data/lib/bio-publisci/dsl/dataset_dsl.rb +4 -2
  15. data/lib/bio-publisci/dsl/dsl.rb +3 -0
  16. data/lib/bio-publisci/metadata/generator.rb +1 -1
  17. data/lib/bio-publisci/metadata/metadata_model.rb +27 -0
  18. data/lib/bio-publisci/metadata/prov/activity.rb +1 -0
  19. data/lib/bio-publisci/metadata/prov/model/prov_models.rb +33 -2
  20. data/lib/bio-publisci/query/query_helper.rb +5 -1
  21. data/lib/bio-publisci/readers/arff.rb +2 -40
  22. data/lib/bio-publisci/readers/dataframe.rb +1 -1
  23. data/lib/bio-publisci/writers/arff.rb +42 -16
  24. data/lib/bio-publisci/writers/base.rb +77 -0
  25. data/lib/bio-publisci/writers/csv.rb +31 -0
  26. data/lib/bio-publisci/writers/dataframe.rb +2 -2
  27. data/resources/queries/codes.rq +10 -5
  28. data/resources/queries/dimensions.rq +9 -4
  29. data/resources/queries/measures.rq +7 -2
  30. data/resources/queries/observations.rq +5 -4
  31. data/resources/weather.numeric.arff +26 -21
  32. data/spec/ORM/data_cube_orm_spec.rb +23 -3
  33. data/spec/ORM/prov_model_spec.rb +53 -0
  34. data/spec/dataset_for_spec.rb +21 -0
  35. data/spec/dsl_spec.rb +5 -2
  36. data/spec/metadata/metadata_dsl_spec.rb +1 -1
  37. data/spec/r_builder_spec.rb +2 -2
  38. data/spec/turtle/bacon +1 -1
  39. data/spec/turtle/reference +1 -1
  40. data/spec/turtle/weather +275 -0
  41. data/spec/writer_spec.rb +61 -0
  42. metadata +66 -28
  43. checksums.yaml +0 -7
data/Gemfile CHANGED
@@ -14,7 +14,7 @@ group :development do
14
14
  gem "bio", ">= 1.4.2"
15
15
  gem "rdoc", "~> 3.12"
16
16
  gem "spoon"
17
- gem "spira"
17
+ gem "spira", git: "https://github.com/ruby-rdf/spira.git"
18
18
  end
19
19
 
20
20
 
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Jeweler::Tasks.new do |gem|
21
21
  gem.description = %Q{A toolkit for publishing scientific results and datasets using RDF, OWL, and related technologies }
22
22
  gem.email = "wstrinz@gmail.com"
23
23
  gem.authors = ["Will Strinz"]
24
- gem.version = "0.0.7"
24
+ gem.version = "0.0.8"
25
25
 
26
26
  # dependencies defined in Gemfile
27
27
  end
@@ -1,7 +1,7 @@
1
1
  require_relative '../lib/bio-publisci.rb'
2
2
 
3
3
  Given /^an ORM::DataCube entitled "(.*?)"$/ do |name|
4
- @cube = PubliSci::ORM::DataCube.new(name: name)
4
+ @cube = PubliSci::DataSet::ORM::DataCube.new(name: name)
5
5
  end
6
6
 
7
7
  Given /^an ORM::DataCube entitled "(.*?)" with the following options:$/ do |name, opts|
@@ -18,7 +18,7 @@ Given /^an ORM::DataCube entitled "(.*?)" with the following options:$/ do |name
18
18
 
19
19
  options_hash[k] = v
20
20
  }
21
- @cube = PubliSci::ORM::DataCube.new(options_hash)
21
+ @cube = PubliSci::DataSet::ORM::DataCube.new(options_hash)
22
22
  end
23
23
 
24
24
  Given(/^a turtle string from file (.*)$/) do |file|
@@ -30,7 +30,7 @@ Given(/^the URI string "(.*?)"$/) do |uri|
30
30
  end
31
31
 
32
32
  When(/^I call the ORM::DataCube class method load on it$/) do
33
- @cube = PubliSci::ORM::DataCube.load(@string)
33
+ @cube = PubliSci::DataSet::ORM::DataCube.load(@string)
34
34
  end
35
35
 
36
36
  When /^I add a "(.*?)" dimension$/ do |dim|
@@ -70,5 +70,5 @@ Then /^the to_n3 method should return a string with a "(.*?)"$/ do |search|
70
70
  end
71
71
 
72
72
  Then(/^I should receive an ORM::DataCube object$/) do
73
- @cube.is_a?(PubliSci::ORM::DataCube).should == true
73
+ @cube.is_a?(PubliSci::DataSet::ORM::DataCube).should == true
74
74
  end
@@ -6,20 +6,20 @@ Feature: generate RDF
6
6
  Scenario: generate turtle RDF from a Dataframe
7
7
  Given a Dataframe generator
8
8
  When I provide an R dataframe and the label "mr"
9
- And generate a turtle string from it
9
+ And generate a turtle string from it
10
10
  Then the result should contain a "qb:dataSet"
11
11
  And the result should contain some "qb:Observation"s
12
12
 
13
13
  Scenario: generate turtle RDF from a CSV
14
14
  Given a CSV generator
15
15
  When I provide the reference file spec/csv/bacon.csv and the label "bacon"
16
- And generate a turtle string from it
16
+ And generate a turtle string from it
17
17
  Then the result should contain a "qb:dataSet"
18
18
  And the result should contain some "qb:Observation"s
19
19
 
20
20
  Scenario: generate turtle RDF from an ARFF file
21
21
  Given a ARFF generator
22
22
  When I provide the file resources/weather.numeric.arff
23
- And generate a turtle string from it
23
+ And generate a turtle string from it
24
24
  Then the result should contain a "qb:dataSet"
25
25
  And the result should contain some "qb:Observation"s
@@ -41,6 +41,7 @@ end
41
41
 
42
42
  When /^generate a turtle string from it$/ do
43
43
  @turtle_string = @generator.send :generate_n3, *@attr
44
+ # open('weather.ttl','w'){|f| f.write @turtle_string}
44
45
  end
45
46
 
46
47
  Then /^I should have access to a (.*) method$/ do |method|
@@ -1,9 +1,14 @@
1
1
  Feature: export to various formats using writers
2
2
 
3
3
  In order to use RDF encoded data in other applications
4
- I want to export domain objects using an PubliSci::Writer object
4
+ I want to export domain objects using an PubliSci::Writers object
5
5
 
6
6
  Scenario: write to ARFF format
7
7
  Given a ARFF writer
8
8
  When I call its from_turtle method on the file spec/turtle/bacon
9
- Then I should receive a .arff file as a string
9
+ Then I should receive a .arff file as a string
10
+
11
+ Scenario: write to CSV
12
+ Given a CSV writer
13
+ When I call its from_turtle method on the file spec/turtle/bacon
14
+ Then I should receive a .csv file as a string
@@ -1,5 +1,5 @@
1
1
  Given(/^a (.*) writer$/) do |type|
2
- @writer = PubliSci::Writer.const_get(type).new
2
+ @writer = PubliSci::Writers.const_get(type).new
3
3
  end
4
4
 
5
5
  When(/^I call its from_turtle method on the file (.*)$/) do |file|
@@ -13,5 +13,12 @@ When(/^I call its from_turtle method on the turtle string$/) do
13
13
  end
14
14
 
15
15
  Then(/^I should receive a \.arff file as a string$/) do
16
+ puts @result
16
17
  @result.is_a?(String).should be true
17
18
  end
19
+
20
+ Then(/^I should receive a \.csv file as a string$/) do
21
+ puts @result
22
+ @result.is_a?(String).should be true
23
+ end
24
+
@@ -34,9 +34,11 @@ load File.dirname(__FILE__) + '/bio-publisci/dataset/data_cube.rb'
34
34
  load File.dirname(__FILE__) + '/bio-publisci/dataset/dataset_for.rb'
35
35
  load File.dirname(__FILE__) + '/bio-publisci/dataset/configuration.rb'
36
36
  load File.dirname(__FILE__) + '/bio-publisci/dataset/dataset.rb'
37
+ load File.dirname(__FILE__) + '/bio-publisci/datacube_model.rb'
37
38
  load File.dirname(__FILE__) + '/bio-publisci/output.rb'
38
39
  load File.dirname(__FILE__) + '/bio-publisci/metadata/prov/element.rb'
39
40
  load File.dirname(__FILE__) + '/bio-publisci/metadata/prov/prov.rb'
41
+ load File.dirname(__FILE__) + '/bio-publisci/writers/base.rb'
40
42
 
41
43
 
42
44
  load_folder('bio-publisci/dsl')
@@ -47,7 +49,7 @@ load_folder('bio-publisci/readers')
47
49
  load_folder('bio-publisci/writers')
48
50
  load_folder('bio-publisci/dataset/ORM')
49
51
  # Dir.foreach(File.dirname(__FILE__) + '/generators') do |file|
50
- # unless file == "." or file == ".."
52
+ # unless file == "." or file == ".."
51
53
  # load File.dirname(__FILE__) + '/generators/' + file
52
54
  # end
53
55
  # end
@@ -2,14 +2,6 @@ require 'rdf/4store'
2
2
 
3
3
  module PubliSci
4
4
  module ORM
5
-
6
- # class Person < Spira::Base
7
- # configure :base_uri => "http://example.org/example/people"
8
-
9
- # property :name, :predicate => FOAF.name, :type => String
10
-
11
- # end
12
-
13
5
  # class Observation < Spira::Base
14
6
  # type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
15
7
  # property :label, predicate: RDFS.label
@@ -25,13 +17,14 @@ module PubliSci
25
17
 
26
18
  class DataStructureDefinition < Spira::Base
27
19
  type QB.DataStructureDefinition
20
+ property :label, predicate: RDFS.label
28
21
  has_many :component, predicate: QB.component
29
22
  end
30
23
 
31
24
  class DataSet < Spira::Base
32
25
  type QB.DataSet
33
26
  property :label, predicate: RDFS.label
34
-
27
+ property :structure, predicate: QB.structure
35
28
  end
36
29
 
37
30
  class Dimension < Spira::Base
@@ -51,20 +44,53 @@ module PubliSci
51
44
  Spira.add_repository :default, repo
52
45
  end
53
46
 
54
- def observation
55
- unless PubliSci::ORM.const_defined?("Observation")
56
- obs = Class.new(Spira::Base) do
57
- type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
47
+ # def observation
48
+ # unless PubliSci::ORM.const_defined?("Observation")
49
+ # obs = Class.new(Spira::Base) do
50
+ # type RDF::URI.new('http://purl.org/linked-data/cube#Observation')
58
51
 
59
- property :structure, predicate: QB.dataSet
52
+ # property :structure, predicate: QB.dataSet
60
53
 
61
- ((Dimension.each.to_a | Measure.each.to_a) || []).each{|component|
62
- property strip_uri(component.subject.to_s), predicate: component.subject
63
- }
64
- end
65
- PubliSci::ORM.const_set("Observation",obs)
54
+ # ((Dimension.each.to_a | Measure.each.to_a) || []).each{|component|
55
+ # property strip_uri(component.subject.to_s), predicate: component.subject
56
+ # }
57
+ # end
58
+ # PubliSci::ORM.const_set("Observation",obs)
59
+ # end
60
+ # Observation
61
+ # end
62
+
63
+ class Observation < Spira::Base
64
+ type QB.Observation
65
+ property :label, predicate: RDFS.label
66
+ property :dataset, predicate: QB.dataSet
67
+
68
+ def load_properties
69
+ comps = dataset.as(DataSet).structure.as(DataStructureDefinition).component.map{|comp| comp.as(Component)}
70
+ props = comps.map{|comp| comp.dimension ? comp.dimension.as(Dimension) : comp.measure.as(Measure) }
71
+ props.each{|prop|
72
+ ss = strip_uri(prop.subject.to_s)
73
+
74
+ self.class.property ss.to_sym, predicate: prop.subject
75
+ }
66
76
  end
67
- Observation
77
+
78
+ # for testing; DRY up eventually
79
+ def strip_uri(uri)
80
+ uri = uri.to_s.dup
81
+ uri[-1] = '' if uri[-1] == '>'
82
+ uri.to_s.split('/').last.split('#').last
83
+ end
84
+
85
+ # def method_missing(meth, *args, &block)
86
+ # if meth.to_s =~ /^find_by_(.+)$/
87
+ # run_find_by_method($1, *args, &block)
88
+ # else
89
+ # super # You *must* call super if you don't handle the
90
+ # # method, otherwise you'll mess up Ruby's method
91
+ # # lookup.
92
+ # end
93
+ # end
68
94
  end
69
95
 
70
96
  def reload_observation
@@ -1,238 +1,240 @@
1
1
  module PubliSci
2
- module ORM
3
- class DataCube
4
- extend PubliSci::Dataset::DataCube
5
- extend PubliSci::Analyzer
6
- # extend PubliSci::Metadata
7
- extend PubliSci::Query
8
- extend PubliSci::Parser
9
-
10
- include PubliSci::Dataset::DataCube
11
- include PubliSci::Analyzer
12
- include PubliSci::Metadata::Generator
13
- include PubliSci::Query
14
- include PubliSci::Parser
15
-
16
- attr_accessor :labels
17
- attr_accessor :dimensions
18
- attr_accessor :measures
19
- attr_accessor :obs
20
- attr_accessor :meta
21
-
22
- def initialize(options={},do_parse = true)
23
- @dimensions = {}
24
- @measures = []
25
- @obs = []
26
- @generator_options = {}
27
- @options = {}
28
-
29
- @meta = {}
30
-
31
- parse_options options if do_parse
32
- end
2
+ module DataSet
3
+ module ORM
4
+ class DataCube
5
+ extend PubliSci::Dataset::DataCube
6
+ extend PubliSci::Analyzer
7
+ # extend PubliSci::Metadata
8
+ extend PubliSci::Query
9
+ extend PubliSci::Parser
10
+
11
+ include PubliSci::Dataset::DataCube
12
+ include PubliSci::Analyzer
13
+ include PubliSci::Metadata::Generator
14
+ include PubliSci::Query
15
+ include PubliSci::Parser
16
+
17
+ attr_accessor :labels
18
+ attr_accessor :dimensions
19
+ attr_accessor :measures
20
+ attr_accessor :obs
21
+ attr_accessor :meta
22
+
23
+ def initialize(options={},do_parse = true)
24
+ @dimensions = {}
25
+ @measures = []
26
+ @obs = []
27
+ @generator_options = {}
28
+ @options = {}
29
+
30
+ @meta = {}
31
+
32
+ parse_options options if do_parse
33
+ end
33
34
 
34
- def self.load(graph,options={},verbose=false)
35
+ def self.load(graph,options={},verbose=false)
35
36
 
36
37
 
37
- graph = load_string(graph) unless graph =~ /^http/
38
+ graph = load_string(graph) unless graph =~ /^http/
38
39
 
39
- # puts get_hashes(execute_from_file('dimension_ranges.rq',graph))
40
- dimensions = Hash[get_hashes(execute_from_file('dimension_ranges.rq',graph),"to_s").map{|solution|
41
- #TODO coded properties should be found via SPARQL queries
42
- if solution[:range].split('/')[-2] == "code"
43
- type = :coded
44
- else
45
- type = solution[:range].to_s
46
- end
47
- [solution[:dimension], {type: type}]
48
- }]
49
- puts "dimensions: #{dimensions}" if verbose
50
-
51
- codes = execute_from_file('code_resources.rq',graph).to_h.map{|sol|
52
- [sol[:dimension].to_s, sol[:codeList].to_s, sol[:class].to_s]
53
- }
54
- puts "codes: #{codes}" if verbose
55
-
56
- measures = execute_from_file('measures.rq',graph).to_h.map{|m| m[:measure].to_s}
57
- puts "measures: #{measures}" if verbose
58
-
59
- name = execute_from_file('dataset.rq',graph).to_h.first[:label]
60
- puts "dataset: #{name}" if verbose
61
-
62
- obs = execute_from_file('observations.rq',graph)
63
- observations = observation_hash(obs)
64
- puts "observations: #{observations}" if verbose
65
-
66
- # simple_observations = observation_hash(obs,true)
67
-
68
- labels = execute_from_file('observation_labels.rq', graph)
69
- labels = Hash[labels.map{|sol|
70
- [sol[:observation].to_s, sol[:label].to_s]
71
- }]
72
-
73
- new_opts = {
74
- measures: measures,
75
- dimensions: dimensions,
76
- observations: observations.values,
77
- name: name,
78
- labels: labels.values,
79
- codes: codes
80
- }
81
-
82
- options = options.merge(new_opts)
83
- puts "creating #{options}" if verbose
84
- self.new(options)
85
- end
40
+ # puts get_hashes(execute_from_file('dimension_ranges.rq',graph))
41
+ dimensions = Hash[get_hashes(execute_from_file('dimension_ranges.rq',graph),"to_s").map{|solution|
42
+ #TODO coded properties should be found via SPARQL queries
43
+ if solution[:range].split('/')[-2] == "code"
44
+ type = :coded
45
+ else
46
+ type = solution[:range].to_s
47
+ end
48
+ [solution[:dimension], {type: type}]
49
+ }]
50
+ puts "dimensions: #{dimensions}" if verbose
86
51
 
87
- def parse_options(options)
88
- if options[:dimensions]
89
- options[:dimensions].each{|name,details|
90
- add_dimension(name, details[:type] || :coded)
52
+ codes = execute_from_file('code_resources.rq',graph).to_h.map{|sol|
53
+ [sol[:dimension].to_s, sol[:codeList].to_s, sol[:class].to_s]
91
54
  }
92
- end
55
+ puts "codes: #{codes}" if verbose
93
56
 
94
- if options[:measures]
95
- options[:measures].each{|m| @measures << m}
96
- end
57
+ measures = execute_from_file('measures.rq',graph).to_h.map{|m| m[:measure].to_s}
58
+ puts "measures: #{measures}" if verbose
97
59
 
98
- if options[:observations]
99
- options[:observations].each{|obs_data| add_observation obs_data}
100
- end
60
+ name = execute_from_file('dataset.rq',graph).to_h.first[:label]
61
+ puts "dataset: #{name}" if verbose
101
62
 
102
- @generator_options = options[:generator_options] if options[:generator_options]
103
- @options[:skip_metadata] = options[:skip_metadata] if options[:skip_metadata]
63
+ obs = execute_from_file('observations.rq',graph)
64
+ observations = observation_hash(obs)
65
+ puts "observations: #{observations}" if verbose
104
66
 
105
- if options[:name]
106
- @name = options[:name]
107
- else
108
- raise "No dataset name specified!"
109
- end
67
+ # simple_observations = observation_hash(obs,true)
110
68
 
111
- if options[:validate_each]
112
- @options[:validate_each] = options[:validate_each]
113
- end
69
+ labels = execute_from_file('observation_labels.rq', graph)
70
+ labels = Hash[labels.map{|sol|
71
+ [sol[:observation].to_s, sol[:label].to_s]
72
+ }]
114
73
 
115
- if options[:labels]
116
- @labels = options[:labels]
117
- end
74
+ new_opts = {
75
+ measures: measures,
76
+ dimensions: dimensions,
77
+ observations: observations.values,
78
+ name: name,
79
+ labels: labels.values,
80
+ codes: codes
81
+ }
118
82
 
119
- if options[:codes]
120
- @codes = options[:codes]
83
+ options = options.merge(new_opts)
84
+ puts "creating #{options}" if verbose
85
+ self.new(options)
121
86
  end
122
- end
123
87
 
124
- def to_n3
88
+ def parse_options(options)
89
+ if options[:dimensions]
90
+ options[:dimensions].each{|name,details|
91
+ add_dimension(name, details[:type] || :coded)
92
+ }
93
+ end
94
+
95
+ if options[:measures]
96
+ options[:measures].each{|m| @measures << m}
97
+ end
98
+
99
+ if options[:observations]
100
+ options[:observations].each{|obs_data| add_observation obs_data}
101
+ end
102
+
103
+ @generator_options = options[:generator_options] if options[:generator_options]
104
+ @options[:skip_metadata] = options[:skip_metadata] if options[:skip_metadata]
125
105
 
126
- #create labels if not specified
127
- unless @labels.is_a?(Array) && @labels.size == @obs.size
128
- if @labels.is_a? Symbol
129
- #define some automatic labeling methods
106
+ if options[:name]
107
+ @name = options[:name]
130
108
  else
131
- @labels = (1..@obs.size).to_a.map(&:to_s)
109
+ raise "No dataset name specified!"
110
+ end
111
+
112
+ if options[:validate_each]
113
+ @options[:validate_each] = options[:validate_each]
114
+ end
115
+
116
+ if options[:labels]
117
+ @labels = options[:labels]
118
+ end
119
+
120
+ if options[:codes]
121
+ @codes = options[:codes]
132
122
  end
133
123
  end
134
- data = {}
135
124
 
125
+ def to_n3
136
126
 
137
- #collect observation data
138
- check_integrity(@obs.map{|o| o.data}, @dimensions.keys, @measures)
139
- @obs.map{|obs|
140
- (@measures | @dimensions.keys).map{ |component|
141
- (data[component] ||= []) << obs.data[component]
142
- }
143
- }
144
-
145
-
146
- @codes = @dimensions.map{|d,v| d if v[:type] == :coded}.compact unless @codes
147
- str = generate(@measures, @dimensions.keys, @codes, data, @labels, @name, @generator_options)
148
- unless @options[:skip_metadata]
149
- fields = {
150
- publishers: publishers(),
151
- subject: subjects(),
152
- author: author(),
153
- description: description(),
154
- date: date(),
155
- var: @name,
127
+ #create labels if not specified
128
+ unless @labels.is_a?(Array) && @labels.size == @obs.size
129
+ if @labels.is_a? Symbol
130
+ #define some automatic labeling methods
131
+ else
132
+ @labels = (1..@obs.size).to_a.map(&:to_s)
133
+ end
134
+ end
135
+ data = {}
136
+
137
+
138
+ #collect observation data
139
+ check_integrity(@obs.map{|o| o.data}, @dimensions.keys, @measures)
140
+ @obs.map{|obs|
141
+ (@measures | @dimensions.keys).map{ |component|
142
+ (data[component] ||= []) << obs.data[component]
143
+ }
156
144
  }
157
- # puts basic(fields,@generator_options)
158
- str += "\n" + basic(fields)
145
+
146
+
147
+ @codes = @dimensions.map{|d,v| d if v[:type] == :coded}.compact unless @codes
148
+ str = generate(@measures, @dimensions.keys, @codes, data, @labels, @name, @generator_options)
149
+ unless @options[:skip_metadata]
150
+ fields = {
151
+ publishers: publishers(),
152
+ subject: subjects(),
153
+ author: author(),
154
+ description: description(),
155
+ date: date(),
156
+ var: @name,
157
+ }
158
+ # puts basic(fields,@generator_options)
159
+ str += "\n" + basic(fields)
160
+ end
161
+ str
159
162
  end
160
- str
161
- end
162
163
 
163
- def add_dimension(name, type=:coded)
164
- @dimensions[name.to_s] = {type: type}
165
- end
164
+ def add_dimension(name, type=:coded)
165
+ @dimensions[name.to_s] = {type: type}
166
+ end
166
167
 
167
- def add_measure(name)
168
- @measures << name
169
- end
168
+ def add_measure(name)
169
+ @measures << name
170
+ end
170
171
 
171
- def add_observation(data)
172
- data = Hash[data.map{|k,v| [k.to_s, v]}]
173
- obs = Observation.new(data)
174
- check_integrity([obs.data],@dimensions.keys,@measures) if @options[:validate_each]
175
- @obs << obs
176
- end
172
+ def add_observation(data)
173
+ data = Hash[data.map{|k,v| [k.to_s, v]}]
174
+ obs = Observation.new(data)
175
+ check_integrity([obs.data],@dimensions.keys,@measures) if @options[:validate_each]
176
+ @obs << obs
177
+ end
177
178
 
178
- def insert(observation)
179
- @obs << observation
180
- end
179
+ def insert(observation)
180
+ @obs << observation
181
+ end
181
182
 
182
- def publishers
183
- @meta[:publishers] ||= []
184
- end
183
+ def publishers
184
+ @meta[:publishers] ||= []
185
+ end
185
186
 
186
- def publishers=(publishers)
187
- @meta[:publishers] = publishers
188
- end
187
+ def publishers=(publishers)
188
+ @meta[:publishers] = publishers
189
+ end
189
190
 
190
- def subjects
191
- @meta[:subject] ||= []
192
- end
191
+ def subjects
192
+ @meta[:subject] ||= []
193
+ end
193
194
 
194
- def subjects=(subjects)
195
- @meta[:subject]=subjects
196
- end
195
+ def subjects=(subjects)
196
+ @meta[:subject]=subjects
197
+ end
197
198
 
198
- def add_publisher(label,uri)
199
- publishers << {label: label, uri: uri}
200
- end
199
+ def add_publisher(label,uri)
200
+ publishers << {label: label, uri: uri}
201
+ end
201
202
 
202
- def add_subject(id)
203
- subject << id
204
- end
203
+ def add_subject(id)
204
+ subject << id
205
+ end
205
206
 
206
- def author
207
- @meta[:creator] ||= ""
208
- end
207
+ def author
208
+ @meta[:creator] ||= ""
209
+ end
209
210
 
210
- def author=(author)
211
- @meta[:creator] = author
212
- end
211
+ def author=(author)
212
+ @meta[:creator] = author
213
+ end
213
214
 
214
- def description
215
- @meta[:description] ||= ""
216
- end
215
+ def description
216
+ @meta[:description] ||= ""
217
+ end
217
218
 
218
- def description=(description)
219
- @meta[:description] = description
220
- end
219
+ def description=(description)
220
+ @meta[:description] = description
221
+ end
221
222
 
222
- def date
223
- @meta[:date] ||= "#{Time.now.day}-#{Time.now.month}-#{Time.now.year}"
224
- end
223
+ def date
224
+ @meta[:date] ||= "#{Time.now.day}-#{Time.now.month}-#{Time.now.year}"
225
+ end
225
226
 
226
- def date=(date)
227
- @meta[:date] = date
228
- end
227
+ def date=(date)
228
+ @meta[:date] = date
229
+ end
229
230
 
230
- def to_h
231
- {
232
- measures: @measures,
233
- dimensions: @dimensions,
234
- observations: @obs.map{|o| o.data}
235
- }
231
+ def to_h
232
+ {
233
+ measures: @measures,
234
+ dimensions: @dimensions,
235
+ observations: @obs.map{|o| o.data}
236
+ }
237
+ end
236
238
  end
237
239
  end
238
240
  end