Class: Dobjects::Dvector
- Inherits:
-
Object
- Object
- Dobjects::Dvector
- Includes:
- Enumerable
- Defined in:
- ext/Dobjects/Dvector/dvector.c,
lib/Dobjects/Dvector_extras.rb,
ext/Dobjects/Dvector/dvector.c,
ext/Tioga/FigureMaker/figures.c
Overview
Dvectors are a specialized implementation of one-dimensional arrays of double precision floating point numbers. They are intended for use in applications needing efficient processing of large vectors of numeric data. Essentially any of the operations you might do with a 1D Ruby Array of numbers can also be done with a Dvector. Just like Arrays, Dvector indexing starts at 0. A negative index is assumed to be relative to the end of the vector—that is, an index of -1 indicates the last element of the vector, -2 is the next to last element in the vector, and so on. Element reference and element assignment are the same as for Arrays, allowing for (start,length) or (range) as well as for simple indexing. All of the other Array operations that make sense for a 1D array of numbers are also provided for Dvectors. For example, you can “fetch” or “fill” with Dvectors, but there is no “assoc” or “compact” for them since one looks for arrays as elements and the other looks for nil elements, neither of which are found in Dvectors.
In addition to the usual Array methods, there are a variety of others that operate on the contents of the entire vector without the use of explicit iterators. These routines are crucial for efficient processing of large vectors. For example, “vec.sqrt” will create a vector of square roots of entries in vec more efficiently than the semantically equivalent form “vec.collect { |x| sqrt(x) }”.
All of the numeric methods also have ‘bang’ versions that modify the contents of the vector in place; for example, “vec.sqrt!” is more efficient than “vec = vec.sqrt”. By providing implicit iterators and in-place modification, Dvectors make it possible to operate on large vectors of doubles in Ruby at speeds closely approaching a C implementation.
As a final example, for diehards only, say we have large vectors holding values of abundances of total helium (xhe), singly ionized helium (xhe1), and doubly ionized helium (xhe2). We’re missing the values for neutral helium, but that is just what’s left of total helium after you subtract the two ionized forms, so it is easy to compute it. Finally, we need to calculate the log of the abundance of neutral helium and store it in another vector (log_xhe0). If we don’t care about creating work for the garbage collector, we can simply do this
log_xhe0 = (xhe - xhe1 - xhe2).log10
This works, but it creates multiple temporary vectors for intermediate results. If, like me, you’re compulsive about efficiency, you can do the whole thing with no garbage created at all:
log_xhe0 = Dvector.new
log_xhe0.replace(xhe).sub!(xhe1).sub!(xhe2).log10!
This copies xhe to log_xhe0, subtracts xhe1 and xhe2 from log_xhe0 in place, and then takes the log, also in place. It’s not pretty, but it is efficient – use if needed.
Please report problems with the Dvector extension to the tioga-users at rubyforge.org mailing list. [Note: for N-dimensional arrays or arrays of complex numbers or integers as well as doubles, along with a variety of matrix operations, check out the NArray extension.]
Dvector now also prides itselfs with a _dump and a _load function, which means you can Marshal them.
Constant Summary collapse
- FANCY_READ_DEFAULTS =
Dvector.fancy_read’s defaults options. See that function for more details
{ 'sep' => /\s+/, 'comments' => /^\s*\#/, 'skip_first' => 0, 'index_col' => false, 'headers' => nil, # not used for now. 'default' => 0.0/0.0, # defaults to NaN 'initial_size' => 5001, 'remove_space' => true ,# removes spaces at the beginning of the lines }
- WRITE_DEFAULTS =
{ 'sep' => "\t", 'write_mode' => "a", }
Class Method Summary collapse
-
.[](*args) ⇒ Object
Returns a new Dvector populated with the given objects.
- ._load ⇒ Object
-
.compute_formula(formula, a, modules = []) ⇒ Object
This function is a rudimentary formula computing stuff.
- .create_pm_cubic_interpolant ⇒ Object
- .create_spline_interpolant ⇒ Object
-
.fancy_read(stream, cols = nil, opts = {}) ⇒ Object
This function is a wrapper for #fast_fancy_read that reflects the look-and-feel of #old_fancy_read.
-
.fast_fancy_read(stream, options) ⇒ Object
:call-seq: Dvector.fast_fancy_read(stream, options) => Array_of_Dvectors.
-
.from_na(na) ⇒ Object
thanks to Dave MacMahon for from_na and to_na Create a Dvector from an NArray.
- .is_a_dvector ⇒ Object
- .linear_interpolate ⇒ Object
- .max_of_many ⇒ Object
- .min_of_many ⇒ Object
-
.old_fancy_read(stream, cols = nil, opts = {}) ⇒ Object
This function reads in
stream(can an IO object or a String, in which case it represents the name of a file to be opened) the columns specified bycolsand returns them. - .pm_cubic_interpolate ⇒ Object
- .read ⇒ Object
- .read_columns ⇒ Object
- .read_row ⇒ Object
- .read_rows ⇒ Object
- .spline_interpolate ⇒ Object
-
.write(file, cols, options = {}) ⇒ Object
Writes an array of Dvectors into a text file.
Instance Method Summary collapse
- #<< ⇒ Object
- #<=> ⇒ Object
- #[] ⇒ Object (also: #slice)
- #[]= ⇒ Object
-
#_dump ⇒ Object
dvector marshalling.
-
#abs ⇒ Object
numeric methods.
- #abs! ⇒ Object
-
#acos ⇒ Object
standard math functions.
- #acos! ⇒ Object
- #acosh ⇒ Object
- #acosh! ⇒ Object
- #add ⇒ Object (also: #+, #plus)
- #add! ⇒ Object (also: #plus!)
- #as_exponent_of ⇒ Object
- #as_exponent_of! ⇒ Object
- #asin ⇒ Object
- #asin! ⇒ Object
- #asinh ⇒ Object
- #asinh! ⇒ Object
- #at ⇒ Object
- #atan ⇒ Object
- #atan! ⇒ Object
- #atan2 ⇒ Object
- #atan2! ⇒ Object
- #atanh ⇒ Object
- #atanh! ⇒ Object
-
#bounds ⇒ Object
Returns the boundaries of a Dvector, that is [min, max].
- #ceil ⇒ Object
- #ceil! ⇒ Object
- #clean? ⇒ Boolean
- #clear ⇒ Object
- #collect ⇒ Object (also: #map)
- #collect! ⇒ Object (also: #map!)
- #collect2 ⇒ Object (also: #map2)
- #collect2! ⇒ Object (also: #map2!)
- #concat ⇒ Object
-
#convolve(kernel, middle) ⇒ Object
:call-seq: vector.convolve(kernel, middle).
- #cos ⇒ Object
- #cos! ⇒ Object
- #cosh ⇒ Object
- #cosh! ⇒ Object
- #delete ⇒ Object
- #delete_at ⇒ Object
- #delete_if ⇒ Object
- #dirty= ⇒ Object
-
#dirty? ⇒ Boolean
(also: #dirty)
dirty flag related methods.
- #div ⇒ Object (also: #/)
- #div! ⇒ Object
- #dot ⇒ Object
- #dup ⇒ Object
- #each ⇒ Object
- #each2 ⇒ Object
- #each2_with_index ⇒ Object
- #each3 ⇒ Object
- #each3_with_index ⇒ Object
- #each_index ⇒ Object
- #each_with_index ⇒ Object
- #empty? ⇒ Boolean
- #eql? ⇒ Boolean (also: #==)
- #exp ⇒ Object
- #exp! ⇒ Object
- #exp10 ⇒ Object
- #exp10! ⇒ Object
-
#extrema(*args) ⇒ Object
Returns a list of local extrema of the vector, organized thus:.
- #fetch ⇒ Object
-
#fft! ⇒ Object
Performs an in-place Fourier transform of the vector.
-
#fft_conj! ⇒ Object
Converts the FFTed data in the complex conjugate.
-
#fft_mul!(m) ⇒ Object
Multiplies the FFTed data held in the vector by another vector.
-
#fft_spectrum ⇒ Object
Returns the power spectra of the ffted data (ie the square of the norm of the complex fourier coefficients.
- #fill ⇒ Object
- #first ⇒ Object
- #floor ⇒ Object
- #floor! ⇒ Object
- #freeze ⇒ Object
- #frozen? ⇒ Boolean
- #include? ⇒ Boolean
- #index ⇒ Object
- #initialize ⇒ Object constructor
- #initialize_copy ⇒ Object
- #insert ⇒ Object
- #inv ⇒ Object
- #inv! ⇒ Object
- #join ⇒ Object
- #last ⇒ Object
- #length ⇒ Object (also: #size, #nitems)
- #log ⇒ Object
- #log! ⇒ Object
- #log10 ⇒ Object
- #log10! ⇒ Object
- #make_bezier_control_points_for_cubic_in_x ⇒ Object
- #max ⇒ Object
- #max_lt ⇒ Object
- #min ⇒ Object
- #min_gt ⇒ Object
- #modulo ⇒ Object (also: #mod, #%)
- #modulo! ⇒ Object (also: #mod!)
- #mul ⇒ Object (also: #*, #times)
- #mul! ⇒ Object (also: #times!)
-
#neg ⇒ Object
(also: #-@)
nonstandard math functions.
- #neg! ⇒ Object
- #pop ⇒ Object
- #pow ⇒ Object (also: #raised_to, #**)
- #pow! ⇒ Object (also: #raised_to!)
- #prune ⇒ Object
- #prune! ⇒ Object
- #push ⇒ Object
- #reject ⇒ Object
- #reject! ⇒ Object
- #remainder ⇒ Object
- #remainder! ⇒ Object
- #replace ⇒ Object
- #resize ⇒ Object
- #reverse ⇒ Object
- #reverse! ⇒ Object
- #reverse_each ⇒ Object
- #reverse_each2 ⇒ Object
- #reverse_each2_with_index ⇒ Object
- #reverse_each3 ⇒ Object
- #reverse_each3_with_index ⇒ Object
- #reverse_each_index ⇒ Object
- #reverse_each_with_index ⇒ Object
-
#rfft! ⇒ Object
Performs a reverse in-place Fourier transform of the vector.
- #rindex ⇒ Object
- #round ⇒ Object
- #round! ⇒ Object
- #safe_acos ⇒ Object
- #safe_acos! ⇒ Object
- #safe_asin ⇒ Object
- #safe_asin! ⇒ Object
- #safe_inv ⇒ Object
- #safe_inv! ⇒ Object
- #safe_log ⇒ Object
- #safe_log! ⇒ Object
- #safe_log10 ⇒ Object
- #safe_log10! ⇒ Object
- #safe_sqrt ⇒ Object
- #safe_sqrt! ⇒ Object
- #select ⇒ Object
- #set ⇒ Object
- #shift ⇒ Object
- #sin ⇒ Object
- #sin! ⇒ Object
- #sinh ⇒ Object
- #sinh! ⇒ Object
- #slice! ⇒ Object
- #sort ⇒ Object
- #sort! ⇒ Object
- #sqrt ⇒ Object
- #sqrt! ⇒ Object
- #sub ⇒ Object (also: #-, #minus)
- #sub! ⇒ Object (also: #minus!)
- #sum ⇒ Object
- #tan ⇒ Object
- #tan! ⇒ Object
- #tanh ⇒ Object
- #tanh! ⇒ Object
- #to_a ⇒ Object (also: #to_ary)
- #to_dvector ⇒ Object
-
#to_na ⇒ Object
Create an NArray with the same length and contents as
self. - #to_s ⇒ Object (also: #inspect)
- #tridag ⇒ Object
- #trim ⇒ Object
- #trim! ⇒ Object
- #uniq ⇒ Object
- #uniq! ⇒ Object
- #unshift ⇒ Object
- #values_at ⇒ Object
- #vector_length ⇒ Object
- #where_closest ⇒ Object (also: #where_first_closest)
- #where_first_eq ⇒ Object (also: #where_eq)
- #where_first_ge ⇒ Object (also: #where_ge)
- #where_first_gt ⇒ Object (also: #where_gt)
- #where_first_le ⇒ Object (also: #where_le)
- #where_first_lt ⇒ Object (also: #where_lt)
- #where_first_ne ⇒ Object (also: #where_ne)
- #where_last_closest ⇒ Object
- #where_last_eq ⇒ Object
- #where_last_ge ⇒ Object
- #where_last_gt ⇒ Object
- #where_last_le ⇒ Object
- #where_last_lt ⇒ Object
- #where_last_max ⇒ Object
- #where_last_min ⇒ Object
- #where_last_ne ⇒ Object
- #where_max ⇒ Object (also: #where_first_max)
- #where_min ⇒ Object (also: #where_first_min)
Constructor Details
#initialize ⇒ Object
Class Method Details
.[](*args) ⇒ Object
Returns a new Dvector populated with the given objects.
Dvector.[]( 1, 2, 3, 4 ) -> a_dvector
Dvector[ 1, 2, 3, 4 ] -> a_dvector
146 147 148 149 150 151 152 153 154 |
# File 'ext/Dobjects/Dvector/dvector.c', line 146 static VALUE dvector_s_create(int argc, VALUE *argv, VALUE klass) { VALUE ary = make_new_dvector(klass, argc, argc); Dvector *d = Get_Dvector(ary); if (argc < 0) { rb_raise(rb_eArgError, "negative number of arguments"); } ary_to_dvector(argv, argc, d->ptr); return ary; } |
._load ⇒ Object
.compute_formula(formula, a, modules = []) ⇒ Object
This function is a rudimentary formula computing stuff. Give it a text formula and an array of Dvectors (a), and it returns a Dvector with the result. The formula should contain the following;
- column
-
represents the current element of the n th Dvector of the array
This is just a try, and should be implemented in C rather than in Ruby. But if you’re looking for simplicity, here you go ;-) !
modules are the modules you would wish the evaluator to include. This feature enables one to make sure custom functions are included
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/Dobjects/Dvector_extras.rb', line 221 def Dvector.compute_formula(formula, a, modules = []) # :doc: evaluator = MathEvaluator.new(formula, "column", modules) # if we reach this place, it means that there a no big syntax errors ;-) # we now need to inspect the array given, and make sure that there is # and transform it into a clean stuff (an array with only Dvectors and # nil elements). target = [] last = nil a.each { |elem| if elem.is_a? Dvector target << elem last = elem else target << nil end } raise "No Dvector found" unless last # we check all the vectors have the same length target.each {|x| if x && x.length != last.length raise "Dvectors should have all the same length !" end } res = Dvector.new last.each_index { |i| args = target.collect { |val| if val val[i] else nil end } # we add the index at the beginning: # args.unshift(i) # Commented out for simplicity # then we call the block: elem = evaluator.compute(args) res << elem } return res end |
.create_pm_cubic_interpolant ⇒ Object
.create_spline_interpolant ⇒ Object
.fancy_read(stream, cols = nil, opts = {}) ⇒ Object
This function is a wrapper for #fast_fancy_read that reflects the look-and-feel of #old_fancy_read
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/Dobjects/Dvector_extras.rb', line 93 def Dvector.fancy_read(stream, cols = nil, opts = {}) # :doc: o = FANCY_READ_DEFAULTS.dup o.update(opts) if stream.is_a?(String) stream = File.open(stream) end raise ArgumentError.new("'stream' should have a gets method") unless stream.respond_to? :gets o['sep'] = Regexp.new(o['sep']) unless o['sep'].is_a? Regexp res = Dvector.fast_fancy_read(stream, o) # Adding the index columns if necessary if o["index_col"] res.unshift(Dvector.new(res[0].length) { |i| i}) end if cols return cols.map {|i| res[i] } else return res end end |
.fast_fancy_read(stream, options) ⇒ Object
:call-seq: Dvector.fast_fancy_read(stream, options) => Array_of_Dvectors
Reads data from an IO stream (or anything that supports a gets method) and separate it into columns of data according to the options, a hash holding the following elements (compulsory, but you can use FANCY_READ_DEFAULTS): ‘sep’: a regular expression that separate the entries ‘comments’: any line matching this will be skipped ‘skip_first’: skips that many lines before reading anything ‘index_col’: if true, the first column returned contains the
number of the line read
‘remove_space’: whether to remove spaces at the beginning of a line. *This
option is currently not implemented !*
‘comment_out’: this should be an array into which the comments
will be dumped one by one.
‘default’: what to put when nothing was found but a number must be used
In addition to these options that control the output, here are a few others to tune memory allocation; these can strongly improve the performance (or make it worse if you wish):
‘initial_size’: the initial size of the memory buffers: if there
are not more lines than that, no additional memory allocation/copy
occurs.
5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5654 static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE ) { /* First, we read up options: */ double def = rb_num2dbl(rb_hash_aref(, rb_str_new2("default"))); int remove_space = RTEST(rb_hash_aref(, rb_str_new2("remove_space"))); // int index_col = RTEST(rb_hash_aref(, // rb_str_new2("index_col"))); long skip_first = FIX2LONG(rb_hash_aref(, rb_str_new2("skip_first"))); VALUE sep = rb_hash_aref(, rb_str_new2("sep")); VALUE comments = rb_hash_aref(, rb_str_new2("comments")); VALUE comment_out = rb_hash_aref(, rb_str_new2("comment_out")); /* Then, some various variables: */ VALUE line; ID chomp_id = rb_intern("chomp!"); ID gets_id = rb_intern("gets"); long line_number = 0; /* Now come the fun part - rudimentary vectors management TODO: if the stream provides functionality to get its total size, it could be interesting to estimate the total number of lines based on some small heuristics */ int nb_vectors = 0; /* The number of vectors currently created */ int current_size = 10; /* The number of slots available */ double ** vectors = ALLOC_N(double *, current_size); long index = 0; /* The current index in the vectors */ /* The size available in the vectors */ int allocated_size = FIX2LONG(rb_hash_aref(, rb_str_new2("initial_size"))); int i; /* The return value */ VALUE ary; /* We use a real gets so we can also use StringIO, for instance */ while(RTEST(line = rb_funcall(stream, gets_id, 0))) { VALUE pre, post, match; const char * line_ptr; int col = 0; line_number++; /* Whether we should skip the line... */ if(skip_first >= line_number) continue; /* We check for a blank line using isspace: */ line_ptr = StringValueCStr(line); while(line_ptr && *line_ptr) { if(! isspace(*line_ptr)) break; line_ptr++; } if(! *line_ptr) continue; /* We found a blank line */ if(remove_space) /* We replace the contents of the line */ line = rb_str_new2(line_ptr); /* ... or a comment line */ if(RTEST(comments) && RTEST(rb_reg_match(comments, line))) { if(RTEST(comment_out)) rb_ary_push(comment_out, line); continue; } /* Then, we remove the newline: */ post = line; rb_funcall(post, chomp_id, 0); /* We iterate over the different portions between matches */ while(RTEST(post)) { const char * a; char * b; if(RTEST(rb_reg_match(sep, post))) { match = rb_gv_get("$~"); pre = rb_reg_match_pre(match); post = rb_reg_match_post(match); } else { pre = post; post = Qnil; } a = StringValueCStr(pre); double c = strtod(a, &b); if(b == a) c = def; if(col >= nb_vectors) { nb_vectors++; /* We need to create a new vector */ if(col >= current_size) { /* Increase the available size */ current_size += 5; REALLOC_N(vectors, double * , current_size); } double * vals = vectors[col] = ALLOC_N(double, allocated_size); /* Filling it with the default value */ for(i = 0; i < index; i++) { vals[i] = def; } } vectors[col][index] = c; col++; } /* Now, we finish the line */ for(; col < nb_vectors; col++) vectors[col][index] = def; index++; /* Now, we reallocate memory if necessary */ if(index >= allocated_size) { allocated_size *= 2; /* We double the size */ for(col = 0; col < nb_vectors; col++) REALLOC_N(vectors[col], double, allocated_size); } } /* Now, we make up the array */ ary = rb_ary_new(); for(i = 0; i < nb_vectors; i++) { /* We create a vector */ rb_ary_store(ary, i, make_dvector_from_data(cDvector, index, vectors[i])); /* And free the memory */ free(vectors[i]); } free(vectors); return ary; } |
.from_na(na) ⇒ Object
thanks to Dave MacMahon for from_na and to_na Create a Dvector from an NArray.
64 65 66 |
# File 'lib/Dobjects/Dvector_extras.rb', line 64 def Dvector.from_na(na) _load([1, na.length, na.to_s].pack('CIa*')) end |
.is_a_dvector ⇒ Object
.linear_interpolate ⇒ Object
.max_of_many ⇒ Object
.min_of_many ⇒ Object
.old_fancy_read(stream, cols = nil, opts = {}) ⇒ Object
This function reads in stream (can an IO object or a String, in which case it represents the name of a file to be opened) the columns specified by cols and returns them. column 0 is the first column. If cols is nil, then fancy_read attempts to find all the columns in the file, while filling absent data with NaN.
opts is a hash for tuning the behavior of the reading. It can hold the following keys:
- ‘sep’
-
the record separator
- ‘comments’
-
a regular expression matching comment lines
- ‘skip_first’
-
how many lines to skip at the beginning of the file,
- ‘default’
-
the value taken for missing elements
- ‘index_col’
-
if set to true, the first column contains the indices of the elements (starting from 0 for first and so on)
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/Dobjects/Dvector_extras.rb', line 135 def Dvector.old_fancy_read(stream, cols = nil, opts = {}) # :doc: # first, we turn the stream into a real IO stream if stream.is_a?(String) stream = File.open(stream) end raise ArgumentError.new("'stream' should have a gets method") unless stream.respond_to? :gets # we take default options and override them with opts o = FANCY_READ_DEFAULTS.merge(opts) # strip off the first lines. while o["skip_first"] > 0 stream.gets o["skip_first"] -= 1 end # then, parsing the lines. We store the results in an array. We read up # all columns, regardless of what is asked (it doesn't slow that much # the process -- or does it ?) columns = [] line_number = 0 # the number of the significant lines read so far while line = stream.gets next if line =~ o["comments"] next if line =~ /^\s*$/ # skip empty lines if o["remove_space"] line.gsub!(/^\s+/,'') end elements = line.split(o["sep"]) # now, the fun: the actual reading. # we first turn this elements into floats: numbers = elements.collect do |s| begin a = Float(s) rescue o["default"] end end if numbers.size < columns.size # we pad it with default values while numbers.size < columns.size numbers << o["default"] end else # in that case, we need to create new Dvectors to match the # size of numbers while columns.size < numbers.size columns << Dvector.new(line_number, o["default"]) end end # now, we should have the same number of elements both # in numbers and in columns columns.size.times do |i| columns[i] << numbers[i] end # and it's done ;-) ! line_number += 1 end # Adding the index columns if necessary if o["index_col"] columns.unshift(Dvector.new(columns[0].length) { |i| i}) end return columns unless cols return cols.collect { |i| columns[i] } end |
.pm_cubic_interpolate ⇒ Object
.read ⇒ Object
.read_columns ⇒ Object
.read_row ⇒ Object
.read_rows ⇒ Object
.spline_interpolate ⇒ Object
.write(file, cols, options = {}) ⇒ Object
Writes an array of Dvectors into a text file
278 279 280 281 282 283 284 285 286 287 |
# File 'lib/Dobjects/Dvector_extras.rb', line 278 def Dvector.write(file, cols, = {}) ops = WRITE_DEFAULTS.update() if file.is_a?(String) file = File.open(file, ops["write_mode"]) end nb = cols.map {|d| d.size}.max # The number of lines nb.times do |i| file.puts(cols.map {|d| d[i].to_s }.join(ops["sep"])) end end |
Instance Method Details
#<< ⇒ Object
#<=> ⇒ Object
#[] ⇒ Object Also known as: slice
#[]= ⇒ Object
#_dump ⇒ Object
dvector marshalling
#abs ⇒ Object
numeric methods
#abs! ⇒ Object
#acos ⇒ Object
standard math functions
#acos! ⇒ Object
#acosh ⇒ Object
#acosh! ⇒ Object
#add ⇒ Object Also known as: +, plus
#add! ⇒ Object Also known as: plus!
#as_exponent_of ⇒ Object
#as_exponent_of! ⇒ Object
#asin ⇒ Object
#asin! ⇒ Object
#asinh ⇒ Object
#asinh! ⇒ Object
#at ⇒ Object
#atan ⇒ Object
#atan! ⇒ Object
#atan2 ⇒ Object
#atan2! ⇒ Object
#atanh ⇒ Object
#atanh! ⇒ Object
#bounds ⇒ Object
Returns the boundaries of a Dvector, that is [min, max]. It ignores
NaN and will complain if the Dvector contains only NaN.
v = Dvector[0.0/0.0, 0.0/0.0, 1,2,4,5,9,0.0/0.0,0.1]
v.bounds -> [0.1, 9]
5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5539 static VALUE dvector_bounds(VALUE self) { double min, max; VALUE ret; long len; double * data = Dvector_Data_for_Read(self, &len); /* skip all NaNs at the beginning */ while(len-- > 0) if(!isnan(*data++)) break; if(len>=0) { min = max = *(data-1); while(len-- > 0) { if(! isnan(*data)) { if(*data < min) min = *data; if(*data > max) max = *data; } data++; } ret = rb_ary_new2(2); rb_ary_store(ret, 0, rb_float_new(min)); rb_ary_store(ret, 1, rb_float_new(max)); return ret; } else rb_raise(rb_eRuntimeError, "bounds called on an array containing only NaN"); return Qnil; } |
#ceil ⇒ Object
#ceil! ⇒ Object
#clean? ⇒ Boolean
#clear ⇒ Object
#collect ⇒ Object Also known as: map
#collect! ⇒ Object Also known as: map!
#collect2 ⇒ Object Also known as: map2
#collect2! ⇒ Object Also known as: map2!
#concat ⇒ Object
#convolve(kernel, middle) ⇒ Object
:call-seq:
vector.convolve(kernel, middle)
convolve applies a simple convolution to the vector using kernel centered at the point middle. (0 is the leftmost point of the kernel).
5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5582 static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle) { long len; const double * values = Dvector_Data_for_Read(self, &len); VALUE retval = dvector_new2(len,len); double * ret = Dvector_Data_for_Write(retval,NULL); long kernel_len; const double * ker = Dvector_Data_for_Read(kernel, &kernel_len); /* I guess */ long mid = NUM2LONG(middle); if(mid > kernel_len) rb_raise(rb_eArgError, "middle should be within kernel's range"); else { long i,j,k; for(i = 0; i < len; i++) { double sum = 0, k_sum = 0; for(j = 0; j < kernel_len; j++) { /* check that we are within the vector */ k = i - mid + j; /* The current index inside the vector */ /* This code is equivalent to saying that the vector is prolongated until infinity with values at the boundaries -> no, obnoxious, I think. Simply don't take care of these points -> yes, finally ? */ if( k < 0) /* continue; */ k = 0; if( k >= len) /* continue; */ k = len - 1; sum += ker[j] * values[k]; k_sum += ker[j]; } sum/= k_sum; ret[i] = sum; } } return retval; } |
#cos ⇒ Object
#cos! ⇒ Object
#cosh ⇒ Object
#cosh! ⇒ Object
#delete ⇒ Object
#delete_at ⇒ Object
#delete_if ⇒ Object
#dirty= ⇒ Object
#dirty? ⇒ Boolean Also known as: dirty
dirty flag related methods
#div ⇒ Object Also known as: /
#div! ⇒ Object
#dot ⇒ Object
#dup ⇒ Object
#each ⇒ Object
#each2 ⇒ Object
#each2_with_index ⇒ Object
#each3 ⇒ Object
#each3_with_index ⇒ Object
#each_index ⇒ Object
#each_with_index ⇒ Object
#empty? ⇒ Boolean
#eql? ⇒ Boolean Also known as: ==
#exp ⇒ Object
#exp! ⇒ Object
#exp10 ⇒ Object
#exp10! ⇒ Object
#extrema(*args) ⇒ Object
Returns a list of local extrema of the vector, organized thus:
[ [:min, idmin1], [:max, idmax1], ...]
The values are pushed in the order in which they are found. It works thus: it scans the vector and looks around the current point in a given window. If the current point is the maximum or the minimum, it is considered as a local maximum/minimum. Control over which extrema are included is given to the used through threshold mechanisms.
The options hash controls how the peaks are detected: window: the number of elements on which we look on
both sides (default 5, ie the local maximum is over 11 points)
threshold: the minimum amplitude the extrema must have to
be considered (default 0)
dthreshold: how much over/under the average an extremum must be
(default 0)
or: whether the threshold and dthreshold tests are both
necessary or if only one is (default false: both tests are
necessary)
Note:* beware of NANs ! They will screw up peak detection, as they are neither bigger nor smaller than anything…
5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5814 static VALUE dvector_extrema(int argc, VALUE *argv, VALUE self) { long window = 5; double threshold = 0; double dthreshold = 0; int inclusive = 1; if(argc == 1) { VALUE t; t = rb_hash_aref(argv[0], rb_str_new2("window")); if(RTEST(t)) { window = FIX2LONG(t); } t = rb_hash_aref(argv[0], rb_str_new2("threshold")); if(RTEST(t)) { threshold = rb_num2dbl(t); } t = rb_hash_aref(argv[0], rb_str_new2("dthreshold")); if(RTEST(t)) { dthreshold = rb_num2dbl(t); } t = rb_hash_aref(argv[0], rb_str_new2("or")); inclusive = ! RTEST(t); } else if(argc > 1) rb_raise(rb_eArgError, "Dvector.extrema only takes 0 or 1 argument"); /* Handling of the vector */ long len, i,j; double * data = Dvector_Data_for_Read(self, &len); VALUE s_min = ID2SYM(rb_intern("min")); VALUE s_max = ID2SYM(rb_intern("max")); VALUE ret = rb_ary_new(); for(i = 0; i < len; i++) { /* This is stupid and will need decent optimization when I have time */ long first = i > window ? i - window : 0; double cur_min = data[first]; long cur_min_idx = first; double cur_max = data[first]; long cur_max_idx = first; double average = 0; long nb = 0; for(j = first; (j < i+window) && (j < len); j++,nb++) { average += data[j]; if(data[j] <= cur_min) { cur_min = data[j]; cur_min_idx = j; } if(data[j] >= cur_max) { cur_max = data[j]; cur_max_idx = j; } } average /= nb; if(cur_min_idx == i) { /* This is a potential minimum */ if((inclusive && (fabs(cur_min) >= threshold) && (fabs(cur_min - average) >= dthreshold)) || (!inclusive && ((fabs(cur_min) >= threshold) || (fabs(cur_min - average) >= dthreshold)) )) { VALUE min = rb_ary_new(); rb_ary_push(min, s_min); rb_ary_push(min, LONG2FIX(i)); rb_ary_push(ret, min); } } else if(cur_max_idx == i) { /* A potential maximum */ if((inclusive && (fabs(cur_max) >= threshold) && (fabs(cur_max - average) >= dthreshold)) || (!inclusive && ((fabs(cur_max) >= threshold) || (fabs(cur_max - average) >= dthreshold)) )) { VALUE max = rb_ary_new(); rb_ary_push(max, s_max); rb_ary_push(max, LONG2FIX(i)); rb_ary_push(ret, max); } } } return ret; } |
#fetch ⇒ Object
#fft! ⇒ Object
Performs an in-place Fourier transform of the vector. The results is stored in the so-called “half-complex” format (see www.fftw.org/fftw3_doc/The-Halfcomplex_002dformat-DFT.html for more information).
5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5921 static VALUE dvector_fft(VALUE self) { long len; double * values = Dvector_Data_for_Write(self, &len); fftw_plan plan = fftw_plan_r2r_1d(len, values, values, FFTW_R2HC, FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); return self; } |
#fft_conj! ⇒ Object
Converts the FFTed data in the complex conjugate
5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5994 static VALUE dvector_fft_conj(VALUE self) { long len; double * v1 = Dvector_Data_for_Write(self, &len); double * img; long i; for(i = 1, img = v1 + len-1; i < (len+1)/2; i++, img--) *img = -*img; return self; } |
#fft_mul!(m) ⇒ Object
Multiplies the FFTed data held in the vector by another vector. The behaviour depends on the size of the target vector:
if it is the same size, it is assumed to be FFTed data if it is the same size of a power spectrum, then it is assumed that it
is multiplication by real values
anything else won’t make this function happy.
As a side note, if you only want multiplication by a scalar, the standard #mul! should be what you look for.
6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 |
# File 'ext/Dobjects/Dvector/dvector.c', line 6019 static VALUE dvector_fft_mul(VALUE self, VALUE m) { long len; double * v1 = Dvector_Data_for_Write(self, &len); long len2; const double * v2 = Dvector_Data_for_Write(m, &len2); if(len2 == len) { /* Full complex multiplication */ const double * m_img; const double * m_real; double * v_img; double * v_real; long i; /* First, special cases */ v1[0] *= v2[0]; if(len % 2 == 0) v1[len/2] *= v2[len/2]; for(i = 1, m_real = v2 + 1, m_img = v2 + len-1, v_real = v1 + 1, v_img = v1 + len-1; i < (len+1)/2; i++, m_real++, v_real++, m_img--, v_img--) { double r = *m_real * *v_real - *m_img * *v_img; *v_img = *m_real * *v_img + *v_real * *m_img; *v_real = r; } return self; } else if(len2 == len/2+1) { /* Complex * real*/ const double * val; double * v_img; double * v_real; long i; /* First, special cases */ v1[0] *= v2[0]; if(len % 2 == 0) v1[len/2] *= v2[len/2]; for(i = 1, val = v2 + 1, v_real = v1 + 1, v_img = v1 + len-1; i < (len+1)/2; i++, val++, v_real++, v_img--) { *v_real *= *val; *v_img *= *val; } return self; } else { rb_raise(rb_eArgError, "incorrect Dvector size for fft_mul!"); } } |
#fft_spectrum ⇒ Object
Returns the power spectra of the ffted data (ie the square of the norm of the complex fourier coefficients.
The returned value is a new Dvector of size about two times smaller than the original (precisely size/2 + 1)
For some reasons, convolutions don’t work for now.
5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5966 static VALUE dvector_fft_spectrum(VALUE self) { long len; const double * values = Dvector_Data_for_Read(self, &len); /* First compute the size of the target: */ long target_size = len/2+1; long i; VALUE retval = dvector_new2(target_size,target_size); double * ret = Dvector_Data_for_Write(retval,NULL); /* Pointer to real and imaginary parts */ const double * real; const double * img; ret[0] = values[0] * values[0]; /* The Nyquist frequency */ if(len % 2 == 0) ret[target_size - 1] = values[target_size-1] * values[target_size-1]; for(i = 1, real = values + 1, img = values + len-1; i < len/2; i++, real++, img--) ret[i] = *real * *real + *img * *img; return retval; } |
#fill ⇒ Object
#first ⇒ Object
#floor ⇒ Object
#floor! ⇒ Object
#freeze ⇒ Object
#frozen? ⇒ Boolean
#include? ⇒ Boolean
#index ⇒ Object
#initialize_copy ⇒ Object
#insert ⇒ Object
#inv ⇒ Object
#inv! ⇒ Object
#join ⇒ Object
#last ⇒ Object
#length ⇒ Object Also known as: size, nitems
#log ⇒ Object
#log! ⇒ Object
#log10 ⇒ Object
#log10! ⇒ Object
#make_bezier_control_points_for_cubic_in_x ⇒ Object
#max ⇒ Object
#max_lt ⇒ Object
#min ⇒ Object
#min_gt ⇒ Object
#modulo ⇒ Object Also known as: mod, %
#modulo! ⇒ Object Also known as: mod!
#mul ⇒ Object Also known as: *, times
#mul! ⇒ Object Also known as: times!
#neg ⇒ Object Also known as: -@
nonstandard math functions
#neg! ⇒ Object
#pop ⇒ Object
#pow ⇒ Object Also known as: raised_to, **
#pow! ⇒ Object Also known as: raised_to!
#prune ⇒ Object
#prune! ⇒ Object
#push ⇒ Object
#reject ⇒ Object
#reject! ⇒ Object
#remainder ⇒ Object
#remainder! ⇒ Object
#replace ⇒ Object
#resize ⇒ Object
#reverse ⇒ Object
#reverse! ⇒ Object
#reverse_each ⇒ Object
#reverse_each2 ⇒ Object
#reverse_each2_with_index ⇒ Object
#reverse_each3 ⇒ Object
#reverse_each3_with_index ⇒ Object
#reverse_each_index ⇒ Object
#reverse_each_with_index ⇒ Object
#rfft! ⇒ Object
Performs a reverse in-place Fourier transform of the vector. The original data must have been stored in the so called “half-complex” format (see #fft!).
5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 |
# File 'ext/Dobjects/Dvector/dvector.c', line 5938 static VALUE dvector_rfft(VALUE self) { long len; double * values = Dvector_Data_for_Write(self, &len); fftw_plan plan = fftw_plan_r2r_1d(len, values, values, FFTW_HC2R, FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); return self; } |
#rindex ⇒ Object
#round ⇒ Object
#round! ⇒ Object
#safe_acos ⇒ Object
#safe_acos! ⇒ Object
#safe_asin ⇒ Object
#safe_asin! ⇒ Object
#safe_inv ⇒ Object
#safe_inv! ⇒ Object
#safe_log ⇒ Object
#safe_log! ⇒ Object
#safe_log10 ⇒ Object
#safe_log10! ⇒ Object
#safe_sqrt ⇒ Object
#safe_sqrt! ⇒ Object
#select ⇒ Object
#set ⇒ Object
#shift ⇒ Object
#sin ⇒ Object
#sin! ⇒ Object
#sinh ⇒ Object
#sinh! ⇒ Object
#slice! ⇒ Object
#sort ⇒ Object
#sort! ⇒ Object
#sqrt ⇒ Object
#sqrt! ⇒ Object
#sub ⇒ Object Also known as: -, minus
#sub! ⇒ Object Also known as: minus!
#sum ⇒ Object
#tan ⇒ Object
#tan! ⇒ Object
#tanh ⇒ Object
#tanh! ⇒ Object
#to_a ⇒ Object Also known as: to_ary
#to_dvector ⇒ Object
74 75 76 |
# File 'lib/Dobjects/Dvector_extras.rb', line 74 def to_dvector self end |
#to_na ⇒ Object
Create an NArray with the same length and contents as self.
69 70 71 |
# File 'lib/Dobjects/Dvector_extras.rb', line 69 def to_na ::NArray.to_na(_dump(nil)[5..-1], ::NArray::DFLOAT) end |