labimotion 1.4.1 → 2.0.0.rc6

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labimotion/apis/generic_element_api.rb +1 -0
  3. data/lib/labimotion/apis/generic_klass_api.rb +3 -2
  4. data/lib/labimotion/apis/labimotion_api.rb +13 -0
  5. data/lib/labimotion/apis/standard_api.rb +25 -0
  6. data/lib/labimotion/apis/standard_layer_api.rb +87 -0
  7. data/lib/labimotion/apis/vocabulary_api.rb +93 -0
  8. data/lib/labimotion/constants.rb +21 -0
  9. data/lib/labimotion/entities/dataset_entity.rb +1 -1
  10. data/lib/labimotion/entities/element_entity.rb +1 -0
  11. data/lib/labimotion/entities/properties_entity.rb +229 -56
  12. data/lib/labimotion/entities/segment_entity.rb +0 -1
  13. data/lib/labimotion/entities/vocabulary_entity.rb +28 -0
  14. data/lib/labimotion/helpers/element_helpers.rb +8 -6
  15. data/lib/labimotion/helpers/generic_helpers.rb +6 -1
  16. data/lib/labimotion/helpers/param_helpers.rb +121 -82
  17. data/lib/labimotion/helpers/segment_helpers.rb +1 -1
  18. data/lib/labimotion/helpers/vocabulary_helpers.rb +16 -0
  19. data/lib/labimotion/libs/converter.rb +12 -33
  20. data/lib/labimotion/libs/data/mapper/Chemwiki.json +236 -0
  21. data/lib/labimotion/libs/data/mapper/Source.json +78 -0
  22. data/lib/labimotion/libs/data/vocab/Standard.json +385 -0
  23. data/lib/labimotion/libs/data/vocab/System.json +131 -0
  24. data/lib/labimotion/libs/dataset_builder.rb +70 -0
  25. data/lib/labimotion/libs/export_dataset.rb +165 -66
  26. data/lib/labimotion/libs/nmr_mapper.rb +204 -246
  27. data/lib/labimotion/libs/sample_association.rb +4 -0
  28. data/lib/labimotion/libs/vocabulary_handler.rb +118 -0
  29. data/lib/labimotion/models/concerns/attachment_converter.rb +5 -4
  30. data/lib/labimotion/models/concerns/datasetable.rb +1 -0
  31. data/lib/labimotion/models/concerns/segmentable.rb +2 -0
  32. data/lib/labimotion/models/element.rb +3 -0
  33. data/lib/labimotion/models/std_layer.rb +9 -0
  34. data/lib/labimotion/models/std_layers_revision.rb +9 -0
  35. data/lib/labimotion/models/vocabulary.rb +12 -0
  36. data/lib/labimotion/utils/mapper_utils.rb +169 -0
  37. data/lib/labimotion/utils/utils.rb +22 -0
  38. data/lib/labimotion/version.rb +1 -1
  39. data/lib/labimotion.rb +13 -3
  40. metadata +25 -5
