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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1c30f358902beeb863766ddb2ee02b980b3cca7055f45babe20fb4211277772
4
- data.tar.gz: 86e1e46884b26fbfff1a91618698ab29072940109f9bc7c3d114b48a9b93ee86
3
+ metadata.gz: b55a7bdf8c25fd127bd7a7bab35676d74e3f3523cb55e03516cc28d3e2df738c
4
+ data.tar.gz: a28bad0092a10adc3befb26c3803d5f969d40bf9e387a7015890c2f81cd3089e
5
5
  SHA512:
6
- metadata.gz: 41655a864b15b848116b370964ae6a05c707512d6ba80987cdec1f392d3fb647476fcf119612f116a2923c4992e32b00127371ac8a77d6e7de6cf1dc94773dbd
7
- data.tar.gz: 8308707ad72ac2ebd38c725bc1336151712b5900fa4f35429674ee54f26cbe6fcc7ed43ef71777b6dd069701411540c776a7f183b183d147c1a3658a124e12a7
6
+ metadata.gz: 94b3f84c3b2588b08f19c66bafdd17fb9eef3674040bd3dc0683132a4b5709c11f643e81afda2109741da24e4a38c6b407c4eff279c00c9292ef0942611c4ec8
7
+ data.tar.gz: 19082b803643920e698b9f14c1ce89b68aac5121a5adeab473d86c16c7129ba1d9e024e1bcec83b7c802ed79409183e1129967881295b66c363912652d563191
@@ -12,6 +12,7 @@ module Labimotion
12
12
  helpers CollectionHelpers
13
13
  helpers UserLabelHelpers
14
14
  helpers Labimotion::SampleAssociationHelpers
15
+ helpers Labimotion::VocabularyHelpers
15
16
  helpers Labimotion::GenericHelpers
16
17
  helpers Labimotion::ElementHelpers
17
18
  helpers Labimotion::ParamHelpers
@@ -6,7 +6,7 @@ require 'labimotion/libs/export_element'
6
6
  module Labimotion
7
7
  # Generic Element API
8
8
  class GenericKlassAPI < Grape::API
9
-
9
+
10
10
  resource :generic_klass do
11
11
  namespace :download_klass do
12
12
  desc 'export klass'
@@ -28,7 +28,8 @@ module Labimotion
28
28
  Labimotion.log_exception(e, current_user)
29
29
  {}
30
30
  end
31
- end
31
+ end
32
+
32
33
  end
33
34
  end
34
35
  end
