labimotion 2.2.0.rc15 → 2.2.0.rc17

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2299d3c8a510830bb38ab2ea17455dc1953d02839f6ddc184391b49a653fcfe0
4
- data.tar.gz: 5611b57ea435c6cac0cc14d3300e8abe80eedf0ffcc74043501ea6a1fd55cdad
3
+ metadata.gz: 1c5a8e890d23ca465b50fcb79e7cb437d2cbecada3141b42cbbf288c5bde00ff
4
+ data.tar.gz: df0c4bca0642d4d29cd9844088a7a2bd656fb240c1e573e63a366bd26a3bff36
5
5
  SHA512:
6
- metadata.gz: c817a0528d4a02e1de11261482daff54b19682215e7abc2fb76b452a845b6f49a59c3048c5bf2771f15a9e67cbac337dcd07ce85df67ac4b1e4e04d482c351da
7
- data.tar.gz: 90b1f64be5bf16bf7e514ec0530163e9194e3e036839354d86e416520fc0b73e2b639d2620d3ccad07300d22f90a551256db16c892a9014885c88cbb123d8bb3
6
+ metadata.gz: 2b1522bf995bf6d7ecc88b5f80d2c4c24bed210501cd328a79e91d07bdeda984c51aca9259f5f70b80588f6b43e19b8eb090634071b6c2ae8fd2f08481099fe2
7
+ data.tar.gz: df75a698a49478ae259c64bbfc854ad855ad8ed3fe096225a5bcd4a0390ebca6f04b0ccb82122d58f689d675b4b5d07dcaa3d107d35ba1ae6a3f9e9b81c6ad10
@@ -17,5 +17,6 @@ module Labimotion
17
17
  mount Labimotion::ElementVariationAPI
18
18
  mount Labimotion::LabimotionDoiAPI
19
19
  mount Labimotion::LabimotionTemplateBrowseAPI
20
+ mount Labimotion::WellplateAPI
20
21
  end
21
22
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ # API for wellplates linked to a generic element
5
+ class WellplateAPI < Grape::API
6
+ resource :wellplates do
7
+ namespace :by_generic_element do
8
+ desc 'Get wellplates for a generic element'
9
+ params do
10
+ requires :element_id, type: Integer, desc: 'Generic element id'
11
+ end
12
+ route_param :element_id do
13
+ get do
14
+ element = Labimotion::Element.find_by(id: params[:element_id])
15
+ error!('404 Not Found', 404) unless element
16
+ error!('401 Unauthorized', 401) unless ElementPolicy.new(current_user, element).read?
17
+
18
+ wellplate_ids = Labimotion::ElementsWellplate.where(element_id: element.id).pluck(:wellplate_id)
19
+ wellplates = Wellplate.where(id: wellplate_ids)
20
+ .includes(:wells, wells: :sample)
21
+
22
+ serialized_wellplates = wellplates.map do |wellplate|
23
+ detail_levels = ElementDetailLevelCalculator.new(user: current_user, element: wellplate).detail_levels
24
+ Entities::WellplateEntity.represent(wellplate, detail_levels: detail_levels)
25
+ end
26
+
27
+ { wellplates: serialized_wellplates }
28
+ end
29
+
30
+ desc 'Update wellplates for a generic element'
31
+ params do
32
+ requires :wellplate_ids, type: Array, desc: 'Wellplate IDs'
33
+ end
34
+ put do
35
+ element = Labimotion::Element.find_by(id: params[:element_id])
36
+ error!('404 Not Found', 404) unless element
37
+ error!('401 Unauthorized', 401) unless ElementPolicy.new(current_user, element).update?
38
+
39
+ ActiveRecord::Base.transaction do
40
+ current_ids = Labimotion::ElementsWellplate.where(element_id: element.id).pluck(:wellplate_id)
41
+ new_ids = params[:wellplate_ids] || []
42
+
43
+ ids_to_remove = current_ids - new_ids
44
+ if ids_to_remove.any?
45
+ Labimotion::ElementsWellplate.where(element_id: element.id, wellplate_id: ids_to_remove).destroy_all
46
+ end
47
+
48
+ ids_to_add = new_ids - current_ids
49
+ ids_to_add.each do |wellplate_id|
50
+ Labimotion::ElementsWellplate.create!(element_id: element.id, wellplate_id: wellplate_id)
51
+ end
52
+ end
53
+
54
+ { wellplate_ids: Labimotion::ElementsWellplate.where(element_id: element.id).pluck(:wellplate_id) }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -9,7 +9,6 @@
9
9
  "file": "acqus",