@@ -0,0 +1,131 @@
1
+ [
2
+ {
3
+ "id": 1,
4
+ "identifier": "dateTime-create",
5
+ "name": "create_time",
6
+ "label": "Create Time",
7
+ "field_type": "datetime",
8
+ "opid": 9,
9
+ "term_id": "NCIT_C164483",
10
+ "ontology": {
11
+ "id": "ncit:class:http://purl.obolibrary.org/obo/NCIT_C164483",
12
+ "iri": "http://purl.obolibrary.org/obo/NCIT_C164483",
13
+ "type": "class",
14
+ "label": "Created Date",
15
+ "obo_id": "NCIT:C164483",
16
+ "short_form": "NCIT_C164483",
17
+ "description": [
18
+ "The date on which the activity or entity is created."
19
+ ],
20
+ "ontology_name": "ncit",
21
+ "ontology_prefix": "NCIT"
22
+ },
23
+ "source": "System",
24
+ "voc": {
25
+ "source": "System"
26
+ }
27
+ },
28
+ {
29
+ "id": 2,
30
+ "identifier": "dateTime-update",
31
+ "name": "update_time",
32
+ "label": "Update Time",
33
+ "field_type": "datetime",
34
+ "opid": 9,
35
+ "term_id": "NCIT_C25164",
36
+ "ontology": {
37
+ "id": "ncit:class:http://purl.obolibrary.org/obo/NCIT_C25710",
38
+ "iri": "http://purl.obolibrary.org/obo/NCIT_C25710",
39
+ "short_form": "NCIT_C25710",
40
+ "obo_id": "NCIT:C25710",
41
+ "label": "Update",
42
+ "description": [
43
+ "Make current; supply with recent information or technology."
44
+ ],
45
+ "ontology_name": "ncit",
46
+ "ontology_prefix": "NCIT",
47
+ "type": "class"
48
+ },
49
+ "source": "System",
50
+ "voc": {
51
+ "source": "System"
52
+ }
53
+ },
54
+ {
55
+ "id": 4,
56
+ "identifier": "user-name",
57
+ "name": "creator",
58
+ "label": "creator",
59
+ "field_type": "text",
60
+ "opid": 9,
61
+ "term_id": "NCIT_C42628",
62
+ "ontology": {
63
+ "id": "ncit:class:http://purl.obolibrary.org/obo/NCIT_C42628",
64
+ "iri": "http://purl.obolibrary.org/obo/NCIT_C42628",
65
+ "type": "class",
66
+ "label": "Created By",
67
+ "obo_id": "NCIT:C42628",
68
+ "short_form": "NCIT_C42628",
69
+ "description": [
70
+ "Indicates the person or authoritative body who brought the item into existence."
71
+ ],
72
+ "ontology_name": "ncit",
73
+ "ontology_prefix": "NCIT"
74
+ },
75
+ "source": "User",
76
+ "voc": {
77
+ "source": "User"
78
+ }
79
+ },
80
+ {
81
+ "id": 2,
82
+ "identifier": "element-id",
83
+ "name": "element_id",
84
+ "label": "Element Id",
85
+ "field_type": "text",
86
+ "opid": 9,
87
+ "term_id": "NCIT_C25364",
88
+ "source": "Element",
89
+ "voc": {
90
+ "source": "Element"
91
+ }
92
+ },
93
+ {
94
+ "id": 5,
95
+ "identifier": "element-name",
96
+ "name": "element_name",
97
+ "label": "Element Name",
98
+ "field_type": "text",
99
+ "opid": 8,
100
+ "term_id": "NCIT_C42694",
101
+ "source": "Element",
102
+ "voc": {
103
+ "source": "Element"
104
+ }
105
+ },
106
+ {
107
+ "id": 3,
108
+ "identifier": "element-short_label",
109
+ "name": "element_short_label",
110
+ "label": "Element Short Label",
111
+ "field_type": "text",
112
+ "opid": 9,
113
+ "term_id": "NCIT_C45561",
114
+ "source": "Element",
115
+ "voc": {
116
+ "source": "Element"
117
+ }
118
+ },
119
+ {
120
+ "id": 3,
121
+ "identifier": "element-class",
122
+ "name": "element_class",
123
+ "label": "Element Class",
124
+ "field_type": "text",
125
+ "opid": 9,
126
+ "source": "Element",
127
+ "voc": {
128
+ "source": "Element"
129
+ }
130
+ }
131
+ ]
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/utils/utils'
4
+ require 'labimotion/version'
5
+
6
+ module Labimotion
7
+ class DatasetBuilder
8
+ def self.build(container, content)
9
+ return unless valid_input?(container, content)
10
+
11
+ create_dataset_with_metadata(container, content)
12
+ end
13
+
14
+ private
15
+
16
+ def self.valid_input?(container, content)
17
+ container.present? &&
18
+ content.present? &&
19
+ content[:ols].present? &&
20
+ content[:metadata].present?
21
+ end
22
+
23
+ def self.create_dataset_with_metadata(container, content)
24
+ klass = find_dataset_klass(content[:ols])
25
+ return unless klass
26
+
27
+ dataset = create_dataset(container, klass)
28
+ build_result(dataset, content)
29
+ end
30
+
31
+ def self.find_dataset_klass(ols_term_id)
32
+ Labimotion::DatasetKlass.find_by(ols_term_id: ols_term_id)
33
+ end
34
+
35
+ def self.create_dataset(container, klass)
36
+ uuid = SecureRandom.uuid
37
+ props = prepare_properties(klass, uuid)
38
+
39
+ Labimotion::Dataset.create!(
40
+ uuid: uuid,
41
+ dataset_klass_id: klass.id,
42
+ element_type: 'Container',
43
+ element_id: container.id,
44
+ properties: props,
45
+ properties_release: klass.properties_release,
46
+ klass_uuid: klass.uuid
47
+ )
48
+ end
49
+
50
+ def self.prepare_properties(klass, uuid)
51
+ props = klass.properties_release
52
+ props['uuid'] = uuid
53
+ props['pkg'] = Labimotion::Utils.pkg(props['pkg'])
54
+ props['klass'] = 'Dataset'
55
+ props
56
+ end
57
+
58
+ def self.build_result(dataset, content)
59
+ {
60
+ dataset: dataset,
61
+ metadata: content[:metadata],
62
+ ols: content[:ols],
63
+ parameters: content[:parameters]
64
+ }
65
+ end
66
+
67
+ private_class_method :valid_input?, :create_dataset_with_metadata, :find_dataset_klass, :create_dataset,
68
+ :prepare_properties, :build_result
69
+ end
70
+ end
@@ -8,47 +8,190 @@ module Labimotion
8
8
  DEFAULT_ROW_WIDTH = 100