@@ -0,0 +1,13 @@
1
+ # app/api/labimotion/central_api.rb
2
+ module Labimotion
3
+ class LabimotionAPI < Grape::API
4
+ mount Labimotion::ConverterAPI
5
+ mount Labimotion::GenericKlassAPI
6
+ mount Labimotion::GenericElementAPI
7
+ mount Labimotion::GenericDatasetAPI
8
+ mount Labimotion::SegmentAPI
9
+ mount Labimotion::LabimotionHubAPI
10
+ mount Labimotion::StandardLayerAPI
11
+ mount Labimotion::VocabularyAPI
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/version'
4
+ require 'labimotion/libs/export_element'
5
+
6
+ module Labimotion
7
+ # Generic Element API
8
+ class StandardAPI < Grape::API
9
+ resource :standards do
10
+ namespace :create_std_layer do
11
+ desc 'create standard layer'
12
+ params do
13
+ use :create_std_layer_params
14
+ end
15
+ post do
16
+ authenticate_admin!('standard_layers')
17
+ create_std_layer(current_user, params)
18
+ status 201
19
+ rescue ActiveRecord::RecordInvalid => e
20
+ { error: e.message }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/version'
4
+
5
+ module Labimotion
6
+ # Generic Element API
7
+ class StandardLayerAPI < Grape::API
8
+ include Grape::Kaminari
9
+ helpers Labimotion::ParamHelpers
10
+ helpers Labimotion::GenericHelpers
11
+
12
+ resource :layers do
13
+ namespace :get_all_layers do
14
+ desc 'get all standard layers for designer'
15
+ get do
16
+ list = Labimotion::StdLayer.all.sort_by { |e| e.name }
17
+ return { mc: 'ss00', data: list }
18
+ rescue StandardError => e
19
+ Labimotion.log_exception(e, current_user)
20
+ { mc: 'se00', msg: e.message, data: [] }
21
+ end
22
+ end
23
+
24
+ namespace :get_standard_layer do
25
+ desc 'get standard layer by id'
26
+ route_param :id do
27
+ get do
28
+ authenticate_admin!('standard_layers')
29
+ entity = Labimotion::StdLayer.find(params[:id])
30
+ return { mc: 'ss00', data: entity }
31
+ rescue StandardError => e
32
+ Labimotion.log_exception(e, current_user)
33
+ { mc: 'se00', msg: e.message, data: {} }
34
+ end
35
+ end
36
+ end
37
+
38
+ namespace :save_standard_layer do
39
+ desc 'create Generic Element Klass'
40
+ params do
41
+ use :std_layer_save
42
+ end
43
+ before do
44
+ authenticate_admin!('standard_layers')
45
+ cur_layer = Labimotion::StdLayer.find_by(name: params[:key])
46
+ error!('Error! duplicate name', 409) if cur_layer.present?
47
+ end
48
+ post do
49
+ attributes = {
50
+ name: params[:key],
51
+ label: params[:label],
52
+ description: params[:description],
53
+ identifier: SecureRandom.uuid,
54
+ created_by: current_user.id,
55
+ properties: declared(params, include_missing: false)
56
+ }
57
+ layer = Labimotion::StdLayer.new(attributes)
58
+ layer.save!
59
+ { mc: 'ss00', data: layer }
60
+ rescue ActiveRecord::RecordInvalid => e
61
+ Labimotion.log_exception(e, current_user)
62
+ { mc: 'se00', msg: e.message, data: {} }
63
+ end
64
+ end
65
+
66
+ namespace :delete_standard_layer do
67
+ desc 'delete standard layer by id'
68
+ params do
69
+ requires :id, type: Integer, desc: 'Standard layer id'
70
+ end
71
+ route_param :id do
72
+ before do
73
+ authenticate_admin!('standard_layers')
74
+ end
75
+ delete do
76
+ entity = Labimotion::StdLayer.find(params[:id])
77
+ entity.destroy
78
+ return { mc: 'ss00', data: {} }
79
+ rescue StandardError => e
80
+ Labimotion.log_exception(e, current_user)
81
+ { mc: 'se00', msg: e.message, data: [] }
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/version'
4
+
5
+ module Labimotion
6
+ # Generic Element API
7
+ class VocabularyAPI < Grape::API
8
+ include Grape::Kaminari
9
+ helpers Labimotion::ParamHelpers
10
+ helpers Labimotion::GenericHelpers
11
+
12
+ resource :vocab do
13
+ namespace :save_vocabulary do
14
+ desc 'Save vocabularies'
15
+ params do
16
+ use :vocab_save
17
+ end
18
+ before do
19
+ authenticate_admin!('vocabularies')
20
+ rescue ActiveRecord::RecordNotFound
21
+ error!('404 Not Found', 404)
22
+ end
23
+ post do
24
+ attributes = {
25
+ name: params[:name],
26
+ label: params[:label],
27
+ field_type: params[:field_type],
28
+ opid: 8,
29
+ term_id: params[:term_id],
30
+ source: params[:source],
31
+ source_id: params[:source_id],
32
+ layer_id: params[:layer_id],
33
+ field_id: params[:name],
34
+ identifier: params[:source_id],
35
+ created_by: current_user.id,
36
+ properties: declared(params, include_missing: false),
37
+ }
38
+ voc = Labimotion::Vocabulary.new(attributes)
39
+ voc.save!
40
+ { mc: 'ss00', data: voc }
41
+ rescue StandardError => e
42
+ Labimotion.log_exception(e, current_user)
43
+ { mc: 'se00', msg: e.message, data: {} }
44
+ end
45
+ end
46
+
47
+ namespace :get_all_vocabularies do
48
+ desc 'get all standard layers for designer'
49
+ get do
50
+ authenticate_admin!('vocabularies')
51
+ combined_data = Labimotion::VocabularyHandler.load_all_vocabularies
52
+ return { mc: 'ss00', data: combined_data }
53
+ rescue StandardError => e
54
+ Labimotion.log_exception(e, current_user)
55
+ { mc: 'se00', msg: e.message, data: [] }
56
+ end
57
+ end
58
+
59
+ namespace :field_klasses do
60
+ desc 'get all field klasses for admin function'
61
+ get do
62
+ authenticate_admin!('vocabularies')
63
+ vocabularies = Labimotion::VocabularyHandler.load_app_vocabularies
64
+ merged_data = Labimotion::FieldKlassEntity.represent(vocabularies, serializable: true)
65
+ merged_data
66
+ rescue StandardError => e
67
+ Labimotion.log_exception(e, current_user)
68
+ []
69
+ end
70
+ end
71
+
72
+ namespace :delete_vocabulary do
73
+ desc 'delete vocabulary by id'
74
+ params do
75
+ requires :id, type: Integer, desc: 'Vocabulary id'
76
+ end
77
+ route_param :id do
78
+ before do
79
+ authenticate_admin!('vocabularies')
80
+ end
81
+ delete do
82
+ entity = Labimotion::Vocabulary.find(params[:id])
83
+ entity.destroy
84
+ return { mc: 'ss00', data: {} }
85
+ rescue StandardError => e
86
+ Labimotion.log_exception(e, current_user)
87
+ { mc: 'se00', msg: e.message, data: [] }
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ module Constants
5
+ module DateTime
6
+ DATE_FORMAT = '%Y-%m-%d'
7
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
8
+ TIME_FORMAT = '%H:%M:%S %Z'
9
+ TIME_ZONE = 'UTC'
10
+ end
11
+
12
+ module File
13
+ ENCODING = 'UTF-8'
14
+ end
15
+
16
+ module Mapper
17
+ NMR_CONFIG = ::File.join(__dir__, 'libs', 'data', 'mapper', 'Source.json').freeze
18
+ WIKI_CONFIG = ::File.join(__dir__, 'libs', 'data', 'mapper', 'Chemwiki.json').freeze
19
+ end
20
+ end
21
+ end
@@ -3,7 +3,7 @@
3
3
  require 'labimotion/entities/application_entity'