10
10
  "parameters": [
11
11
  "DATE",
12
- "D1",
13
12
  "INSTRUM",
14
13
  "NS",
15
14
  "NUC1",
@@ -23,7 +22,10 @@
23
22
  "TD",
24
23
  "TE",
25
24
  "TITLE"
26
- ]
25
+ ],
26
+ "arrayParameters": {
27
+ "D1": { "name": "D", "index": 1 }
28
+ }
27
29
  },
28
30
  "procs": {
29
31
  "file": "pdata/1/procs",
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ class ElementsWellplate < ApplicationRecord
5
+ acts_as_paranoid
6
+ self.table_name = :elements_wellplates
7
+ belongs_to :element, class_name: 'Labimotion::Element'
8
+ belongs_to :wellplate
9
+ end
10
+ end
@@ -70,6 +70,37 @@ module Labimotion
70
70
  extracted_parameters
71
71
  end
72
72
 
73
+ # Extracts scalar values from Bruker array parameters such as
74
+ # ##$D= (0..63)
75
+ # 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0002 ...
76
+ # where the values live on the line(s) following the header. The config maps
77
+ # each output key to an array name + index, e.g.
78
+ # { "D1" => { "name" => "D", "index" => 1 } } => D1 = the 2nd value (here 1).
79
+ def extract_array_parameters(file_content, array_parameters)
80
+ return {} if file_content.blank? || array_parameters.blank?
81
+
82
+ lines = file_content.lines
83
+ extracted = {}
84
+ lines.each_with_index do |line, idx|
85
+ header = line.match(/^\s*##\$(?<name>[A-Za-z0-9_]+)\s*=\s*\(\s*\d+\s*\.\.\s*\d+\s*\)/)
86
+ next unless header
87
+
88
+ targets = array_parameters.select { |_key, cfg| cfg['name'] == header[:name] }
89
+ next if targets.empty?
90
+
91
+ values = collect_array_values(lines, idx + 1)
92
+ targets.each do |out_key, cfg|
93
+ value = values[cfg['index'].to_i]
94
+ extracted[out_key] = clean_value(value) if value.present?
95
+ end
96
+ end
97
+ extracted.compact_blank!
98
+ extracted
99
+ rescue StandardError => e
100
+ Rails.logger.error "Error extracting array parameters: #{e.message}"
101
+ {}
102
+ end
103
+
73
104
  def format_timestamp(timestamp_str, give_format = nil)
74
105
  return nil if timestamp_str.blank?
75
106
 
@@ -118,6 +149,21 @@ module Labimotion
118
149
  value
119
150
  end
120
151
 
152
+ # Collects whitespace-separated values from the line(s) following an array
153
+ # header, stopping at the next directive (line starting with '##') or a blank line.
154
+ def collect_array_values(lines, start_index)
155
+ values = []
156
+ index = start_index
157
+ while index < lines.length
158
+ stripped = lines[index].strip
159
+ break if stripped.empty? || stripped.start_with?('##')
160
+
161
+ values.concat(stripped.split(/\s+/))
162
+ index += 1
163
+ end
164
+ values
165
+ end
166
+
121
167
  def process_zip_file(zip_file_url, source_map)
122
168
  final_parameters = {}
123
169
 
@@ -137,23 +183,28 @@ module Labimotion
137
183
 
138
184
  zip_file.each do |entry|
139
185
  if source_file?(entry, source_config)
140
- process_file_entry(entry, source_config['parameters'], final_parameters)
186
+ process_file_entry(entry, source_config, final_parameters)
141
187
  elsif bagit_metadata_file?(entry)
142
188
  return { is_bagit: true, metadata: nil }
143
189
  end
144
190
  end
145
191
  end
146
192
 
147
- def process_file_entry(entry, parameters, final_parameters)
193
+ def process_file_entry(entry, source_config, final_parameters)
148
194
  file_content = entry.get_input_stream.read.force_encoding(Constants::File::ENCODING)
149
- extracted_parameters = extract_parameters(file_content, parameters)
195
+ extracted_parameters = extract_parameters(file_content, source_config['parameters'])
150
196
  final_parameters.merge!(extracted_parameters) if extracted_parameters.present?
197
+
198
+ # Array parameters (e.g. D1 from acqus ##$D) are a fallback: they only fill a
199
+ # value that an earlier/higher-priority source (e.g. parm.txt D1) did not provide.
200
+ array_parameters = extract_array_parameters(file_content, source_config['arrayParameters'])
201
+ final_parameters.reverse_merge!(array_parameters) if array_parameters.present?
151
202
  end
152
203
 
153
204
  def invalid_source_config?(source_config)
154
205
  source_config.nil? ||
155
206
  source_config['file'].nil? ||
156
- source_config['parameters'].nil?
207
+ (source_config['parameters'].nil? && source_config['arrayParameters'].nil?)
157
208
  end
158
209
 
159
210
  def source_file?(entry, source_config)
@@ -2,5 +2,5 @@
2
2
 
3
3
  ## Labimotion Version
4
4
  module Labimotion
5
- VERSION = '2.2.0.rc15'
5
+ VERSION = '2.2.0.rc17'
6
6
  end
data/lib/labimotion.rb CHANGED
@@ -32,6 +32,7 @@ module Labimotion
32
32
  autoload :ElementVariationAPI, 'labimotion/apis/element_variation_api'
33
33
  autoload :LabimotionDoiAPI, 'labimotion/apis/labimotion_doi_api'
34
34
  autoload :LabimotionTemplateBrowseAPI, 'labimotion/apis/labimotion_template_browse_api'
35
+ autoload :WellplateAPI, 'labimotion/apis/wellplate_api'
35
36
 
36
37
  ######## Entities
37
38
  autoload :PropertiesEntity, 'labimotion/entities/properties_entity'
@@ -123,6 +124,7 @@ module Labimotion
123
124
 
124
125
  autoload :ElementsSample, 'labimotion/models/elements_sample'
125
126
  autoload :ElementsElement, 'labimotion/models/elements_element'
127
+ autoload :ElementsWellplate, 'labimotion/models/elements_wellplate'
126
128
  autoload :CollectionsElement, 'labimotion/models/collections_element'
127
129
 
128
130
  autoload :StdLayer, 'labimotion/models/std_layer'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: labimotion
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0.rc15
4
+ version: 2.2.0.rc17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chia-Lin Lin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-06-23 00:00:00.000000000 Z
12
+ date: 2026-06-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: caxlsx
@@ -73,6 +73,7 @@ files:
73
73
  - lib/labimotion/apis/standard_layer_api.rb
74
74
  - lib/labimotion/apis/user_api.rb
75
75
  - lib/labimotion/apis/vocabulary_api.rb
76
+ - lib/labimotion/apis/wellplate_api.rb
76
77
  - lib/labimotion/collection/export.rb
77
78
  - lib/labimotion/collection/import.rb
78
79
  - lib/labimotion/conf.rb
@@ -150,6 +151,7 @@ files:
150
151
  - lib/labimotion/models/elements_element.rb
151
152
  - lib/labimotion/models/elements_revision.rb
152
153
  - lib/labimotion/models/elements_sample.rb
154
+ - lib/labimotion/models/elements_wellplate.rb
153
155
  - lib/labimotion/models/hub_log.rb
154
156
  - lib/labimotion/models/reaction.rb
155
157
  - lib/labimotion/models/research_plan.rb