9
9
  DEFAULT_ROW_HEIGHT = 20
10
10
 
11
- def initialize(**args)
11
+ def initialize(id)
12
12
  @xfile = Axlsx::Package.new
13
- @file_extension = 'xlsx'
14
13
  @xfile.workbook.styles.fonts.first.name = 'Calibri'
14
+ @file_extension = 'xlsx'
15
+
16
+ @id = id
17
+ @dataset = Labimotion::Dataset.find_by(element_id: @id, element_type: 'Container')
18
+ return if @dataset.nil?
19
+
20
+ @klass = @dataset.dataset_klass
21
+ @ols_term_id = @klass.ols_term_id
22
+ @label = @klass.label
23
+ @analysis = @dataset&.element&.parent
24
+ @element = @analysis&.root&.containable if @analysis.present?
25
+ @element_type = @element.class.name if @element.present?
26
+ end
27
+
28
+ def read
29
+ @xfile.to_stream.read
15
30
  end
16
31
 
17
- def res_name(id)
18
- element_name = Container.find(id)&.root_element&.short_label
19
- ols = ols_name(id)
32
+ def res_name
33
+ element_name = Container.find(@id)&.root_element&.short_label
34
+ ols = ols_name
20
35
  "#{element_name}_#{ols.gsub(' ', '_')}.xlsx"
21
36
  rescue StandardError => e
22
37
  Labimotion.log_exception(e)
23
38
  end
24
39
 
25
- def ols_name(id)
26
- ds = Labimotion::Dataset.find_by(element_id: id, element_type: 'Container')
27
- return nil if ds.nil?
40
+ def spectra
41
+ name_mapping = []
42
+ ## gds = Labimotion::Dataset.find_by(element_id: id, element_type: 'Container')
43
+ cds = Container.find(@id)
44
+ cds_csv = cds.attachments.where(aasm_state: 'csv').order(:filename)
45
+ csv_length = cds_csv.length
46
+ return if csv_length.zero?
47
+
48
+ cds_csv.each_with_index do |att, idx|
49
+ sheet_name = "Sheet#{idx+1}"
50
+ sheet = @xfile.workbook.add_worksheet(name: sheet_name)
51
+ name_mapping.push([sheet_name, att.filename])
52
+ File.open(att.attachment_url) do |fi|
53
+ fi.each_line do |line|
54
+ sheet.add_row(line.split(','))
55
+ end
56
+ end
57
+ end
58
+ return unless name_mapping.length > 1
59
+
60
+ first_sheet = @xfile.workbook.worksheets&.first
61
+ header_style = first_sheet&.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
62
+ first_sheet&.add_row(['Sheet name', 'File name'], style: header_style)
63
+ name_mapping&.each do |mapping|
64
+ next if mapping.length < 2
65
+
66
+ @xfile.workbook.worksheets&.first&.add_row([mapping[0].to_s, mapping[1].to_s])
67
+ end
68
+ rescue StandardError => e
69
+ Labimotion.log_exception(e)
70
+ end
71
+
72
+ def export
73
+ return if @dataset.nil? || @analysis.nil? || @element.nil?
74
+
75
+ description
76
+ dataset_info
77
+ # element_info
78
+ chemwiki_info
79
+ rescue StandardError => e
80
+ Labimotion.log_exception(e)
81
+ end
82
+
83
+ private
84
+
85
+ def chemwiki_info
86
+ config = Labimotion::MapperUtils.load_config(File.read(Constants::Mapper::WIKI_CONFIG))
87
+ return if config.nil? || config[@ols_term_id].nil?
28
88
 