4
4
  module Labimotion
5
5
  # Dataset entity
6
- class DatasetEntity < ApplicationEntity
6
+ class DatasetEntity < PropertiesEntity
7
7
  expose :id, :dataset_klass_id, :properties, :properties_release, :element_id, :element_type, :klass_ols, :klass_label, :klass_uuid
8
8
  def klass_ols
9
9
  object&.dataset_klass&.ols_term_id
@@ -20,6 +20,7 @@ module Labimotion
20
20
  expose! :thumb_svg
21
21
  expose! :type
22
22
  expose! :uuid
23
+ expose! :user_labels
23
24
  end
24
25
 
25
26
  with_options(anonymize_below: 10) do
@@ -1,91 +1,264 @@
1
1
  require 'labimotion/entities/application_entity'
2
2
 
3
- # Entity module
4
3
  module Labimotion
5
4
  class PropertiesEntity < Labimotion::ApplicationEntity
6
-
7
- # TODO: Refactor this method to something more readable/understandable
8
5
  def properties
9
- (object&.properties.is_a?(Hash) && object.properties[Labimotion::Prop::LAYERS]&.keys || []).each do |key|
10
- # layer = object.properties[key]
11
- field_sample_molecules = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].select { |ss| ss['type'] == Labimotion::FieldType::DRAG_SAMPLE || ss['type'] == Labimotion::FieldType::DRAG_MOLECULE }
12
- field_sample_molecules.each do |field|
13
- idx = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].index(field)
14
- sid = field.dig('value', 'el_id')
15
- next unless sid.present?
16
-
17
- el = field['type'] == Labimotion::FieldType::DRAG_SAMPLE ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
18
- next unless el.present?
19
- next unless object.properties.dig(Labimotion::Prop::LAYERS, key, Labimotion::Prop::FIELDS, idx, 'value').present?
20
-
21
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_label'] = el.short_label if field['type'] == Labimotion::FieldType::DRAG_SAMPLE
22
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_tip'] = el.short_label if field['type'] == Labimotion::FieldType::DRAG_SAMPLE
23
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_svg'] = field['type'] == Labimotion::FieldType::DRAG_SAMPLE ? el.get_svg_path : File.join('/images', 'molecules', el&.molecule_svg_file || 'nosvg')
24
- end
6
+ process_layers do |key, layer|
7
+ process_fields(key, layer)
8
+ end
9
+ object.properties
10
+ end
25
11
 
