Class: Cicada::Correction
- Inherits:
-
Object
- Object
- Cicada::Correction
- Defined in:
- lib/cicada/correction/correction.rb
Overview
Stores data for a standard 3d high-resolution colocalization correction, including positions for a number of objects used for correction, and local quadratic fits of aberration near these objects. Can correct 2d positions based upon this data.
Constant Summary collapse
- XML_STRINGS =
Strings used in XML elements and attributes when writing a correction to an XML format
{ correction_element: "correction", correction_point_element: "point", n_points_attr: "n", ref_channel_attr: "reference_channel", corr_channel_attr: "correction_channel", x_pos_attr: "x_position", y_pos_attr: "y_position", z_pos_attr: "z_position", x_param_element: "x_dimension_parameters", y_param_element: "y_dimension_parameters", z_param_element: "z_dimension_parameters", binary_data_element: "serialized_form", encoding_attr: "encoding", encoding_name: "base64"}
- NUM_CORR_PARAM =
Number of parameters used for correction (6, as this is the number of parameters for a 2d quadratic fit)
6
Instance Attribute Summary collapse
-
#correction_channel ⇒ Object
Returns the value of attribute correction_channel.
-
#correction_x ⇒ Object
Returns the value of attribute correction_x.
-
#correction_y ⇒ Object
Returns the value of attribute correction_y.
-
#correction_z ⇒ Object
Returns the value of attribute correction_z.
-
#distance_cutoffs ⇒ Object
Returns the value of attribute distance_cutoffs.
-
#positions_for_correction ⇒ Object
Returns the value of attribute positions_for_correction.
-
#reference_channel ⇒ Object
Returns the value of attribute reference_channel.
-
#tre ⇒ Object
Returns the value of attribute tre.
Class Method Summary collapse
-
.read_from_file(fn) ⇒ Correction
Reads a correction from a specified file containing an XML-encoded correction.
-
.read_from_xml(xml_str) ⇒ Correction
Reads a correction from an XML string.
Instance Method Summary collapse
-
#calculate_normalized_dists_to_centroids(x, y) ⇒ Vector
Calculates the 2d distances from a specified 2d point to the centroid of each of the image objects used for the correction.
-
#calculate_weights(x, y) ⇒ Vector
Calculates the weight of each local quadratic fit for correcting a specified point.
-
#correct_position(x, y) ⇒ MVector
Calculates the correction for a specified position.
-
#find_points_for_correction(x, y) ⇒ OpenStruct, ...
Selects the local fits and their associated image objects that are to be used for correcting a specified point (i.e. those fits with nonzero weight).
-
#initialize(c_x, c_y, c_z, distance_cutoffs, image_objects, reference_channel, correction_channel) ⇒ Correction
constructor
Constructs a new correction based on the supplied data.
-
#write_all_correction_point_xml(correction_element) ⇒ void
Writes all the points used for correction to XML within a supplied correction XML element.
-
#write_correction_binary_data_element(correction_element) ⇒ void
Writes the internal binary representation of the correction into an XML element.
-
#write_correction_point_xml(correction_element, i) ⇒ void
Writes a single point used for correction to XML within a supplied correction XML element.
-
#write_to_file(fn) ⇒ void
Writes the correction to a specified file in XML format.
-
#write_to_xml ⇒ String
Writes the correction to a string in XML format.
Constructor Details
#initialize(c_x, c_y, c_z, distance_cutoffs, image_objects, reference_channel, correction_channel) ⇒ Correction
Constructs a new correction based on the supplied data
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/cicada/correction/correction.rb', line 84 def initialize(c_x, c_y, c_z, distance_cutoffs, image_objects, reference_channel, correction_channel) @correction_x = c_x @correction_y = c_y @correction_z = c_z @reference_channel = reference_channel @correction_channel = correction_channel @distance_cutoffs = distance_cutoffs n_dims = 3 @positions_for_correction = MMatrix.build(image_objects.size, n_dims) do |r, c| image_objects[r].getPositionForChannel(reference_channel).toArray[c] end end |
Instance Attribute Details
#correction_channel ⇒ Object
Returns the value of attribute correction_channel.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def correction_channel @correction_channel end |
#correction_x ⇒ Object
Returns the value of attribute correction_x.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def correction_x @correction_x end |
#correction_y ⇒ Object
Returns the value of attribute correction_y.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def correction_y @correction_y end |
#correction_z ⇒ Object
Returns the value of attribute correction_z.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def correction_z @correction_z end |
#distance_cutoffs ⇒ Object
Returns the value of attribute distance_cutoffs.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def distance_cutoffs @distance_cutoffs end |
#positions_for_correction ⇒ Object
Returns the value of attribute positions_for_correction.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def positions_for_correction @positions_for_correction end |
#reference_channel ⇒ Object
Returns the value of attribute reference_channel.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def reference_channel @reference_channel end |
#tre ⇒ Object
Returns the value of attribute tre.
67 68 69 |
# File 'lib/cicada/correction/correction.rb', line 67 def tre @tre end |
Class Method Details
.read_from_file(fn) ⇒ Correction
Reads a correction from a specified file containing an XML-encoded correction.
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/cicada/correction/correction.rb', line 228 def self.read_from_file(fn) return nil unless File.exist?(fn) xml_str = "" File.open(fn) do |f| xml_str = f.read end read_from_xml(xml_str) end |
.read_from_xml(xml_str) ⇒ Correction
Reads a correction from an XML string.
252 253 254 255 256 257 258 259 260 |
# File 'lib/cicada/correction/correction.rb', line 252 def self.read_from_xml(xml_str) doc = REXML::Document.new xml_str bin_el = doc.root.elements[1, XML_STRINGS[:binary_data_element]] Marshal.load(Base64.decode64(bin_el.text)) end |
Instance Method Details
#calculate_normalized_dists_to_centroids(x, y) ⇒ Vector
Calculates the 2d distances from a specified 2d point to the centroid of each of the image objects used for the correction.
273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/cicada/correction/correction.rb', line 273 def calculate_normalized_dists_to_centroids(x,y) dists_to_centroids = @positions_for_correction.column(0).map { |x0| (x0-x)**2 } dists_to_centroids += @positions_for_correction.column(1).map { |y0| (y0-y)**2 } dists_to_centroids = dists_to_centroids.map { |e| Math.sqrt(e) } dists_to_centroids.map2(@distance_cutoffs) { |e1, e2| e1/e2 } end |
#calculate_weights(x, y) ⇒ Vector
Calculates the weight of each local quadratic fit for correcting a specified point.
292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/cicada/correction/correction.rb', line 292 def calculate_weights(x, y) dist_ratio = calculate_normalized_dists_to_centroids(x,y) dist_ratio_mask = MVector.zero(dist_ratio.size) dist_ratio_mask = dist_ratio.map { |e| e <= 1 ? 1 : 0 } weights = dist_ratio.map { |e| -3*e**2 + 1 + 2*e**3 } weights.map2(dist_ratio_mask) { |e1, e2| e1*e2 } end |
#correct_position(x, y) ⇒ MVector
Calculates the correction for a specified position.
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
# File 'lib/cicada/correction/correction.rb', line 371 def correct_position(x, y) points = find_points_for_correction(x,y) x_corr = 0.0 y_corr = 0.0 z_corr = 0.0 all_correction_parameters = MMatrix.columns([MVector.unit(points.x_vec.size), points.x_vec, points.y_vec, points.x_vec.map { |e| e**2 }, points.y_vec.map { |e| e**2 }, points.x_vec.map2(points.y_vec) { |e1, e2| e1*e2 }]) all_correction_parameters.row_size.times do |i| x_corr += all_correction_parameters.row(i).inner_product(points.cx.row(i))*points.weights[i] y_corr += all_correction_parameters.row(i).inner_product(points.cy.row(i))*points.weights[i] z_corr += all_correction_parameters.row(i).inner_product(points.cz.row(i))*points.weights[i] end sum_weights = points.weights.reduce(0.0) { |a,e| a + e } x_corr /= sum_weights y_corr /= sum_weights z_corr /= sum_weights MVector[x_corr, y_corr, z_corr] end |
#find_points_for_correction(x, y) ⇒ OpenStruct, ...
Selects the local fits and their associated image objects that are to be used for correcting a specified point (i.e. those fits with nonzero weight).
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/cicada/correction/correction.rb', line 316 def find_points_for_correction(x,y) weights = calculate_weights(x,y) count_weights = weights.count { |e| e > 0 } raise UnableToCorrectError, "Incomplete coverage in correction dataset at (x,y) = (#{x}, #{y})." if count_weights == 0 cx = MMatrix.zero(count_weights, @correction_x[0].size) cy = MMatrix.zero(count_weights, @correction_y[0].size) cz = MMatrix.zero(count_weights, @correction_z[0].size) x_vec = MVector.zero(count_weights) y_vec = MVector.zero(count_weights) kept_weights = MVector.zero(count_weights) kept_counter = 0 weights.each_with_index do |w, i| if w > 0 then cx.replace_row(kept_counter, @correction_x[i]) cy.replace_row(kept_counter, @correction_y[i]) cz.replace_row(kept_counter, @correction_z[i]) x_vec[kept_counter] = x - positions_for_correction[i,0] y_vec[kept_counter] = y - positions_for_correction[i,1] kept_weights[kept_counter] = weights[i] kept_counter += 1 end end OpenStruct.new(cx: cx, cy: cy, cz: cz, x_vec: x_vec, y_vec: y_vec, weights: kept_weights) end |
#write_all_correction_point_xml(correction_element) ⇒ void
This method returns an undefined value.
Writes all the points used for correction to XML within a supplied correction
XML element
129 130 131 132 133 134 135 136 137 |
# File 'lib/cicada/correction/correction.rb', line 129 def write_all_correction_point_xml(correction_element) @distance_cutoffs.each_with_index do |e,i| write_correction_point_xml(correction_element, i) end end |
#write_correction_binary_data_element(correction_element) ⇒ void
This method returns an undefined value.
Writes the internal binary representation of the correction into
an XML element.
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/cicada/correction/correction.rb', line 180 def write_correction_binary_data_element(correction_element) bd = correction_element.add_element XML_STRINGS[:binary_data_element] bd.attributes[XML_STRINGS[:encoding_attr]]= XML_STRINGS[:encoding_name] bin_data = Base64.encode64(Marshal.dump(self)) bd.text = bin_data end |
#write_correction_point_xml(correction_element, i) ⇒ void
This method returns an undefined value.
Writes a single point used for correction to XML within a supplied correction
XML element
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/cicada/correction/correction.rb', line 149 def write_correction_point_xml(correction_element, i) cp = correction_element.add_element XML_STRINGS[:correction_point_element] cp.attributes[XML_STRINGS[:x_pos_attr]]= @positions_for_correction[i,0] cp.attributes[XML_STRINGS[:y_pos_attr]]= @positions_for_correction[i,1] cp.attributes[XML_STRINGS[:z_pos_attr]]= @positions_for_correction[i,2] point_dims_to_corr = {XML_STRINGS[:x_param_element] => @correction_x, XML_STRINGS[:y_param_element] => @correction_y, XML_STRINGS[:z_param_element] => @correction_z} point_dims_to_corr.each do |dim_el, corr_txt| p = cp.add_element dim_el p.text = corr_txt[i].to_a.join(", ") end end |
#write_to_file(fn) ⇒ void
This method returns an undefined value.
Writes the correction to a specified file in XML format.
110 111 112 113 114 115 116 117 118 |
# File 'lib/cicada/correction/correction.rb', line 110 def write_to_file(fn) File.open(fn, 'w') do |f| f.puts(write_to_xml) end end |
#write_to_xml ⇒ String
Writes the correction to a string in XML format
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/cicada/correction/correction.rb', line 197 def write_to_xml doc = REXML::Document.new ce = doc.add_element XML_STRINGS[:correction_element] ce.attributes[XML_STRINGS[:n_points_attr]] = @distance_cutoffs.size ce.attributes[XML_STRINGS[:ref_channel_attr]] = @reference_channel ce.attributes[XML_STRINGS[:corr_channel_attr]] = @correction_channel write_all_correction_point_xml(ce) write_correction_binary_data_element(ce) doc_string = "" doc.write doc_string, 2 doc_string end |