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
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/cicada/correction/correction.rb', line 79 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.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def correction_channel @correction_channel end |
#correction_x ⇒ Object
Returns the value of attribute correction_x.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def correction_x @correction_x end |
#correction_y ⇒ Object
Returns the value of attribute correction_y.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def correction_y @correction_y end |
#correction_z ⇒ Object
Returns the value of attribute correction_z.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def correction_z @correction_z end |
#distance_cutoffs ⇒ Object
Returns the value of attribute distance_cutoffs.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def distance_cutoffs @distance_cutoffs end |
#positions_for_correction ⇒ Object
Returns the value of attribute positions_for_correction.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def positions_for_correction @positions_for_correction end |
#reference_channel ⇒ Object
Returns the value of attribute reference_channel.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def reference_channel @reference_channel end |
#tre ⇒ Object
Returns the value of attribute tre.
62 63 64 |
# File 'lib/cicada/correction/correction.rb', line 62 def tre @tre end |
Class Method Details
.read_from_file(fn) ⇒ Correction
Reads a correction from a specified file containing an XML-encoded correction.
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/cicada/correction/correction.rb', line 183 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.
202 203 204 205 206 |
# File 'lib/cicada/correction/correction.rb', line 202 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.
219 220 221 222 223 224 |
# File 'lib/cicada/correction/correction.rb', line 219 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.
233 234 235 236 237 238 239 |
# File 'lib/cicada/correction/correction.rb', line 233 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.
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/cicada/correction/correction.rb', line 292 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).
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/cicada/correction/correction.rb', line 251 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
113 114 115 116 117 |
# File 'lib/cicada/correction/correction.rb', line 113 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.
151 152 153 154 155 156 |
# File 'lib/cicada/correction/correction.rb', line 151 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
128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/cicada/correction/correction.rb', line 128 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.
99 100 101 102 103 |
# File 'lib/cicada/correction/correction.rb', line 99 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
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/cicada/correction/correction.rb', line 163 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 |