26
- field_sys_reactions = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].select { |ss| ss['type'] == Labimotion::FieldType::SYS_REACTION }
27
- field_sys_reactions.each do |field|
28
- idx = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].index(field)
29
- sid = field.dig('value', 'el_id')
30
- next unless sid.present?
12
+ private
31
13
 
32
- el = Reaction.find_by(id: sid)
33
- if el.blank?
34
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_tip'] = 'ERROR'
35
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_svg'] = ''
36
- end
14
+ def process_layers
15
+ (object&.properties.is_a?(Hash) && (object.properties[Labimotion::Prop::LAYERS]&.keys || [])).each do |key|
16
+ yield(key, object.properties[Labimotion::Prop::LAYERS][key])
17
+ end
18
+ end
37
19
 
38
- next unless el.present?
39
- next unless object.properties.dig(Labimotion::Prop::LAYERS, key, Labimotion::Prop::FIELDS, idx, 'value').present?
20
+ def process_fields(key, layer)
21
+ process_sample_and_molecule_fields(key, layer)
22
+ process_reaction_fields(key, layer)
23
+ process_table_fields(key, layer)
24
+ # process_voc_fields(key, layer)
25
+ end
40
26
 
41
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_label'] = el.short_label
42
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_tip'] = el.short_label
43
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]['value']['el_svg'] = el.reaction_svg_file
44
- end
27
+ def process_sample_and_molecule_fields(key, layer)
28
+ select_fields(layer,
29
+ [Labimotion::FieldType::DRAG_SAMPLE, Labimotion::FieldType::DRAG_MOLECULE]).each do |field, idx|
30
+ update_sample_or_molecule_field(key, field, idx)
31
+ end
32
+ end
33
+
34
+ def process_reaction_fields(key, layer)
35
+ select_fields(layer, [Labimotion::FieldType::SYS_REACTION]).each do |field, idx|
36
+ update_reaction_field(key, field, idx)
37
+ end
38
+ end
39
+
40
+ def process_table_fields(key, layer)
41
+ select_fields(layer, [Labimotion::FieldType::TABLE]).each do |field, idx|
42
+ update_table_field(key, field, idx)
43
+ end
44
+ end
45
+
46
+ def process_voc_fields(key, layer)
47
+ select_fields(layer, nil, true).each do |field, idx|
48
+ update_voc_field(key, field, idx)
49
+ end
50
+ end
51
+
52
+ def select_fields(layer, types = nil, is_voc = false)
53
+ fields = layer[Labimotion::Prop::FIELDS]
54
+ fields = fields.select { |f| types.include?(f['type']) } if types
55
+ fields = fields.select { |f| f['is_voc'] == true } if is_voc
56
+ fields.map { |f| [f, layer[Labimotion::Prop::FIELDS].index(f)] }
57
+ end
58
+
59
+ def update_sample_or_molecule_field(key, field, idx)
60
+ sid = field.dig('value', 'el_id')
61
+ return unless sid.present?
62
+
63
+ el = field['type'] == Labimotion::FieldType::DRAG_SAMPLE ? Sample.find_by(id: sid) : Molecule.find_by(id: sid)
64
+ return unless el.present? && object.properties.dig(Labimotion::Prop::LAYERS, key, Labimotion::Prop::FIELDS, idx,
65
+ 'value').present?
66
+
67
+ label = field['type'] == Labimotion::FieldType::DRAG_SAMPLE ? el&.short_label : el.iupac_name
68
+ update_field_value(key, idx, {
69
+ 'el_label' => label,
70
+ 'el_tip' => label,
71
+ 'el_svg' => if field['type'] == Labimotion::FieldType::DRAG_SAMPLE
72
+ el&.get_svg_path
73
+ else
74
+ File.join('/images',
75
+ 'molecules', el&.molecule_svg_file || 'nosvg')
76
+ end
77
+ })
78
+ end
79
+
80
+ def update_reaction_field(key, field, idx)
81
+ sid = field.dig('value', 'el_id')
82
+ return unless sid.present?
83
+
84
+ el = Reaction.find_by(id: sid)
85
+ if el.blank?
86
+ update_field_value(key, idx, { 'el_tip' => 'ERROR', 'el_svg' => '' })
87
+ return
88
+ end
89
+
90
+ return unless object.properties.dig(Labimotion::Prop::LAYERS, key, Labimotion::Prop::FIELDS, idx,
91
+ 'value').present?
92
+
93
+ update_field_value(key, idx, {
94
+ 'el_label' => el.short_label,
95
+ 'el_tip' => el.short_label,
96
+ 'el_svg' => el.reaction_svg_file
97
+ })
98
+ end
99
+
100
+ def update_table_field(key, field, idx)
101
+ return unless field['sub_values'].present? && field[Labimotion::Prop::SUBFIELDS].present?
102
+
103
+ field_table_molecules = field[Labimotion::Prop::SUBFIELDS].select do |ss|
104
+ ss['type'] == Labimotion::FieldType::DRAG_MOLECULE
105
+ end
106
+ if field_table_molecules.present?
107
+ object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] =
108
+ set_table(field, field_table_molecules, Labimotion::Prop::MOLECULE)
109
+ end
110
+
111
+ field_table_samples = field[Labimotion::Prop::SUBFIELDS].select do |ss|
112
+ ss['type'] == Labimotion::FieldType::DRAG_SAMPLE
113
+ end
114
+ return unless field_table_samples.present?
115
+
116
+ object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] =
117
+ set_table(field, field_table_samples, Labimotion::Prop::SAMPLE)
118
+ end
119
+
120
+ def update_voc_field(key, field, idx)
121
+ root_element = get_root_element
122
+ case field['source']
123
+ when Labimotion::Prop::ELEMENT
124
+ update_element_voc_field(key, field, idx, root_element)
125
+ when Labimotion::Prop::SEGMENT
126
+ update_segment_voc_field(key, field, idx, root_element)
127
+ when Labimotion::Prop::DATASET
128
+ update_dataset_voc_field(key, field, idx, root_element)
129
+ end
130
+ end
45
131
 
