Class: SciYAG::Backends::TextBackend
- Includes:
- Dobjects
- Defined in:
- lib/SciYAG/Backends/text.rb
Direct Known Subclasses
Constant Summary collapse
- UNCOMPRESSORS =
A constant holding a relation extension -> command to decompress (to be fed to sprintf with the filename as argument)
{ ".gz" => "gunzip -c %s", ".bz2" => "bunzip2 -c %s", ".lzma" => "unlzma -c %s", }
- InvalidLineRE =
A line is invalid if it is blank or starts neither with a digit nor +, - or .
Maybe to be improved later.
/^\s*$|^\s*[^\d+.\s-]+/
Instance Method Summary collapse
-
#compute_error_bars(values) ⇒ Object
Turns a target => values specification into something usable as error bars, that is :xmin, :xmax and the like hashes.
-
#expand_sets(spec) ⇒ Object
Expands specifications into few sets.
- #extend(mod) ⇒ Object
-
#get_data(col_spec) ⇒ Object
Reads the data using the columns specification, provided that the appropriate fle has already been loaded into @current.
-
#get_io_object(file) ⇒ Object
Returns a IO object suitable to acquire data from it for the given file, which can be one of the following: * a real file name * a compressed file name * a pipe command.
-
#get_io_set(file) ⇒ Object
Returns an IO object corresponding to the given file.
-
#get_set_string(io, set) ⇒ Object
Returns a string corresponding to the given set of the given io object.
-
#initialize ⇒ TextBackend
constructor
param_accessor :select, ‘select’, “Select lines”, => :string, “Skips line where the code returns false”.
-
#query_xy_data(set) ⇒ Object
This is called by the architecture to get the data.
-
#read_file(file) ⇒ Object
Reads data from a file.
Methods inherited from Backend
#base_line=, #clear_xy_filters, default_state, describe, #get_cached_entry, #has_set?, list_backends, list_descriptions, logger=, #meta_data, #pop_xy_filter, #push_xy_filter, #set_type, #sets_available, #xy_data, #xyz_data
Methods included from MetaBuilder::DescriptionExtend
#base_description, #create_factory, #describe, #description, #factory_class, #factory_description, #factory_description_hash, #factory_description_list, #group, #has_factory?, #inherit_parameters, #param, #param_accessor, #param_reader, #param_writer, #register_class, #set_description
Methods included from MetaBuilder::DescriptionInclude
#description, #get_param, #get_param_raw, #long_name, #option_parser_banner, #option_parser_fill, #option_parser_options, #parameter, #restore_state, #save_state, #set_param, #set_param_raw
Constructor Details
#initialize ⇒ TextBackend
param_accessor :select, ‘select’, “Select lines”, => :string,
"Skips line where the code returns false"
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/SciYAG/Backends/text.rb', line 78 def initialize @dummy = nil @current = nil # Current is the name of the last file used. Necessary for '' specs. @current_data = nil # The data of the last file used. @skip = 0 @included_modules = [NaN] # to make sure we give them to # Dvector.compute_formula @default_column_spec = "1:2" @separator = /\s+/ # We don't split data by default. @split = false super() # Override Backend's cache - for now. @cache = {} # A cache file_name -> data end |
Instance Method Details
#compute_error_bars(values) ⇒ Object
Turns a target => values specification into something usable as error bars, that is :xmin, :xmax and the like hashes. The rules are the following:
-
?min/?max are passed on directly;
-
?e(abs) are transformed into ?min = ? - ?eabs, ?max = ? + ?eabs
-
?eu(p/?ed(own) are transformed respectively into ? +/- ?…
-
?er(el) become ?min = ?*(1 - ?erel, ?max = ?(1 + ?erel)
-
?erup/?erdown follow the same pattern…
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/SciYAG/Backends/text.rb', line 281 def (values) target = {} for key in values.keys case key.to_s when /^[xy](min|max)?$/ target[key] = values[key].dup # Just to make sure. when /^(.)e(a(bs?)?)?$/ target["#{$1}min".to_sym] = values[$1.to_sym] - values[key] target["#{$1}max".to_sym] = values[$1.to_sym] + values[key] when /^(.)eu(p)?$/ target["#{$1}max".to_sym] = values[$1.to_sym] + values[key] when /^(.)ed(o(wn?)?)?$/ target["#{$1}min".to_sym] = values[$1.to_sym] - values[key] when /^(.)er(el?)?$/ target["#{$1}min".to_sym] = values[$1.to_sym] * (values[key].neg + 1) target["#{$1}max".to_sym] = values[$1.to_sym] * (values[key] + 1) when /^(.)erd(o(wn?)?)?$/ target["#{$1}min".to_sym] = values[$1.to_sym] * (values[key].neg + 1) when /^(.)erup?$/ target["#{$1}max".to_sym] = values[$1.to_sym] * (values[key] + 1) else warn "Somehow, the target specification #{key} " + "didn't make it through" end end return target end |
#expand_sets(spec) ⇒ Object
Expands specifications into few sets. This function will separate the set into a file spec and a col spec. Within the col spec, the 2##6 keyword is used to expand to 2,3,4,5,6. 2## followed by a non-digit expands to 2,…,last column in the file. For now, the expansions stops on the first occurence found, and the second form doesn’t work yet. But soon…
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/SciYAG/Backends/text.rb', line 319 def (spec) if m = /(\d+)##(\D|$)/.match(spec) a = m[1].to_i trail = m[2] b = read_file(spec) b = (b.length - 1) ret = [] a.upto(b) do |i| ret << m.pre_match + i.to_s + trail + m.post_match end return ret else return super end end |
#extend(mod) ⇒ Object
100 101 102 103 |
# File 'lib/SciYAG/Backends/text.rb', line 100 def extend(mod) super @included_modules << mod end |
#get_data(col_spec) ⇒ Object
Reads the data using the columns specification, provided that the appropriate fle has already been loaded into @current. For now no single sanity check.
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 271 |
# File 'lib/SciYAG/Backends/text.rb', line 234 def get_data(col_spec) # First, we must split the column specification into what # I would call target specifications. A target is in the form # of stuff=spec, where stuff can be basically anything. x=, y=, # yea= are implied for the first specifications. defaults = [:x,:y,:yea] specifications = {} # A hash value spec => column spec col_spec.split(/:/).each do |spec| d = defaults.shift if spec =~ /^\s*(\w+)\s*=(.*)/ spec = $2 d = $1.to_sym end specifications[d] = spec end debug "spec #{col_spec} becomes #{specifications.inspect}" values = {} if col_spec =~ /\$/ # There is a formula in the specification for key,spec in specifications formula = spec.gsub(/\$(\d+)/, 'column[\1]') debug "Using formula '#{formula}' for #{key}" values[key] = Dvector. compute_formula(formula, @current_data, @included_modules) end else for key,spec in specifications values[key] = @current_data[spec.to_i].dup end end errors = (values) # Now, we're left with a hash... return [values[:x],values[:y], errors] end |
#get_io_object(file) ⇒ Object
Returns a IO object suitable to acquire data from it for the given file, which can be one of the following:
-
a real file name
-
a compressed file name
-
a pipe command.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/SciYAG/Backends/text.rb', line 110 def get_io_object(file) if file == "-" return $stdin elsif file =~ /(.*?)\|\s*$/ # A pipe return IO.popen($1) elsif not File.readable?(file) # Try to find a compressed version for ext,method in UNCOMPRESSORS if File.readable? "#{file}#{ext}" info "Using compressed file #{name}#{ext} in stead of #{name}" return IO.popen(method % "#{file}#{ext}") end end else for ext, method in UNCOMPRESSORS if file =~ /#{ext}$/ info "Taking file #{file} as a compressed file" return IO.popen(method % file) end end return File::open(file) end error "Could not open #{file}" return nil end |
#get_io_set(file) ⇒ Object
Returns an IO object corresponding to the given file.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/SciYAG/Backends/text.rb', line 175 def get_io_set(file) if not @split return get_io_object(file) else file =~ /(.*?)(?:#(\d+))?$/; # ; to make ruby-mode indent correctly. filename = $1 if $2 set = $2.to_i else set = 1 end debug "Trying to get set #{set} from file '#{filename}'" str = get_set_string(get_io_object(filename), set) return StringIO.new(str) end end |
#get_set_string(io, set) ⇒ Object
Returns a string corresponding to the given set of the given io object.
Sets are 1-based.
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 |
# File 'lib/SciYAG/Backends/text.rb', line 146 def get_set_string(io, set) cur_set = 1 last_line_is_invalid = true str = "" line_number = 0 while line = io.gets line_number += 1 if line =~ InvalidLineRE debug "Found invalid line at #{line_number}" if ! last_line_is_invalid # We begin a new set. cur_set += 1 debug "Found set #{cur_set} at line #{line_number}" if(cur_set > set) return str end end last_line_is_invalid = true else last_line_is_invalid = false if cur_set == set str += line end end end return str end |
#query_xy_data(set) ⇒ Object
This is called by the architecture to get the data. It splits the set name into filename@cols, reads the file if necessary and calls get_data
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/SciYAG/Backends/text.rb', line 215 def query_xy_data(set) if set =~ /(.*)@(.*)/ col_spec = $2 file = $1 else col_spec = @default_column_spec file = set end if file.length > 0 @current_data = read_file(file) @current = file end x,y,err = get_data(col_spec) return [Function.new(x,y),err] end |
#read_file(file) ⇒ Object
Reads data from a file. If needed, extract the file from the columns specification.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/SciYAG/Backends/text.rb', line 194 def read_file(file) if file =~ /(.*)@.*/ file = $1 end name = file # As file will be modified. if ! @cache.key?(file) # Read the file if it is not cached. = {'index_col' => true, 'skip_first' => @skip, 'sep' => @separator } io_set = get_io_set(file) debug "Fancy read '#{file}', options #{.inspect}" @cache[name] = Dvector.fancy_read(io_set, nil, ) end return @cache[name] end |