29
- name = ds.dataset_klass.label
89
+ sheet = @xfile.workbook.add_worksheet(name: 'ChemWiki')
90
+ map_index = config.dig(@ols_term_id, 'index')
91
+ map_mapper = config.dig(@ols_term_id, 'mapper')
92
+ map_source = config.dig(@ols_term_id, 'source')
30
93
 
31
- match = name.match(/\((.*?)\)/)
32
- name = match && match.length > 1 ? match[1] : name
94
+ return if map_index.nil? || map_mapper.nil? || map_source.nil?
33
95
 
34
- name = '1H NMR' if ds.dataset_klass.ols_term_id == 'CHMO:0000593'
35
- name = '13C NMR' if ds.dataset_klass.ols_term_id == 'CHMO:0000595'
96
+ return unless map_index.is_a?(Array) && map_mapper.is_a?(Hash) && map_source.is_a?(Hash)
97
+
98
+ # sheet.column_info.each { |col| col.width = map_width }
99
+
100
+ array_header = []
101
+ array_data = []
102
+ map_index.each do |key|
103
+ mapper = map_mapper.dig(key)
104
+ next if mapper.nil? || mapper['sources'].nil? || !mapper.is_a?(Hash)
105
+
106
+ col_header = ''
107
+ col_value = ''
108
+ mapper['sources'].each_with_index do |source_key, idx|
109
+ source = map_source&.dig(source_key)
110
+ next if source.nil? || source['title'].nil?
111
+
112
+ col_header = source['title']
113
+
114
+ if col_value.present?
115
+ col_value += (mapper['separator'] || '') + source_data(source)
116
+ else
117
+ col_value = source_data(source)
118
+ end
119
+ end
120
+ array_header.push(col_header || '')
121
+ array_data.push(col_value || '')
122
+ end
123
+ sheet.add_row(array_header)
124
+ sheet.add_row(array_data)
125
+ rescue StandardError => e
126
+ Labimotion.log_exception(e)
127
+ end
128
+
129
+
130
+ def conv_value(field, properties)
131
+ return '' if field.nil?
132
+
133
+ case field['type']
134
+ when 'select'
135
+ Labimotion::Utils.find_options_val(field, properties) || field['value']
136
+ else
137
+ field['value']
138
+ end
139
+ end
140
+
141
+ def source_data(source)
142
+ param = source['param']
143
+ return '' if param.nil? || source['type'].nil?
144
+
145
+ val = case source['type']
146
+ when 'string'
147
+ param
148
+ when 'sample'
149
+ @element.send(param) if @element.respond_to?(param)
150
+ when 'molecule'
151
+ @element.molecule.send(param) if @element_type == 'Sample' && @element&.molecule&.respond_to?(param)
152
+ when 'dataset'
153
+ field = Labimotion::Utils.find_field(@dataset.properties, param)
154
+ # (field && field['value']) || ''
155
+ conv_value(field, @dataset.properties)
156
+ end
157
+ val || ''
158
+ rescue StandardError => e
159
+ Labimotion.log_exception(e)
160
+ end
161
+
162
+ def element_info
163
+ if @element.class.name == 'Sample'
164
+ sheet = @xfile.workbook.add_worksheet(name: 'Element')
165
+ sheet.add_row(['inchikey', @element.molecule_inchikey])
166
+ sheet.add_row(['molfile', @element.molfile])
167
+ end
168
+ rescue StandardError => e
169
+ Labimotion.log_exception(e)
170
+ end
171
+
172
+ def ols_name
173
+ #name = @dataset.dataset_klass.label
174
+
175
+ match = @label.match(/\((.*?)\)/)
176
+ name = match && match.length > 1 ? match[1] : @label
177
+
178
+ name = '1H NMR' if @ols_term_id == 'CHMO:0000593'
179
+ name = '13C NMR' if @ols_term_id == 'CHMO:0000595'
36
180
  name.slice(0, 26)
37
181
  rescue StandardError => e
38
182
  Labimotion.log_exception(e)
39
183
  'ols_name'
40
184
  end
41
185
 
42
- def description(ds, id)
43
- wb = @xfile.workbook
186
+ def description
44
187
  sheet = @xfile.workbook.add_worksheet(name: 'Description')
45
188
  header_style = sheet.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
46
- sheet.add_row(['File name', res_name(id)])
189
+ sheet.add_row(['File name', res_name])
47
190
  sheet.add_row(['Time', Time.now.strftime("%Y-%m-%d %H:%M:%S %Z")] )