46
- field_tables = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].select { |ss| ss['type'] == Labimotion::FieldType::TABLE }
47
- field_tables.each do |field|
48
- idx = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS].index(field)
49
- next unless field['sub_values'].present? && field[Labimotion::Prop::SUBFIELDS].present?
132
+ def get_root_element
133
+ case object.class.name
134
+ when Labimotion::Prop::L_ELEMENT
135
+ object
136
+ when Labimotion::Prop::L_SEGMENT
137
+ object&.element
138
+ when Labimotion::Prop::L_DATASET
139
+ object&.element&.root_element
140
+ end
141
+ end
50
142
 
51
- field_table_molecules = field[Labimotion::Prop::SUBFIELDS].select { |ss| ss['type'] == Labimotion::FieldType::DRAG_MOLECULE }
52
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] = set_table(field, field_table_molecules, Labimotion::Prop::MOLECULE) if field_table_molecules.present?
143
+ def update_element_voc_field(key, field, idx, root_element)
144
+ return unless field['identifier'] == 'element.name'
145
+
146
+ update_field_value(key, idx, root_element&.name)
147
+ end
53
148
 
54
- field_table_samples = field[Labimotion::Prop::SUBFIELDS].select { |ss| ss['type'] == Labimotion::FieldType::DRAG_SAMPLE }
55
- object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx] = set_table(field, field_table_samples, Labimotion::Prop::SAMPLE) if field_table_samples.present?
149
+ def update_segment_voc_field(key, field, idx, root_element)
150
+ segs = root_element&.segments&.select { |ss| field['source_id'] == ss.segment_klass&.identifier }
151
+ return if segs.empty? || field['layer_id'].blank? || field['field_id'].blank?
152
+
153
+ seg = segs&.first
154
+ seg_fields = seg.properties.dig(Labimotion::Prop::LAYERS, field['layer_id'],
155
+ Labimotion::Prop::FIELDS).select do |ff|
156
+ ff['field'] == field['field_id']
157
+ end
158
+ seg_field = seg_fields&.first
159
+ update_field_value(key, idx, seg_field['value'])
160
+ end
161
+
162
+ def update_dataset_voc_field(key, field, idx, root_element)
163
+ dk = DatasetKlass.find_by(identifier: field['source_id'])
164
+ dk['ols_term_id']
165
+ anas = root_element.analyses.select do |ana|
166
+ ana.extended_metadata['kind'].split('|')&.first&.strip == dk['ols_term_id']
167
+ end
168
+ anas.each do |ana|
169
+ ana.children.each do |cds|
170
+ next unless cds.dataset.present?
171
+
172
+ ds_prop = cds.dataset.properties
173
+ ds_fields = ds_prop.dig(Labimotion::Prop::LAYERS, field['layer_id'], Labimotion::Prop::FIELDS).select do |ff|
174
+ ff['field'] == field['field_id']
175
+ end
176
+ ds_field = ds_fields&.first
177
+ if object.properties[Labimotion::Prop::LAYERS][key].present? && ds_field['value'].present?
178
+ update_field_value(key, idx, ds_field['value'])
179
+ end
56
180
  end
