summaryrefslogtreecommitdiff
path: root/lib/dataset.rb
blob: ed0ccddaf82e82a07586b27c0c8d3f573c6eaf83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
module OpenTox

  # Ruby wrapper for OpenTox Dataset Webservices (http://opentox.org/dev/apis/api-1.2/dataset).
  class Dataset 

    attr_accessor :features, :compounds, :data_entries

    def initialize uri=nil, subjectid=nil
      super uri, subjectid
      @features = []
      @compounds = []
      @data_entries = []
      append RDF.type, RDF::OT.OrderedDataset
    end

    def upload filename
      file = File.new filename
      RestClientWrapper.put(@uri, {:file => file}, {:subjectid => @subjectid})
    end

    def get
      super
      @features = []
      @compounds = []
      @data_entries = []
      query = RDF::Query.new do
        pattern [:uri, RDF.type, RDF::OT.OrderedDataset]
      end
      if query.execute(@rdf).first # ordered dataset
        query = RDF::Query.new do
          pattern [:uri, RDF.type, RDF::OT.Compound]
          pattern [:uri, RDF::OLO.index, :idx]
        end
        @compounds = query.execute(@rdf).sort_by{|s| s.idx}.collect{|s| OpenTox::Compound.new s.uri.to_s}
        query = RDF::Query.new do
          pattern [:uri, RDF.type, RDF::OT.Feature]
          pattern [:uri, RDF::OLO.index, :idx]
        end
        @features = query.execute(@rdf).sort_by{|s| s.idx}.collect{|s| OpenTox::Feature.new(s.uri.to_s)}
        numeric_features = @features.collect{|f| f.get; f[RDF.type].include? RDF::OT.NumericFeature}
        @compounds.each_with_index do |compound,i|
          query = RDF::Query.new do
            pattern [:data_entry, RDF::OLO.index, i]
            pattern [:data_entry, RDF::OT.values, :values]
            pattern [:values, RDF::OT.feature, :feature]
            pattern [:feature, RDF::OLO.index, :feature_idx]
            pattern [:values, RDF::OT.value, :value]
          end
          values = query.execute(@rdf).sort_by{|s| s.feature_idx}.collect do |s|
            numeric_features[s.feature_idx] ?  s.value.to_s.to_f : s.value.to_s
          end
          @data_entries << values
        end
      else
        query = RDF::Query.new do
          pattern [:uri, RDF.type, RDF::OT.Feature]
        end
        @features = query.execute(@rdf).collect{|s| OpenTox::Feature.new(s.uri.to_s)}
        query = RDF::Query.new do
          pattern [:data_entry, RDF::OT.compound, :compound]
        end
        @compounds = query.execute(@rdf).sort_by{|s| s.data_entry}.collect{|s| OpenTox::Compound.new s.compound.to_s}
        numeric_features = @features.collect{|f| f.get; f[RDF.type].include? RDF::OT.NumericFeature}
        @compounds.each do |compound|
          values = []
          @features.each_with_index do |feature,i|
            query = RDF::Query.new do
              pattern [:data_entry, RDF::OT.compound, RDF::URI.new(compound.uri)]
              pattern [:data_entry, RDF::OT.values, :values]
              pattern [:values, RDF::OT.feature, RDF::URI.new(feature.uri)]
              pattern [:values, RDF::OT.value, :value]
            end
            value = query.execute(@rdf).first.value.to_s
            value = value.to_f if numeric_features[i]
            values << value
          end
          @data_entries << values
        end
      end
    end

    def get_metadata
      uri = File.join(@uri,"metadata")
      begin
        parse_ntriples RestClientWrapper.get(uri,{},{:accept => "text/plain", :subjectid => @subjectid})
      rescue # fall back to rdfxml
        parse_rdfxml RestClientWrapper.get(uri,{},{:accept => "application/rdf+xml", :subjectid => @subjectid})
      end
      metadata
    end

    def << data_entry
      compound = data_entry.shift
      bad_request_error "Dataset features are empty." unless features
      bad_request_error "data_entry size does not match features size." unless data_entry.size == features.size
      bad_request_error "First data_entry is not a OpenTox::Compound" unless compound.class == OpenTox::Compound
      @compounds << compound
      @data_entries << data_entry
    end

    RDF_FORMATS.each do |format|

      # redefine rdf serialization methods 
      send :define_method, "to_#{format}".to_sym do
        # TODO: check, might affect appending to unordered datasets
        features.each_with_index do |feature,i|
          @rdf << [RDF::URI.new(feature.uri), RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.Feature)] 
          @rdf << [RDF::URI.new(feature.uri), RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)] 
        end
        compounds.each_with_index do |compound,i|
          @rdf << [RDF::URI.new(compound.uri), RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.Compound)]
          @rdf << [RDF::URI.new(compound.uri), RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)]
          data_entry_node = RDF::Node.new
          @rdf << [RDF::URI.new(@uri), RDF::URI.new(RDF::OT.dataEntry), data_entry_node]
          @rdf << [data_entry_node, RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.DataEntry)]
          @rdf << [data_entry_node, RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)]
          @rdf << [data_entry_node, RDF::URI.new(RDF::OT.compound), RDF::URI.new(compound.uri)]
          data_entries[i].each_with_index do |value,j|
            value_node = RDF::Node.new
            @rdf << [data_entry_node, RDF::URI.new(RDF::OT.values), value_node]
            @rdf << [value_node, RDF::URI.new(RDF::OT.feature), RDF::URI.new(@features[j].uri)]
            @rdf << [value_node, RDF::URI.new(RDF::OT.value), RDF::Literal.new(value)]
          end
        end
        super()
      end

    end
  end
end