48
191
  sheet.add_row(['(This file is automatically generated by the system.)'])
49
192
  sheet.add_row([''])
50
193
  sheet.add_row([''])
51
- sheet.add_row(['Fields description of sheet:' + ds.dataset_klass.label])
194
+ sheet.add_row(['Fields description of sheet:' + @dataset.dataset_klass.label])
52
195
  sheet.add_row(['Fields', 'Field description'], style: header_style)
53
196
  sheet.add_row(['Layer Label', 'The label of the layer'])
54
197
  sheet.add_row(['Field Label', 'The label of the field'])
@@ -65,24 +208,18 @@ module Labimotion
65
208
  Labimotion.log_exception(e)
66
209
  end
67
210
 
68
- def export(id)
69
- ds = Labimotion::Dataset.find_by(element_id: id, element_type: 'Container')
70
- return if ds.nil?
71
-
72
- description(ds, id)
73
-
74
- wb = @xfile.workbook
75
- name = ols_name(id)
211
+ def dataset_info
212
+ name = ols_name
76
213
  return if name.nil?
77
214
 
78
215
  sheet = @xfile.workbook.add_worksheet(name: name)
79
- sheet.add_row([ds.dataset_klass.label])
216
+ sheet.add_row([@dataset.dataset_klass.label])
80
217
  header_style = sheet.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
81
218
  layer_style = sheet.styles.add_style(b: true, bg_color: 'CEECF5')
82
219
  sheet.add_row(header, style: header_style)
83
220
 
84
- layers = ds.properties[Labimotion::Prop::LAYERS] || {}
85
- options = ds.properties[Labimotion::Prop::SEL_OPTIONS]
221
+ layers = @dataset.properties[Labimotion::Prop::LAYERS] || {}
222
+ options = @dataset.properties[Labimotion::Prop::SEL_OPTIONS]
86
223
  layer_keys = layers.keys.sort_by { |key| layers[key]['position'] }
87
224
  layer_keys.each do |key|
88
225
  layer = layers[key]
@@ -116,8 +253,6 @@ module Labimotion
116
253
  end
117
254
  sheet.rows.last.cells[2].value = show_value
118
255
  sheet.rows.last.cells[8].value = field['system'] || field['device']
119
-
120
-
121
256
  end
122
257
  # sheet.column_widths nil, nil, nil, nil, 0, 0, 0, 0, 0
123
258
  end
@@ -136,45 +271,9 @@ module Labimotion
136
271
  field['value']
137
272
  end
138
273
 
139
- def spectra(id)
140
- name_mapping = []
141
- wb = @xfile.workbook
142
- gds = Labimotion::Dataset.find_by(element_id: id, element_type: 'Container')
143
- cds = Container.find(id)
144
- cds_csv = cds.attachments.where(aasm_state: 'csv').order(:filename)
145
- csv_length = cds_csv.length
146
- return if csv_length.zero?
147
- cds_csv.each_with_index do |att, idx|
148
- sheet_name = "Sheet#{idx+1}"
149
- sheet = @xfile.workbook.add_worksheet(name: sheet_name)
150
- name_mapping.push([sheet_name, att.filename])
151
- File.open(att.attachment_url) do |fi|
152
- fi.each_line do |line|
153
- sheet.add_row(line.split(','))
154
- end
155
- end
156
- end
157
-
158
- if name_mapping.length > 1
159
- first_sheet = @xfile.workbook.worksheets&.first
160
- header_style = first_sheet&.styles.add_style(sz: 12, fg_color: 'FFFFFF', bg_color: '00008B', border: { style: :thick, color: 'FF777777', edges: [:bottom] })
161
- first_sheet&.add_row(['Sheet name', 'File name'], style: header_style)
162
- name_mapping&.each do |mapping|
163
- next if mapping.length < 2
164
-
165
- @xfile.workbook.worksheets&.first&.add_row([mapping[0].to_s, mapping[1].to_s])
166
- end
167
- end
168
-
169
- end
170
-
171
274
  def header
172
275
  ['Layer Label', 'Field Label', 'Value', 'Unit', 'Name', 'Type', 'Source?', 'Source identifier', 'Source data', 'Ontology', 'Ontology Label', 'iri'].freeze
173
276
  end
174
277
 
175
- def read
176
- @xfile.to_stream.read
177
- end
178
-
179
278
  end
180
279
  end