57
181
  end
58
- object.properties
182
+ end
183
+
184
+ def update_field_value(key, idx, value, act = 'merge')
185
+ field_path = object.properties[Labimotion::Prop::LAYERS][key][Labimotion::Prop::FIELDS][idx]
186
+ original_value = field_path['value']
187
+
188
+ field_path['value'] = merge_values(original_value, value, act)
189
+ end
190
+
191
+ def merge_by_type(original_value, new_value)
192
+ if original_value.is_a?(Hash)
193
+ merge_hash_values(original_value, new_value)
194
+ # elsif original_value.is_a?(Array)
195
+ # merge_array_values(original_value, new_value)
196
+ else
197
+ new_value
198
+ end
199
+ end
200
+
201
+ def merge_values(original_value, new_value, act)
202
+ return new_value if act == 'overwrite'
203
+ return new_value if original_value.blank?
204
+ return original_value if new_value.blank?
205
+
206
+ merge_by_type(original_value, new_value)
59
207
  end
60
208
 
61
209
  def set_table(field, field_table_objs, obj)
62
210
  col_ids = field_table_objs.map { |x| x.values[0] }
63
211
  col_ids.each do |col_id|
64
212
  field['sub_values'].each do |sub_value|
65
- next unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
213
+ unless sub_value[col_id].present? && sub_value[col_id]['value'].present? && sub_value[col_id]['value']['el_id'].present?
214
+ next
215
+ end
66
216
 
67
217
  find_obj = obj.constantize.find_by(id: sub_value[col_id]['value']['el_id'])
68
218
  next if find_obj.blank?
69
219
 
70
220
  case obj
71
221
  when Labimotion::Prop::MOLECULE
