source: sasview/DataLoader/data_info.py @ d16e396

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since d16e396 was 2c0f2a5, checked in by Jae Cho <jhjcho@…>, 15 years ago

working on tiff reader and plotter

  • Property mode set to 100644
File size: 26.5 KB
Line 
1"""
2    Module that contains classes to hold information read from
3    reduced data files.
4   
5    A good description of the data members can be found in
6    the CanSAS 1D XML data format:
7   
8    http://www.smallangles.net/wgwiki/index.php/cansas1d_documentation
9"""
10
11"""
12This software was developed by the University of Tennessee as part of the
13Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
14project funded by the US National Science Foundation.
15
16If you use DANSE applications to do scientific research that leads to
17publication, we ask that you acknowledge the use of the software with the
18following sentence:
19
20"This work benefited from DANSE software developed under NSF award DMR-0520547."
21
22copyright 2008, University of Tennessee
23"""
24
25#TODO: Keep track of data manipulation in the 'process' data structure.
26#TODO: This module should be independent of plottables. We should write
27#        an adapter class for plottables when needed.
28
29#from sans.guitools.plottables import Data1D as plottable_1D
30from data_util.uncertainty import Uncertainty
31import numpy
32import math
33
34class plottable_1D:
35    """
36        Data1D is a place holder for 1D plottables.
37    """
38    # The presence of these should be mutually exclusive with the presence of Qdev (dx)
39    x = None
40    y = None
41    dx = None
42    dy = None
43    ## Slit smearing length
44    dxl = None
45    ## Slit smearing width
46    dxw = None
47   
48    # Units
49    _xaxis = ''
50    _xunit = ''
51    _yaxis = ''
52    _yunit = ''
53   
54    def __init__(self,x,y,dx=None,dy=None,dxl=None,dxw=None):
55        self.x = x
56        self.y = y
57        self.dx = dx
58        self.dy = dy
59        self.dxl = dxl
60        self.dxw = dxw
61
62    def xaxis(self, label, unit):
63        self._xaxis = label
64        self._xunit = unit
65       
66    def yaxis(self, label, unit):
67        self._yaxis = label
68        self._yunit = unit
69
70class plottable_2D:
71    """
72        Data2D is a place holder for 2D plottables.
73    """
74    xmin = None
75    xmax = None
76    ymin = None
77    ymax = None
78    data = None
79    err_data = None
80   
81    # Units
82    _xaxis = ''
83    _xunit = ''
84    _yaxis = ''
85    _yunit = ''
86    _zaxis = ''
87    _zunit = ''
88   
89    def __init__(self, data=None, err_data=None):
90        self.data = numpy.asarray(data)
91        self.err_data = numpy.asarray(err_data)
92       
93    def xaxis(self, label, unit):
94        self._xaxis = label
95        self._xunit = unit
96       
97    def yaxis(self, label, unit):
98        self._yaxis = label
99        self._yunit = unit
100           
101    def zaxis(self, label, unit):
102        self._zaxis = label
103        self._zunit = unit
104       
105class plottable_image:
106    """
107        Data2D is a place holder for 2D plottables.
108    """
109    xmin = None
110    xmax = None
111    ymin = None
112    ymax = None
113    image = None
114   
115    # Units
116    _xaxis = ''
117    _xunit = 'pixels'
118    _yaxis = ''
119    _yunit = 'pixels'
120    _zaxis = ''
121    _zunit = ''
122   
123    def __init__(self, image=None):
124        self.image = image#numpy.asarray(data)
125       
126    def xaxis(self, label, unit):
127        self._xaxis = label
128        self._xunit = unit
129       
130    def yaxis(self, label, unit):
131        self._yaxis = label
132        self._yunit = unit
133           
134    def zaxis(self, label, unit):
135        self._zaxis = label
136        self._zunit = unit
137           
138           
139class Vector:
140    """
141        Vector class to hold multi-dimensional objects
142    """
143    ## x component
144    x = None
145    ## y component
146    y = None
147    ## z component
148    z = None
149   
150    def __init__(self, x=None, y=None, z=None):
151        """
152            Initialization. Components that are not
153            set a set to None by default.
154           
155            @param x: x component
156            @param y: y component
157            @param z: z component
158        """
159        self.x = x
160        self.y = y
161        self.z = z
162       
163    def __str__(self):
164        return "x = %s\ty = %s\tz = %s" % (str(self.x), str(self.y), str(self.z))
165       
166
167class Detector:
168    """
169        Class to hold detector information
170    """
171    ## Name of the instrument [string]
172    name = ''
173    ## Sample to detector distance [float] [mm]
174    distance = None
175    distance_unit = 'mm'
176    ## Offset of this detector position in X, Y, (and Z if necessary) [Vector] [mm]
177    offset = None
178    offset_unit = 'm'
179    ## Orientation (rotation) of this detector in roll, pitch, and yaw [Vector] [degrees]
180    orientation = None
181    orientation_unit = 'degree'
182    ## Center of the beam on the detector in X and Y (and Z if necessary) [Vector] [mm]
183    beam_center = None
184    beam_center_unit = 'mm'
185    ## Pixel size in X, Y, (and Z if necessary) [Vector] [mm]
186    pixel_size = None
187    pixel_size_unit = 'mm'
188    ## Slit length of the instrument for this detector.[float] [mm]
189    slit_length = None
190    #slit_length_unit = '1/A'
191    slit_length_unit = 'mm'
192   
193    def __init__(self):
194        """
195            Initialize class attribute that are objects...
196        """
197        self.offset      = Vector()
198        self.orientation = Vector()
199        self.beam_center = Vector()
200        self.pixel_size  = Vector()
201       
202   
203    def __str__(self):
204        _str  = "Detector:\n"
205        _str += "   Name:         %s\n" % self.name
206        _str += "   Distance:     %s [%s]\n" % \
207            (str(self.distance), str(self.distance_unit))
208        _str += "   Offset:       %s [%s]\n" % \
209            (str(self.offset), str(self.offset_unit))
210        _str += "   Orientation:  %s [%s]\n" % \
211            (str(self.orientation), str(self.orientation_unit))
212        _str += "   Beam center:  %s [%s]\n" % \
213            (str(self.beam_center), str(self.beam_center_unit))
214        _str += "   Pixel size:   %s [%s]\n" % \
215            (str(self.pixel_size), str(self.pixel_size_unit))
216        _str += "   Slit length:  %s [%s]\n" % \
217            (str(self.slit_length), str(self.slit_length_unit))
218        return _str
219
220class Aperture:
221    ## Name
222    name = None
223    ## Type
224    type = None
225    ## Size name
226    size_name = None
227    ## Aperture size [Vector]
228    size = None
229    size_unit = 'mm'
230    ## Aperture distance [float]
231    distance = None
232    distance_unit = 'mm'
233   
234    def __init__(self):
235        self.size = Vector()
236   
237class Collimation:
238    """
239        Class to hold collimation information
240    """
241    ## Name
242    name = ''
243    ## Length [float] [mm]
244    length = None
245    length_unit = 'mm'
246    ## Aperture
247    aperture = None
248   
249    def __init__(self):
250        self.aperture = []
251   
252    def __str__(self):
253        _str = "Collimation:\n"
254        _str += "   Length:       %s [%s]\n" % \
255            (str(self.length), str(self.length_unit))
256        for item in self.aperture:
257            _str += "   Aperture size:%s [%s]\n" % \
258                (str(item.size), str(item.size_unit))
259            _str += "   Aperture_dist:%s [%s]\n" % \
260                (str(item.distance), str(item.distance_unit))
261        return _str
262
263class Source:
264    """
265        Class to hold source information
266    """ 
267    ## Name
268    name = None
269    ## Radiation type [string]
270    radiation = None
271    ## Beam size name
272    beam_size_name = None
273    ## Beam size [Vector] [mm]
274    beam_size = None
275    beam_size_unit = 'mm'
276    ## Beam shape [string]
277    beam_shape = None
278    ## Wavelength [float] [Angstrom]
279    wavelength = None
280    wavelength_unit = 'A'
281    ## Minimum wavelength [float] [Angstrom]
282    wavelength_min = None
283    wavelength_min_unit = 'nm'
284    ## Maximum wavelength [float] [Angstrom]
285    wavelength_max = None
286    wavelength_max_unit = 'nm'
287    ## Wavelength spread [float] [Angstrom]
288    wavelength_spread = None
289    wavelength_spread_unit = 'percent'
290   
291    def __init__(self):
292        self.beam_size = Vector()
293       
294   
295    def __str__(self):
296        _str  = "Source:\n"
297        _str += "   Radiation:    %s\n" % str(self.radiation)
298        _str += "   Shape:        %s\n" % str(self.beam_shape)
299        _str += "   Wavelength:   %s [%s]\n" % \
300            (str(self.wavelength), str(self.wavelength_unit))
301        _str += "   Waveln_min:   %s [%s]\n" % \
302            (str(self.wavelength_min), str(self.wavelength_min_unit))
303        _str += "   Waveln_max:   %s [%s]\n" % \
304            (str(self.wavelength_max), str(self.wavelength_max_unit))
305        _str += "   Waveln_spread:%s [%s]\n" % \
306            (str(self.wavelength_spread), str(self.wavelength_spread_unit))
307        _str += "   Beam_size:    %s [%s]\n" % \
308            (str(self.beam_size), str(self.beam_size_unit))
309        return _str
310   
311   
312"""
313    Definitions of radiation types
314"""
315NEUTRON  = 'neutron'
316XRAY     = 'x-ray'
317MUON     = 'muon'
318ELECTRON = 'electron'
319   
320class Sample:
321    """
322        Class to hold the sample description
323    """
324    ## Short name for sample
325    name = ''
326    ## ID
327    ID = ''
328    ## Thickness [float] [mm]
329    thickness = None
330    thickness_unit = 'mm'
331    ## Transmission [float] [fraction]
332    transmission = None
333    ## Temperature [float] [C]
334    temperature = None
335    temperature_unit = 'C'
336    ## Position [Vector] [mm]
337    position = None
338    position_unit = 'mm'
339    ## Orientation [Vector] [degrees]
340    orientation = None
341    orientation_unit = 'degree'
342    ## Details
343    details = None
344   
345    def __init__(self):
346        self.position    = Vector()
347        self.orientation = Vector()
348        self.details     = []
349   
350    def __str__(self):
351        _str  = "Sample:\n"
352        _str += "   ID:           %s\n" % str(self.ID)
353        _str += "   Transmission: %s\n" % str(self.transmission)
354        _str += "   Thickness:    %s [%s]\n" % \
355            (str(self.thickness), str(self.thickness_unit))
356        _str += "   Temperature:  %s [%s]\n" % \
357            (str(self.temperature), str(self.temperature_unit))
358        _str += "   Position:     %s [%s]\n" % \
359            (str(self.position), str(self.position_unit))
360        _str += "   Orientation:  %s [%s]\n" % \
361            (str(self.orientation), str(self.orientation_unit))
362       
363        _str += "   Details:\n"
364        for item in self.details:
365            _str += "      %s\n" % item
366           
367        return _str
368 
369class Process:
370    """
371        Class that holds information about the processes
372        performed on the data.
373    """
374    name = ''
375    date = ''
376    description= ''
377    term = None
378    notes = None
379   
380    def __init__(self):
381        self.term = []
382        self.notes = []
383   
384    def __str__(self):
385        _str  = "Process:\n"
386        _str += "   Name:         %s\n" % self.name
387        _str += "   Date:         %s\n" % self.date
388        _str += "   Description:  %s\n" % self.description
389        for item in self.term:
390            _str += "   Term:         %s\n" % item
391        for item in self.notes:
392            _str += "   Note:         %s\n" % item
393        return _str
394   
395 
396class DataInfo:
397    """
398        Class to hold the data read from a file.
399        It includes four blocks of data for the
400        instrument description, the sample description,
401        the data itself and any other meta data.
402    """
403    ## Title
404    title      = ''
405    ## Run number
406    run        = None
407    ## Run name
408    run_name   = None
409    ## File name
410    filename   = ''
411    ## Notes
412    notes      = None
413    ## Processes (Action on the data)
414    process    = None
415    ## Instrument name
416    instrument = ''
417    ## Detector information
418    detector   = None
419    ## Sample information
420    sample     = None
421    ## Source information
422    source     = None
423    ## Collimation information
424    collimation = None
425    ## Additional meta-data
426    meta_data  = None
427    ## Loading errors
428    errors = None
429           
430    def __init__(self):
431        """
432            Initialization
433        """
434        ## Title
435        self.title      = ''
436        ## Run number
437        self.run        = []
438        self.run_name   = {}
439        ## File name
440        self.filename   = ''
441        ## Notes
442        self.notes      = []
443        ## Processes (Action on the data)
444        self.process    = []
445        ## Instrument name
446        self.instrument = ''
447        ## Detector information
448        self.detector   = []
449        ## Sample information
450        self.sample     = Sample()
451        ## Source information
452        self.source     = Source()
453        ## Collimation information
454        self.collimation = []
455        ## Additional meta-data
456        self.meta_data  = {}
457        ## Loading errors
458        self.errors = []       
459       
460    def __str__(self):
461        """
462            Nice printout
463        """
464        _str =  "File:            %s\n" % self.filename
465        _str += "Title:           %s\n" % self.title
466        _str += "Run:             %s\n" % str(self.run)
467        _str += "Instrument:      %s\n" % str(self.instrument)
468        _str += "%s\n" % str(self.sample)
469        _str += "%s\n" % str(self.source)
470        for item in self.detector:
471            _str += "%s\n" % str(item)
472        for item in self.collimation:
473            _str += "%s\n" % str(item)
474        for item in self.process:
475            _str += "%s\n" % str(item)
476        for item in self.notes:
477            _str += "%s\n" % str(item)
478
479        return _str
480           
481    # Private method to perform operation. Not implemented for DataInfo,
482    # but should be implemented for each data class inherited from DataInfo
483    # that holds actual data (ex.: Data1D)
484    def _perform_operation(self, other, operation): return NotImplemented
485
486    def __add__(self, other):
487        """
488            Add two data sets
489           
490            @param other: data set to add to the current one
491            @return: new data set
492            @raise ValueError: raised when two data sets are incompatible
493        """
494        def operation(a, b): return a+b
495        return self._perform_operation(other, operation)
496       
497    def __radd__(self, other):
498        """
499            Add two data sets
500           
501            @param other: data set to add to the current one
502            @return: new data set
503            @raise ValueError: raised when two data sets are incompatible
504        """
505        def operation(a, b): return b+a
506        return self._perform_operation(other, operation)
507       
508    def __sub__(self, other):
509        """
510            Subtract two data sets
511           
512            @param other: data set to subtract from the current one
513            @return: new data set
514            @raise ValueError: raised when two data sets are incompatible
515        """
516        def operation(a, b): return a-b
517        return self._perform_operation(other, operation)
518       
519    def __rsub__(self, other):
520        """
521            Subtract two data sets
522           
523            @param other: data set to subtract from the current one
524            @return: new data set
525            @raise ValueError: raised when two data sets are incompatible
526        """
527        def operation(a, b): return b-a
528        return self._perform_operation(other, operation)
529       
530    def __mul__(self, other):
531        """
532            Multiply two data sets
533           
534            @param other: data set to subtract from the current one
535            @return: new data set
536            @raise ValueError: raised when two data sets are incompatible
537        """
538        def operation(a, b): return a*b
539        return self._perform_operation(other, operation)
540       
541    def __rmul__(self, other):
542        """
543            Multiply two data sets
544           
545            @param other: data set to subtract from the current one
546            @return: new data set
547            @raise ValueError: raised when two data sets are incompatible
548        """
549        def operation(a, b): return b*a
550        return self._perform_operation(other, operation)
551       
552    def __div__(self, other):
553        """
554            Divided a data set by another
555           
556            @param other: data set that the current one is divided by
557            @return: new data set
558            @raise ValueError: raised when two data sets are incompatible
559        """
560        def operation(a, b): return a/b
561        return self._perform_operation(other, operation)
562       
563    def __rdiv__(self, other):
564        """
565            Divided a data set by another
566           
567            @param other: data set that the current one is divided by
568            @return: new data set
569            @raise ValueError: raised when two data sets are incompatible
570        """
571        def operation(a, b): return b/a
572        return self._perform_operation(other, operation)           
573           
574class Data1D(plottable_1D, DataInfo):
575    """
576        1D data class
577    """
578    x_unit = '1/A'
579    y_unit = '1/cm'
580   
581    def __init__(self, x, y, dx=None, dy=None):
582        DataInfo.__init__(self)
583        plottable_1D.__init__(self, x, y, dx, dy)
584       
585       
586    def __str__(self):
587        """
588            Nice printout
589        """
590        _str =  "%s\n" % DataInfo.__str__(self)
591   
592        _str += "Data:\n"
593        _str += "   Type:         %s\n" % self.__class__.__name__
594        _str += "   X-axis:       %s\t[%s]\n" % (self._xaxis, self._xunit)
595        _str += "   Y-axis:       %s\t[%s]\n" % (self._yaxis, self._yunit)
596        _str += "   Length:       %g\n" % len(self.x)
597
598        return _str
599
600    def clone_without_data(self, length=0):
601        """
602            Clone the current object, without copying the data (which
603            will be filled out by a subsequent operation).
604            The data arrays will be initialized to zero.
605           
606            @param length: length of the data array to be initialized
607        """
608        from copy import deepcopy
609       
610        x  = numpy.zeros(length) 
611        dx = numpy.zeros(length) 
612        y  = numpy.zeros(length) 
613        dy = numpy.zeros(length) 
614       
615        clone = Data1D(x, y, dx=dx, dy=dy)
616        clone.title       = self.title
617        clone.run         = self.run
618        clone.filename    = self.filename
619        clone.notes       = deepcopy(self.notes) 
620        clone.process     = deepcopy(self.process) 
621        clone.detector    = deepcopy(self.detector) 
622        clone.sample      = deepcopy(self.sample) 
623        clone.source      = deepcopy(self.source) 
624        clone.collimation = deepcopy(self.collimation) 
625        clone.meta_data   = deepcopy(self.meta_data) 
626        clone.errors      = deepcopy(self.errors) 
627       
628        return clone
629
630    def _validity_check(self, other):
631        """
632            Checks that the data lengths are compatible.
633            Checks that the x vectors are compatible.
634            Returns errors vectors equal to original
635            errors vectors if they were present or vectors
636            of zeros when none was found.
637           
638            @param other: other data set for operation
639            @return: dy for self, dy for other [numpy arrays]
640            @raise ValueError: when lengths are not compatible
641        """
642        dy_other = None
643        if isinstance(other, Data1D):
644            # Check that data lengths are the same
645            if len(self.x) != len(other.x) or \
646                len(self.y) != len(other.y):
647                raise ValueError, "Unable to perform operation: data length are not equal"
648           
649            # Here we could also extrapolate between data points
650            for i in range(len(self.x)):
651                if self.x[i] != other.x[i]:
652                    raise ValueError, "Incompatible data sets: x-values do not match"
653           
654            # Check that the other data set has errors, otherwise
655            # create zero vector
656            dy_other = other.dy
657            if other.dy==None or (len(other.dy) != len(other.y)):
658                dy_other = numpy.zeros(len(other.y))
659           
660        # Check that we have errors, otherwise create zero vector
661        dy = self.dy
662        if self.dy==None or (len(self.dy) != len(self.y)):
663            dy = numpy.zeros(len(self.y))           
664           
665        return dy, dy_other
666
667    def _perform_operation(self, other, operation):
668        """
669        """
670        # First, check the data compatibility
671        dy, dy_other = self._validity_check(other)
672        result = self.clone_without_data(len(self.x))
673       
674        for i in range(len(self.x)):
675            result.x[i] = self.x[i]
676            if self.dx is not None and len(self.x)==len(self.dx):
677                result.dx[i] = self.dx[i]
678           
679            a = Uncertainty(self.y[i], dy[i]**2)
680            if isinstance(other, Data1D):
681                b = Uncertainty(other.y[i], dy_other[i]**2)
682            else:
683                b = other
684           
685            output = operation(a, b)
686            result.y[i] = output.x
687            result.dy[i] = math.sqrt(math.fabs(output.variance))
688        return result
689       
690class Data2D(plottable_2D, DataInfo):
691    """
692        2D data class
693    """
694    ## Units for Q-values
695    Q_unit = '1/A'
696   
697    ## Units for I(Q) values
698    I_unit = '1/cm'
699   
700    ## Vector of Q-values at the center of each bin in x
701    x_bins = None
702   
703    ## Vector of Q-values at the center of each bin in y
704    y_bins = None
705   
706   
707    def __init__(self, data=None, err_data=None):
708        self.y_bins = []
709        self.x_bins = []
710        DataInfo.__init__(self)
711        plottable_2D.__init__(self, data, err_data)
712        if len(self.detector)>0:
713            raise RuntimeError, "Data2D: Detector bank already filled at init"
714
715    def __str__(self):
716        _str =  "%s\n" % DataInfo.__str__(self)
717       
718        _str += "Data:\n"
719        _str += "   Type:         %s\n" % self.__class__.__name__
720        _str += "   X- & Y-axis:  %s\t[%s]\n" % (self._yaxis, self._yunit)
721        _str += "   Z-axis:       %s\t[%s]\n" % (self._zaxis, self._zunit)
722        leny = 0
723        if len(self.data)>0:
724            leny = len(self.data[0])
725        _str += "   Length:       %g x %g\n" % (len(self.data), leny)
726       
727        return _str
728 
729    def clone_without_data(self, length=0):
730        """
731            Clone the current object, without copying the data (which
732            will be filled out by a subsequent operation).
733            The data arrays will be initialized to zero.
734           
735            @param length: length of the data array to be initialized
736        """
737        from copy import deepcopy
738       
739        data     = numpy.zeros(length) 
740        err_data = numpy.zeros(length) 
741       
742        clone = Data2D(data, err_data)
743        clone.title       = self.title
744        clone.run         = self.run
745        clone.filename    = self.filename
746        clone.notes       = deepcopy(self.notes) 
747        clone.process     = deepcopy(self.process) 
748        clone.detector    = deepcopy(self.detector) 
749        clone.sample      = deepcopy(self.sample) 
750        clone.source      = deepcopy(self.source) 
751        clone.collimation = deepcopy(self.collimation) 
752        clone.meta_data   = deepcopy(self.meta_data) 
753        clone.errors      = deepcopy(self.errors) 
754       
755        return clone
756 
757 
758    def _validity_check(self, other):
759        """
760            Checks that the data lengths are compatible.
761            Checks that the x vectors are compatible.
762            Returns errors vectors equal to original
763            errors vectors if they were present or vectors
764            of zeros when none was found.
765           
766            @param other: other data set for operation
767            @return: dy for self, dy for other [numpy arrays]
768            @raise ValueError: when lengths are not compatible
769        """
770        err_other = None
771        if isinstance(other, Data2D):
772            # Check that data lengths are the same
773            if numpy.size(self.data) != numpy.size(other.data):
774                raise ValueError, "Unable to perform operation: data length are not equal"
775               
776            # Check that the scales match
777            #TODO: matching scales?     
778           
779            # Check that the other data set has errors, otherwise
780            # create zero vector
781            #TODO: test this
782            err_other = other.err_data
783            if other.err_data==None or (numpy.size(other.err_data) != numpy.size(other.data)):
784                err_other = numpy.zeros([numpy.size(other.data,0), numpy.size(other.data,1)])
785           
786        # Check that we have errors, otherwise create zero vector
787        err = self.err_data
788        if self.err_data==None or (numpy.size(self.err_data) != numpy.size(self.data)):
789            err = numpy.zeros([numpy.size(self.data,0), numpy.size(self.data,1)])
790           
791        return err, err_other
792 
793 
794    def _perform_operation(self, other, operation):
795        """
796            Perform 2D operations between data sets
797           
798            @param other: other data set
799            @param operation: function defining the operation
800        """
801        # First, check the data compatibility
802        dy, dy_other = self._validity_check(other)
803   
804        result = self.clone_without_data([numpy.size(self.data,0), numpy.size(self.data,1)])
805       
806        for i in range(numpy.size(self.data,0)):
807            for j in range(numpy.size(self.data,1)):
808                result.data[i][j] = self.data[i][j]
809                if self.err_data is not None and numpy.size(self.data)==numpy.size(self.err_data):
810                    result.err_data[i][j] = self.err_data[i][j]
811               
812                a = Uncertainty(self.data[i][j], dy[i][j]**2)
813                if isinstance(other, Data2D):
814                    b = Uncertainty(other.data[i][j], dy_other[i][j]**2)
815                else:
816                    b = other
817               
818                output = operation(a, b)
819                result.data[i][j] = output.x
820                result.err_data[i][j] = math.sqrt(math.fabs(output.variance))
821        return result
822   
823#Need more work to make it work   
824class Image2D(plottable_image, DataInfo):
825    """
826        2D image class
827    """
828   
829   
830    def __init__(self, image=None,xmin=None, xmax=None, ymin=None, ymax=None):
831       
832        DataInfo.__init__(self)
833        plottable_image.__init__(self, image)
834        self.pictype = 'image'
835    def __str__(self):
836        _str =  "%s\n" % DataInfo.__str__(self)
837       
838        _str += "Image:\n"
839       # _str += "   Type:         %s\n" % self.__class__.__name__
840       
841        return _str
842 
843 
844 
Note: See TracBrowser for help on using the repository browser.