72
- sub_value[col_id]['value']['el_svg'] = File.join('/images', 'molecules', find_obj.molecule_svg_file) if find_obj&.molecule_svg_file&.present?
73
- sub_value[col_id]['value']['el_inchikey'] = find_obj.inchikey
74
- sub_value[col_id]['value']['el_smiles'] = find_obj.cano_smiles
75
- sub_value[col_id]['value']['el_iupac'] = find_obj.iupac_name
76
- sub_value[col_id]['value']['el_molecular_weight'] = find_obj.molecular_weight
222
+ update_molecule_sub_value(sub_value, col_id, find_obj)
77
223
  when Labimotion::Prop::SAMPLE
78
- sub_value[col_id]['value']['el_svg'] = find_obj.get_svg_path
79
- sub_value[col_id]['value']['el_label'] = find_obj.short_label
80
- sub_value[col_id]['value']['el_short_label'] = find_obj.short_label
81
- sub_value[col_id]['value']['el_name'] = find_obj.name
82
- sub_value[col_id]['value']['el_external_label'] = find_obj.external_label
83
- sub_value[col_id]['value']['el_molecular_weight'] = find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
224
+ update_sample_sub_value(sub_value, col_id, find_obj)
84
225
  end
85
226
  end
86
227
  end
87
228
  field
88
229
  end
89
230
 
231
+ def update_molecule_sub_value(sub_value, col_id, find_obj)
232
+ sub_value[col_id]['value'].merge!({
233
+ 'el_svg' => File.join('/images', 'molecules', find_obj.molecule_svg_file),
234
+ 'el_inchikey' => find_obj.inchikey,
235
+ 'el_smiles' => find_obj.cano_smiles,
236
+ 'el_iupac' => find_obj.iupac_name,
237
+ 'el_molecular_weight' => find_obj.molecular_weight
238
+ })
239
+ end
240
+
241
+ def update_sample_sub_value(sub_value, col_id, find_obj)
242
+ sub_value[col_id]['value'].merge!({
243
+ 'el_svg' => find_obj.get_svg_path,
244
+ 'el_label' => find_obj.short_label,
245
+ 'el_short_label' => find_obj.short_label,
246
+ 'el_name' => find_obj.name,
247
+ 'el_external_label' => find_obj.external_label,
248
+ 'el_molecular_weight' => find_obj.decoupled ? find_obj.molecular_mass : find_obj.molecule.molecular_weight
249
+ })
250
+ end
251
+
252
+ def merge_hash_values(original, new_value)
253
+ return original unless new_value.is_a?(Hash)
254
+
255
+ original.merge(new_value)
256
+ end
257
+
258
+ def merge_array_values(original, new_value)
259
+ return original unless new_value.respond_to?(:to_a)
260
+
261
+ (original + new_value.to_a).uniq
262
+ end
90
263
  end
91
264
  end
@@ -9,6 +9,5 @@ module Labimotion
9
9
  def klass_label
10
10
  object.segment_klass.label
11
11
  end
12
-
13
12
  end
14
13
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'labimotion/entities/application_entity'
4
+ module Labimotion
5
+ # Dataset entity
6
+ class VocabularyEntity < ApplicationEntity
7
+ expose :id, :identifier, :name, :label, :field_type, :opid, :term_id,
8
+ :field_id, :properties, :source, :source_id, :layer_id
9
+ expose :voc do |obj|
10
+ voc = (obj[:properties] && obj[:properties]['voc']) || {}
11
+
12
+ case voc['source']
13
+ when Labimotion::Prop::ELEMENT
14
+ if voc['identifier'] == 'element.name'
15
+ # voc['source_name'] = ElementKlass.find_by(identifier: voc['source_id'])&.name
16
+ end
17
+ when Labimotion::Prop::SEGMENT
18
+ voc['source_name'] = SegmentKlass.find_by(identifier: voc['source_id'])&.label
19
+ when Labimotion::Prop::DATASET
20
+ voc['source_name'] = DatasetKlass.find_by(identifier: voc['source_id'])&.label
21
+ end
22
+ voc
23
+ end
24
+ expose :ontology do |obj|
25
+ (obj[:properties] && obj[:properties]['ontology']) || {}
26
+ end
27
+ end
28
+ end