Exemple #1
0
class AutoRefreshDialog(traits.HasTraits):

    minutes = traits.Float(1.0)
    autoRefreshBool = traits.Bool()

    emailAlertBool = traits.Bool(False)
    soundAlertBool = traits.Bool(False)
    linesOfDataFrame = traits.Range(1, 10)
    alertCode = traits.Code(
        DEFAULT_ALERT_CODE,
        desc="python code for finding alert worthy elements")

    basicGroup = traitsui.Group("minutes", "autoRefreshBool")
    alertGroup = traitsui.VGroup(
        traitsui.HGroup(traitsui.Item("emailAlertBool"),
                        traitsui.Item("soundAlertBool")),
        traitsui.Item("linesOfDataFrame",
                      visible_when="emailAlertBool or soundAlertBool"),
        traitsui.Item("alertCode",
                      visible_when="emailAlertBool or soundAlertBool"))

    traits_view = traitsui.View(traitsui.VGroup(basicGroup, alertGroup),
                                title="auto refresh",
                                buttons=[OKButton],
                                kind='livemodal',
                                resizable=True)
Exemple #2
0
class Element(traits.HasTraits):
    """parent class for a defined element. Element can be chosen as
    a physics property in the physics tab and allow fits to calculate
    properties of atomic clouds"""
    nameID = traits.String(
        desc="name of element for dictionary key (no superscripts etc)")
    massATU = traits.Float(22.9897692807,
                           label="mass (u)",
                           desc="mass in atomic mass units")
    decayRateMHz = traits.Float(
        9.7946,
        label=u"Decay Rate \u0393 (MHz)",
        desc="decay rate/ natural line width of 2S1/2 -> 2P3/2")

    crossSectionSigmaPlus = traits.Float(
        1.6573163925E-13,
        label=u"cross section \u03C3 + (m^2)",
        desc=
        "resonant cross section 2S1/2 -> 2P3/2. Warning not accurate for 6Li yet"
    )

    scatteringLength = traits.Float(62.0, label="scattering length (a0)")
    IsatSigmaPlus = traits.Float(6.260021,
                                 width=10,
                                 label=u"Isat (mW/cm^2)",
                                 desc="I sat sigma + 2S1/2 -> 2P3/2")

    traits_view = traitsui.View(
        traitsui.VGroup(
            traitsui.Item("nameID", style="readonly"),
            traitsui.Item("massATU", style="readonly"),
            traitsui.Item("decayRateMHz", style="readonly"),
            traitsui.Item("crossSectionSigmaPlus", style="readonly"),
            traitsui.Item("scatteringLength"),
            traitsui.Item("IsatSigmaPlus", style="readonly")))
class EntryBlock(traits.HasTraits):
    
    fieldName = traits.String("fieldName",desc = "describes what the information to be entered in the text block is referring to")
    textBlock = traits.String()
    commitButton = traits.Button("save",desc="commit information in text block to logFile")

    
    traits_view = traitsui.View(traitsui.VGroup(
                    traitsui.Item("fieldName",show_label=False, style="readonly"),
                    traitsui.Item("textBlock",show_label=False, style="custom"),
                    traitsui.Item("commitButton",show_label=False), show_border=True, label="information"
                        ))
    
    def __init__(self, **traitsDict):
        """user supplies arguments in init to supply class attributes defined above """
        super(EntryBlock,self).__init__(**traitsDict)
        
    def _commitButton_fired(self):
        logger.info("saving %s info starting" % self.fieldName)
        timeStamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        blockDelimiterStart = "__"+self.fieldName+"__<start>"
        blockDelimiterEnd = "__"+self.fieldName+"__<end>"
        fullString = "\n"+blockDelimiterStart+"\n"+timeStamp+"\n"+self.textBlock+"\n"+blockDelimiterEnd+"\n"
        with open(self.commentFile, "a+") as writeFile:
            writeFile.write(fullString)
        logger.info("saving %s info finished" % self.fieldName)
    
    def clearTextBlock(self):
        self.textBlock = ""
class AxisSelector(traits.HasTraits):
    """here we select what axes the user should use when plotting this data """
    masterList = traits.List
    masterListWithNone =  traits.List
    xAxis = traits.Enum(values="masterList")
    yAxis = traits.Enum(values="masterList")
    series = traits.Enum(values="masterListWithNone")
    
    traits_view=traitsui.View(traitsui.VGroup(traitsui.Item("xAxis",label="x axis"),traitsui.Item("yAxis",label="y axis"),
                                  traitsui.Item("series",label="series"),show_border=True, label="axes selection"))
    
    def __init__(self, **traitsDict):
        """allows user to select which axes are useful for plotting in this log"""
        super(AxisSelector, self).__init__(**traitsDict)
    
    
    def _masterList_default(self):
        """gets the header row of log file which are interpreted as the column
        names that can be plotted."""
        logger.info("updating master list of axis choices")
        logger.debug("comment file = %s" % self.logFile)
        logger.debug( "comment file = %s" % self.logFile)
        if not os.path.exists(self.logFile):
            return []
        try:
            with open(self.logFile) as csvfile:
                headerReader = csv.reader(csvfile)
                headerRow=headerReader.next()
            return headerRow
        except IOError:
            return []
            
    def _masterListWithNone_default(self):
        return ["None"]+self._masterList_default()
Exemple #5
0
class EntryBlock(traits.HasTraits):

    fieldName = traits.String(
        "fieldName",
        desc=
        "describes what the information to be entered in the text block is referring to"
    )
    textBlock = traits.String()

    traits_view = traitsui.View(
        traitsui.VGroup(traitsui.Item("fieldName",
                                      show_label=False,
                                      style="readonly"),
                        traitsui.Item("textBlock",
                                      show_label=False,
                                      style="custom"),
                        show_border=True,
                        label="information"))

    def __init__(self, **traitsDict):
        """user supplies arguments in init to supply class attributes defined above """
        super(EntryBlock, self).__init__(**traitsDict)

    def clearTextBlock(self):
        self.textBlock = ""
Exemple #6
0
class Something(tr.HasTraits):

    txt_file_name = tr.File

    openTxt = tr.Button('Open...')

    a = tr.Int(20, auto_set=False, enter_set=True,
               input=True)

    b = tr.Float(20, auto_set=False, enter_set=True,
                 input=True)

    @tr.on_trait_change('+input')
    def _handle_input_change(self):
        print('some input parameter changed')
        self.input_event = True

    input_event = tr.Event

    def _some_event_changed(self):
        print('input happend')

    def _openTxt_fired(self):
        print('do something')
        print(self.txt_file_name)

    traits_view = ui.View(
        ui.VGroup(
            ui.HGroup(
                ui.Item('openTxt', show_label=False),
                ui.Item('txt_file_name', width=200),
                ui.Item('a')
            ),
        )
    )
class Librarian(traits.HasTraits):
    """Librarian provides a way of writing useful information into the 
    log folder for eagle logs. It is designed to make the information inside
    an eagle log easier to come back to. It mainly writes default strings into
    the comments file in the log folder"""
    
    logType = traits.Enum("important","debug","calibration")
    typeCommitButton = traits.Button("save")
    axisList = AxisSelector()
    purposeBlock = EntryBlock(fieldName="What is the purpose of this log?")
    explanationBlock = EntryBlock(fieldName = "Explain what the data shows (important parameters that change, does it make sense etc.)?")
    additionalComments = EntryBlock(fieldName = "Anything Else?")

    traits_view = traitsui.View(
        traitsui.VGroup(
            traitsui.Item("logFolder",show_label=False, style="readonly"),
            traitsui.HGroup(traitsui.Item("logType",show_label=False),traitsui.Item("typeCommitButton",show_label=False)),
            traitsui.Item("axisList",show_label=False, editor=traitsui.InstanceEditor(),style='custom'),
            traitsui.Item("purposeBlock",show_label=False, editor=traitsui.InstanceEditor(),style='custom'),
            traitsui.Item("explanationBlock",show_label=False, editor=traitsui.InstanceEditor(),style='custom'),
            traitsui.Item("additionalComments",show_label=False, editor=traitsui.InstanceEditor(),style='custom')
        )  , resizable=True  , kind ="live"
    )    
    
    def __init__(self, **traitsDict):
        """Librarian object requires the log folder it is referring to. If a .csv
        file is given as logFolder argument it will use parent folder as the 
        logFolder"""
        super(Librarian, self).__init__(**traitsDict)
        if os.path.isfile(self.logFolder):
            self.logFolder = os.path.split(self.logFolder)[0]
        else:
            logger.debug("found these in %s: %s" %(self.logFolder, os.listdir(self.logFolder) ))
        
        self.logFile = os.path.join(self.logFolder, os.path.split(self.logFolder)[1]+".csv")
        self.commentFile = os.path.join(self.logFolder, "comments.txt")
        self.axisList.commentFile = self.commentFile
        self.axisList.logFile = self.logFile
        self.purposeBlock.commentFile = self.commentFile
        self.explanationBlock.commentFile = self.commentFile
        self.additionalComments.commentFile  = self.commentFile
        
    def _typeCommitButton_fired(self):
        logger.info("saving axes info starting")
        timeStamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        blockDelimiterStart = "__Log Type__<start>"
        blockDelimiterEnd = "__Log Type__<end>"
        fullString = "\n"+blockDelimiterStart+"\n"+timeStamp+"\n"+self.logType+"\n"+blockDelimiterEnd+"\n"
        with open(self.commentFile, "a+") as writeFile:
            writeFile.write(fullString)
        logger.info("saving axes info finished")
Exemple #8
0
class ViewHandler(ui.Handler):

    # You can initialize this by obtaining it from the methods below and, self.info = info
    info = tr.Instance(ui.UIInfo)

    exit_view = ui.View(ui.VGroup(
        ui.Label('Do you really wish to end '
                 'the session? Any unsaved data '
                 'will be lost.'),
        ui.HGroup(ui.Item('ok', show_label=False, springy=True),
                  ui.Item('cancel', show_label=False, springy=True))),
                        title='Exit dialog',
                        kind='live')

    def menu_utilities_csv_joiner(self):
        csv_joiner = CSVJoiner()
        # kind='modal' pauses the background traits window until this window is closed
        csv_joiner.configure_traits()

    def menu_about_tool(self):
        about_tool = AboutTool()
        about_tool.configure_traits()

    def get_outfile(self, folder_name, file_name):
        '''Returns a file in the specified folder using the home
        directory as root.
        '''
        HOME_DIR = os.path.expanduser("~")
        out_dir = os.path.join(HOME_DIR, folder_name)
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)
        outfile = os.path.join(out_dir, file_name)
        return outfile

    def menu_save(self, info):
        file_name = self.get_outfile(folder_name='.hcft', file_name='')
        file_ = save_file(file_name=file_name)
        if file_:
            pickle.dump(info.object.root, open(file_, 'wb'), 1)

    def menu_open(self, info):
        file_name = self.get_outfile(folder_name='.hcft', file_name='')
        file_ = open_file(file_name=file_name)
        if file_:
            info.object.root = pickle.load(open(file_, 'rb'))

    def menu_exit(self, info):
        if info.initialized:
            info.ui.dispose()
class FilterTool(tr.HasTraits):
    data = tr.Array
    max_chans = tr.Int
    t = tr.Array
    channel = tr.Int
    filter_type = tr.Enum(filter_dict.keys())
    filter = tr.Instance(Filter)
    _ds = tr.Instance(ch.ArrayPlotData)
    _plot = tr.Instance(ch.Plot)

    def _max_chans_default(self):
        return int(self.data.shape[1] - 1)

    def _filter_default(self):
        return SvdFilter(t=self.t, d=self.data)

    def __ds_default(self):
        return ch.ArrayPlotData(t=self.t,
                                y=self.data[:, self.channel],
                                yf=self.filter.yf)

    def __plot_default(self):
        pl = ch.Plot(self._ds)
        pl.plot(('t', 'y'), color='black')
        pl.plot(('t', 'yf'), color='red', line_width=1.2)
        return pl

    @tr.on_trait_change('filter.replot')
    def replot(self):
        self._ds.set_data('yf', self.filter.yf)

    def _channel_changed(self):
        self._ds.set_data('y', self.data[:, self.channel])
        self.filter.chan = int(self.channel)
        self.replot()

    def _filter_type_changed(self, value):
        self.filter = filter_dict[value](t=self.t, d=self.data)

    plot_item = ui.Item('_plot', editor=en.ComponentEditor(), show_label=False)

    ch_item = ui.Item('channel',
                      editor=ui.RangeEditor(low=0,
                                            high_name='max_chans',
                                            is_float=False))
    settings_group = ui.VGroup([ch_item, 'filter_type', '@filter'])

    traits_view = ui.View(ui.HGroup([plot_item, settings_group]))
class AboutTool(tr.HasStrictTraits):
    about_tool_text = tr.Str(
        'High-Cycle Fatigue Tool \nVersion: 1.0.0\n\nHCFT is a tool with a graphical user interface \nfor processing CSV files obtained from fatigue \nexperiments up to the high-cycle fatigue ranges.\nAdditionally, tests with monotonic loading can be processed.\n\nDeveloped in:\nRWTH Aachen University - Institute of Structural Concrete\nBy:\nDr.-Ing. Rostislav Chudoba\nM.Sc. Homam Spartali\n\nGithub link:\nhttps://github.com/ishomam/high-cycle-fatigue-tool'
    )

    # =========================================================================
    # Configuration of the view
    # =========================================================================
    traits_view = ui.View(ui.VGroup(ui.UItem('about_tool_text',
                                             style='readonly'),
                                    show_border=True),
                          buttons=[ui.OKButton],
                          title='About HCFT',
                          resizable=True,
                          width=0.3,
                          height=0.25)
class AxisSelector(traits.HasTraits):
    """here we select what axes the user should use when plotting this data """
    masterList = traits.List
    masterListWithNone =  traits.List
    xAxis = traits.Enum(values="masterList")
    yAxis = traits.Enum(values="masterList")
    series = traits.Enum(values="masterListWithNone")
    commitButton = traits.Button("save",desc="commit information in text block to logFile")
    
    traits_view=traitsui.View(traitsui.VGroup(traitsui.Item("xAxis",label="x axis"),traitsui.Item("yAxis",label="y axis"),
                                  traitsui.Item("series",label="series"),traitsui.Item("commitButton",show_label=False),show_border=True, label="axes selection"))
    
    def __init__(self, **traitsDict):
        """allows user to select which axes are useful for plotting in this log"""
        super(AxisSelector, self).__init__(**traitsDict)
    
    
    def _masterList_default(self):
        """gets the header row of log file which are interpreted as the column
        names that can be plotted."""
        logger.info("updating master list of axis choices")
        logger.debug("comment file = %s" % self.logFile)
        print "comment file = %s" % self.logFile
        if not os.path.exists(self.logFile):
            return []
        try:
            with open(self.logFile) as csvfile:
                headerReader = csv.reader(csvfile)
                headerRow=headerReader.next()
            return headerRow
        except IOError:
            return []
            
    def _masterListWithNone_default(self):
        return ["None"]+self._masterList_default()
        
    def _commitButton_fired(self):
        logger.info("saving axes info starting")
        timeStamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        blockDelimiterStart = "__Axes Selection__<start>"
        blockDelimiterEnd = "__Axes Selection__<end>"
        textBlock = "xAxis = %s\nyAxis = %s\n series = %s" % (self.xAxis,self.yAxis,self.series)
        fullString = "\n"+blockDelimiterStart+"\n"+timeStamp+"\n"+textBlock+"\n"+blockDelimiterEnd+"\n"
        with open(self.commentFile, "a+") as writeFile:
            writeFile.write(fullString)
        logger.info("saving axes info finished")
Exemple #12
0
class HCFFRoot(HCFFParent):

    #name = tr.Str('root')

    import_manager = tr.Instance(FileImportManager, ())

    plot_options = tr.List(PlotOptions)

    output_npy = tr.Property()

    tree_view = ui.View(
        ui.VGroup(
            ui.Item('import_manager', style='custom', show_label=False)
        )
    )

    traits_view = tree_view
class ExamineVariablesDictionary(traits.HasTraits):
    """simple wrapper class for displaying the contents of the variables dictionary
    for a particular hardware action"""
    hdwA = traits.Instance(hardwareAction.hardwareAction.HardwareAction)
    displayList = traits.List(traits.Str)
    hardwareActionName = traits.Str

    def __init__(self, **traitsDict):
        super(ExamineVariablesDictionary, self).__init__(**traitsDict)

    def generateDisplayList(self):
        """return a new python lis that is ready for display """
        dispList = []
        for v in self.hdwA.variables:
            if v in self.hdwA.variablesReference:
                value = "%G" % self.hdwA.variablesReference[
                    v]  # string formatted float
            else:
                logger.warning(
                    "we are missing variable %s for hardware %s  in variable definitions"
                    % (v, self.hardwareActionName))
                value = "?"  # key not found could be we haven't loaded the dictionary or that the variable is missing in control
            dispList.append("%s = %s" % (v, value))
        return dispList

    def updateDisplayList(self):
        """updates display list to be a list that contains the keys and values 
        of variablesList in nice strings for user to see"""
        self.displayList = self.generateDisplayList()

    def _displayList_default(self):
        return self.generateDisplayList()

    def _hardwareActionName_default(self):
        return self.hdwA.hardwareActionName

    traits_view = traitsui.View(
        traitsui.VGroup(
            traitsui.Item("hardwareActionName",
                          show_label=False,
                          style="readonly"),
            traitsui.Item("displayList",
                          editor=traitsui.ListEditor(style="readonly"),
                          show_label=False)))
class FileFrame(ta.HasTraits):
    """
    Frame for file selecting
    """
    def_file = '/home/jackdra/LQCD/Scripts/EDM_paper/graphs/FF/FullFFFit/Neutron_ContFit_a.pdf'
    def_folder = '/home/jackdra/LQCD/Scripts/EDM_paper/graphs/FF/FullFFFit/'
    file_directory = ta.Directory(def_folder)
    file_name = ta.File(def_file, filter=['*.pdf'])

    Add_File = ta.Button()
    Add_Folder = ta.Button()
    # Undo_Add = ta.Button()

    view = tua.View(
        tua.HSplit(
            tua.Item('file_directory', style='custom', springy=True),
            tua.Item('file_name', style='custom', springy=True),
            tua.VGroup(tua.Item('file_directory', springy=True),
                       tua.Item('file_name', springy=True),
                       tua.Item('Add_File', show_label=False),
                       tua.Item('Add_Folder', show_label=False)
                       # tua.Item('Undo_Add',show_label=False),
                       )),
        resizable=True,
        height=1000,
        width=1500)

    def _file_name_changed(self):
        self.file_directory = '/'.join(self.file_name.split('/')[:-1]) + '/'

    def _file_directory_changed(self):
        file_list = GetAllPDF(self.file_directory)
        if len(file_list) > 0:
            self.file_name = GetAllPDF(self.file_directory)[0]

    def _Add_File_fired(self):
        global files_selected
        files_selected.file_list.append(self.file_name)

    def _Add_Folder_fired(self):
        global files_selected
        files_selected.file_list += GetAllPDF(self.file_directory)
Exemple #15
0
def create_view(window_name):
    view = tuiapi.View(tuiapi.HSplit(
        tuiapi.VGroup(
            tuiapi.Item('Multi_Select',
                        show_label=False,
                        width=224,
                        height=668,
                        springy=True,
                        resizable=True),
            tuiapi.Item('Change_Axis', show_label=False),
        ),
        tuiapi.Item('Plot_Data',
                    show_label=False,
                    width=800,
                    height=768,
                    springy=True,
                    resizable=True)),
                       style='custom',
                       width=1124,
                       height=868,
                       resizable=True,
                       title=window_name)
    return view
class OptionsDictionaryDialog(traits.HasTraits):
    """options dictionary dialog for editing the options of an image processor"""

    optionsList = traits.List(Option)
    traits_view = traitsui.View(
        traitsui.VGroup(
            traitsui.Item("optionsList",
                          editor=traitsui.ListEditor(style="custom"),
                          show_label=False,
                          resizable=True)),
        buttons=[traitsui.OKButton, traitsui.CancelButton],
        kind="livemodal",
        width=0.15,
        height=0.5)

    def populateOptionsFromDictionary(self, optionsDict):
        """creates the options for GUI from an options dictionary"""
        for key, value in optionsDict.iteritems():
            self.optionsList.append(createOption(key, value))

    def getOptionsDictionaryFromList(self):
        """returns an options dictionary from the current state of the options list"""
        return collections.OrderedDict([(option.name, option.value)
                                        for option in self.optionsList])
class ImagePlotInspector(traits.HasTraits):
    #Traits view definitions:

    settingsGroup = traitsui.VGroup(
        traitsui.VGroup(traitsui.HGroup('autoRangeColor', 'colorMapRangeLow',
                                        'colorMapRangeHigh'),
                        traitsui.HGroup('horizontalAutoRange',
                                        'horizontalLowerLimit',
                                        'horizontalUpperLimit'),
                        traitsui.HGroup('verticalAutoRange',
                                        'verticalLowerLimit',
                                        'verticalUpperLimit'),
                        label="axis limits",
                        show_border=True),
        traitsui.VGroup(traitsui.HGroup('object.model.scale',
                                        'object.model.offset'),
                        traitsui.HGroup(
                            traitsui.Item('object.model.pixelsX',
                                          label="Pixels X"),
                            traitsui.Item('object.model.pixelsY',
                                          label="Pixels Y")),
                        traitsui.HGroup(
                            traitsui.Item('object.model.ODCorrectionBool',
                                          label="Correct OD?"),
                            traitsui.Item('object.model.ODSaturationValue',
                                          label="OD saturation value")),
                        traitsui.HGroup(
                            traitsui.Item('contourLevels',
                                          label="Contour Levels"),
                            traitsui.Item('colormap', label="Colour Map")),
                        traitsui.HGroup(
                            traitsui.Item("cameraModel",
                                          label="Update Camera Settings to:")),
                        label="advanced",
                        show_border=True),
        label="settings")
    plotGroup = traitsui.Group(
        traitsui.Item('container',
                      editor=ComponentEditor(size=(800, 600)),
                      show_label=False))
    mainPlotGroup = traitsui.HSplit(plotGroup, label="Image")

    traits_view = traitsui.View(settingsGroup,
                                plotGroup,
                                handler=EagleHandler,
                                resizable=True)

    model = CameraImage()
    contourLevels = traits.Int(15)
    colormap = traits.Enum(colormaps.color_map_name_dict.keys())

    autoRangeColor = traits.Bool(True)
    colorMapRangeLow = traits.Float
    colorMapRangeHigh = traits.Float

    horizontalAutoRange = traits.Bool(True)
    horizontalLowerLimit = traits.Float
    horizontalUpperLimit = traits.Float

    verticalAutoRange = traits.Bool(True)
    verticalLowerLimit = traits.Float
    verticalUpperLimit = traits.Float

    fixAspectRatioBool = traits.Bool(False)

    cameraModel = traits.Enum("Custom", "ALTA0", "ANDOR0", "ALTA1", "ANDOR1")

    #---------------------------------------------------------------------------
    # Private Traits
    #---------------------------------------------------------------------------
    _image_index = traits.Instance(chaco.GridDataSource)
    _image_value = traits.Instance(chaco.ImageData)
    _cmap = traits.Trait(colormaps.jet, traits.Callable)

    #---------------------------------------------------------------------------
    # Public View interface
    #---------------------------------------------------------------------------

    def __init__(self, *args, **kwargs):
        super(ImagePlotInspector, self).__init__(*args, **kwargs)
        #self.update(self.model)
        self.create_plot()
        #self._selectedFile_changed()
        logger.info("initialisation of experiment Eagle complete")

    def create_plot(self):

        # Create the mapper, etc
        self._image_index = chaco.GridDataSource(scipy.array([]),
                                                 scipy.array([]),
                                                 sort_order=("ascending",
                                                             "ascending"))
        image_index_range = chaco.DataRange2D(self._image_index)
        self._image_index.on_trait_change(self._metadata_changed,
                                          "metadata_changed")

        self._image_value = chaco.ImageData(data=scipy.array([]),
                                            value_depth=1)

        image_value_range = chaco.DataRange1D(self._image_value)

        # Create the contour plots
        #self.polyplot = ContourPolyPlot(index=self._image_index,
        self.polyplot = chaco.CMapImagePlot(
            index=self._image_index,
            value=self._image_value,
            index_mapper=chaco.GridMapper(range=image_index_range),
            color_mapper=self._cmap(image_value_range))

        # Add a left axis to the plot
        left = chaco.PlotAxis(orientation='left',
                              title="y",
                              mapper=self.polyplot.index_mapper._ymapper,
                              component=self.polyplot)
        self.polyplot.overlays.append(left)

        # Add a bottom axis to the plot
        bottom = chaco.PlotAxis(orientation='bottom',
                                title="x",
                                mapper=self.polyplot.index_mapper._xmapper,
                                component=self.polyplot)
        self.polyplot.overlays.append(bottom)

        # Add some tools to the plot
        self.polyplot.tools.append(
            tools.PanTool(self.polyplot,
                          constrain_key="shift",
                          drag_button="middle"))

        self.polyplot.overlays.append(
            tools.ZoomTool(component=self.polyplot,
                           tool_mode="box",
                           always_on=False))

        self.lineInspectorX = clickableLineInspector.ClickableLineInspector(
            component=self.polyplot,
            axis='index_x',
            inspect_mode="indexed",
            write_metadata=True,
            is_listener=False,
            color="white")

        self.lineInspectorY = clickableLineInspector.ClickableLineInspector(
            component=self.polyplot,
            axis='index_y',
            inspect_mode="indexed",
            write_metadata=True,
            color="white",
            is_listener=False)

        self.polyplot.overlays.append(self.lineInspectorX)
        self.polyplot.overlays.append(self.lineInspectorY)

        self.boxSelection2D = boxSelection2D.BoxSelection2D(
            component=self.polyplot)
        self.polyplot.overlays.append(self.boxSelection2D)

        # Add these two plots to one container
        self.centralContainer = chaco.OverlayPlotContainer(padding=0,
                                                           use_backbuffer=True,
                                                           unified_draw=True)
        self.centralContainer.add(self.polyplot)

        # Create a colorbar
        cbar_index_mapper = chaco.LinearMapper(range=image_value_range)
        self.colorbar = chaco.ColorBar(
            index_mapper=cbar_index_mapper,
            plot=self.polyplot,
            padding_top=self.polyplot.padding_top,
            padding_bottom=self.polyplot.padding_bottom,
            padding_right=40,
            resizable='v',
            width=30)

        self.plotData = chaco.ArrayPlotData(
            line_indexHorizontal=scipy.array([]),
            line_valueHorizontal=scipy.array([]),
            scatter_indexHorizontal=scipy.array([]),
            scatter_valueHorizontal=scipy.array([]),
            scatter_colorHorizontal=scipy.array([]),
            fitLine_indexHorizontal=scipy.array([]),
            fitLine_valueHorizontal=scipy.array([]))

        self.crossPlotHorizontal = chaco.Plot(self.plotData, resizable="h")
        self.crossPlotHorizontal.height = 100
        self.crossPlotHorizontal.padding = 20
        self.crossPlotHorizontal.plot(
            ("line_indexHorizontal", "line_valueHorizontal"), line_style="dot")
        self.crossPlotHorizontal.plot(
            ("scatter_indexHorizontal", "scatter_valueHorizontal",
             "scatter_colorHorizontal"),
            type="cmap_scatter",
            name="dot",
            color_mapper=self._cmap(image_value_range),
            marker="circle",
            marker_size=4)

        self.crossPlotHorizontal.index_range = self.polyplot.index_range.x_range

        self.plotData.set_data("line_indexVertical", scipy.array([]))
        self.plotData.set_data("line_valueVertical", scipy.array([]))
        self.plotData.set_data("scatter_indexVertical", scipy.array([]))
        self.plotData.set_data("scatter_valueVertical", scipy.array([]))
        self.plotData.set_data("scatter_colorVertical", scipy.array([]))
        self.plotData.set_data("fitLine_indexVertical", scipy.array([]))
        self.plotData.set_data("fitLine_valueVertical", scipy.array([]))

        self.crossPlotVertical = chaco.Plot(self.plotData,
                                            width=140,
                                            orientation="v",
                                            resizable="v",
                                            padding=20,
                                            padding_bottom=160)
        self.crossPlotVertical.plot(
            ("line_indexVertical", "line_valueVertical"), line_style="dot")

        self.crossPlotVertical.plot(
            ("scatter_indexVertical", "scatter_valueVertical",
             "scatter_colorVertical"),
            type="cmap_scatter",
            name="dot",
            color_mapper=self._cmap(image_value_range),
            marker="circle",
            marker_size=4)

        self.crossPlotVertical.index_range = self.polyplot.index_range.y_range

        # Create a container and add components
        self.container = chaco.HPlotContainer(padding=40,
                                              fill_padding=True,
                                              bgcolor="white",
                                              use_backbuffer=False)

        inner_cont = chaco.VPlotContainer(padding=40, use_backbuffer=True)
        inner_cont.add(self.crossPlotHorizontal)
        inner_cont.add(self.centralContainer)
        self.container.add(self.colorbar)
        self.container.add(inner_cont)
        self.container.add(self.crossPlotVertical)

    def update(self, model):
        print "updating"
        logger.info("updating plot")
        #        if self.selectedFile=="":
        #            logger.warning("selected file was empty. Will not attempt to update plot.")
        #            return
        if self.autoRangeColor:
            self.colorbar.index_mapper.range.low = model.minZ
            self.colorbar.index_mapper.range.high = model.maxZ
        self._image_index.set_data(model.xs, model.ys)
        self._image_value.data = model.zs
        self.plotData.set_data("line_indexHorizontal", model.xs)
        self.plotData.set_data("line_indexVertical", model.ys)
        self.updatePlotLimits()
        self._image_index.metadata_changed = True
        self.container.invalidate_draw()
        self.container.request_redraw()

    #---------------------------------------------------------------------------
    # Event handlers
    #---------------------------------------------------------------------------

    def _metadata_changed(self, old, new):
        """ This function takes out a cross section from the image data, based
        on the line inspector selections, and updates the line and scatter
        plots."""
        if self.horizontalAutoRange:
            self.crossPlotHorizontal.value_range.low = self.model.minZ
            self.crossPlotHorizontal.value_range.high = self.model.maxZ
        if self.verticalAutoRange:
            self.crossPlotVertical.value_range.low = self.model.minZ
            self.crossPlotVertical.value_range.high = self.model.maxZ
        if self._image_index.metadata.has_key("selections"):
            selections = self._image_index.metadata["selections"]
            if not selections:  #selections is empty list
                return  #don't need to do update lines as no mouse over screen. This happens at beginning of script
            x_ndx, y_ndx = selections
            if y_ndx and x_ndx:
                self.plotData.set_data("line_valueHorizontal",
                                       self._image_value.data[y_ndx, :])
                self.plotData.set_data("line_valueVertical",
                                       self._image_value.data[:, x_ndx])
                xdata, ydata = self._image_index.get_data()
                xdata, ydata = xdata.get_data(), ydata.get_data()
                self.plotData.set_data("scatter_indexHorizontal",
                                       scipy.array([xdata[x_ndx]]))
                self.plotData.set_data("scatter_indexVertical",
                                       scipy.array([ydata[y_ndx]]))
                self.plotData.set_data(
                    "scatter_valueHorizontal",
                    scipy.array([self._image_value.data[y_ndx, x_ndx]]))
                self.plotData.set_data(
                    "scatter_valueVertical",
                    scipy.array([self._image_value.data[y_ndx, x_ndx]]))
                self.plotData.set_data(
                    "scatter_colorHorizontal",
                    scipy.array([self._image_value.data[y_ndx, x_ndx]]))
                self.plotData.set_data(
                    "scatter_colorVertical",
                    scipy.array([self._image_value.data[y_ndx, x_ndx]]))
        else:
            self.plotData.set_data("scatter_valueHorizontal", scipy.array([]))
            self.plotData.set_data("scatter_valueVertical", scipy.array([]))
            self.plotData.set_data("line_valueHorizontal", scipy.array([]))
            self.plotData.set_data("line_valueVertical", scipy.array([]))
            self.plotData.set_data("fitLine_valueHorizontal", scipy.array([]))
            self.plotData.set_data("fitLine_valueVertical", scipy.array([]))

    def _colormap_changed(self):
        self._cmap = colormaps.color_map_name_dict[self.colormap]
        if hasattr(self, "polyplot"):
            value_range = self.polyplot.color_mapper.range
            self.polyplot.color_mapper = self._cmap(value_range)
            value_range = self.crossPlotHorizontal.color_mapper.range
            self.crossPlotHorizontal.color_mapper = self._cmap(value_range)
            # FIXME: change when we decide how best to update plots using
            # the shared colormap in plot object
            self.crossPlotHorizontal.plots["dot"][0].color_mapper = self._cmap(
                value_range)
            self.crossPlotVertical.plots["dot"][0].color_mapper = self._cmap(
                value_range)
            self.container.request_redraw()

    def _colorMapRangeLow_changed(self):
        self.colorbar.index_mapper.range.low = self.colorMapRangeLow

    def _colorMapRangeHigh_changed(self):
        self.colorbar.index_mapper.range.high = self.colorMapRangeHigh

    def _horizontalLowerLimit_changed(self):
        self.crossPlotHorizontal.value_range.low = self.horizontalLowerLimit

    def _horizontalUpperLimit_changed(self):
        self.crossPlotHorizontal.value_range.high = self.horizontalUpperLimit

    def _verticalLowerLimit_changed(self):
        self.crossPlotVertical.value_range.low = self.verticalLowerLimit

    def _verticalUpperLimit_changed(self):
        self.crossPlotVertical.value_range.high = self.verticalUpperLimit

    def _autoRange_changed(self):
        if self.autoRange:
            self.colorbar.index_mapper.range.low = self.minz
            self.colorbar.index_mapper.range.high = self.maxz

    def _num_levels_changed(self):
        if self.num_levels > 3:
            self.polyplot.levels = self.num_levels
            self.lineplot.levels = self.num_levels

    def _colorMapRangeLow_default(self):
        logger.debug("setting color map rangle low default")
        return self.model.minZ

    def _colorMapRangeHigh_default(self):
        return self.model.maxZ

    def _horizontalLowerLimit_default(self):
        return self.model.minZ

    def _horizontalUpperLimit_default(self):
        return self.model.maxZ

    def _verticalLowerLimit_default(self):
        return self.model.minZ

    def _verticalUpperLimit_default(self):
        return self.model.maxZ

    def _selectedFit_changed(self, selected):
        logger.debug("selected fit was changed")

    def _fixAspectRatioBool_changed(self):
        if self.fixAspectRatioBool:
            #using zoom range works but then when you reset zoom this function isn't called...
            #            rangeObject = self.polyplot.index_mapper.range
            #            xrangeValue = rangeObject.high[0]-rangeObject.low[0]
            #            yrangeValue = rangeObject.high[1]-rangeObject.low[1]
            #            logger.info("xrange = %s, yrange = %s " % (xrangeValue, yrangeValue))
            #            aspectRatioSquare = (xrangeValue)/(yrangeValue)
            #            self.polyplot.aspect_ratio=aspectRatioSquare
            self.centralContainer.aspect_ratio = float(
                self.model.pixelsX) / float(self.model.pixelsY)
            #self.polyplot.aspect_ratio = self.model.pixelsX/self.model.pixelsY

        else:
            self.centralContainer.aspect_ratio = None
            #self.polyplot.aspect_ratio = None
        self.container.request_redraw()
        self.centralContainer.request_redraw()

    def updatePlotLimits(self):
        """just updates the values in the GUI  """
        if self.autoRangeColor:
            self.colorMapRangeLow = self.model.minZ
            self.colorMapRangeHigh = self.model.maxZ
        if self.horizontalAutoRange:
            self.horizontalLowerLimit = self.model.minZ
            self.horizontalUpperLimit = self.model.maxZ
        if self.verticalAutoRange:
            self.verticalLowerLimit = self.model.minZ
            self.verticalUpperLimit = self.model.maxZ

    def _selectedFile_changed(self):
        self.model.getImageData(self.selectedFile)
        if self.updatePhysicsBool:
            self.physics.updatePhysics()
        for fit in self.fitList:
            fit.fitted = False
            fit.fittingStatus = fit.notFittedForCurrentStatus
            if fit.autoFitBool:  #we should automatically start fitting for this Fit
                fit._fit_routine(
                )  #starts a thread to perform the fit. auto guess and auto draw will be handled automatically
        self.update_view()
        #update log file plot if autorefresh is selected
        if self.logFilePlotObject.autoRefresh:
            try:
                self.logFilePlotObject.refreshPlot()
            except Exception as e:
                logger.error("failed to update log plot -  %s...." % e.message)

    def _cameraModel_changed(self):
        """camera model enum can be used as a helper. It just sets all the relevant
        editable parameters to the correct values. e.g. pixels size, etc.

        cameras:  "Andor Ixon 3838", "Apogee ALTA"
        """
        logger.info("camera model changed")
        if self.cameraModel == "ANDOR0":
            self.model.pixelsX = 512
            self.model.pixelsY = 512
            self.physics.pixelSize = 16.0
            self.physics.magnification = 2.0
            self.searchString = "ANDOR0"
        elif self.cameraModel == "ALTA0":
            self.model.pixelsX = 768
            self.model.pixelsY = 512
            self.physics.pixelSize = 9.0
            self.physics.magnification = 0.5
            self.searchString = "ALTA0"
        elif self.cameraModel == "ALTA1":
            self.model.pixelsX = 768
            self.model.pixelsY = 512
            self.physics.pixelSize = 9.0
            self.physics.magnification = 4.25
            self.searchString = "ALTA1"
        elif self.cameraModel == "ANDOR1":
            self.model.pixelsX = 512
            self.model.pixelsY = 512
            self.physics.pixelSize = 16.0
            self.physics.magnification = 2.0
            self.searchString = "ANDOR1"
        else:
            logger.error("unrecognised camera model")
        self.refreshFitReferences()
        self.model.getImageData(self.selectedFile)

    def refreshFitReferences(self):
        """When aspects of the image change so that the fits need to have
        properties updated, it should be done by this function"""
        for fit in self.fitList:
            fit.endX = self.model.pixelsX
            fit.endY = self.model.pixelsY

    def _pixelsX_changed(self):
        """If pixelsX or pixelsY change, we must send the new arrays to the fit functions """
        logger.info("pixels X Change detected")
        self.refreshFitReferences()
        self.update(self.model)
        self.model.getImageData(self.selectedFile)

    def _pixelsY_changed(self):
        """If pixelsX or pixelsY change, we must send the new arrays to the fit functions """
        logger.info("pixels Y Change detected")
        self.refreshFitReferences()
        self.update(self.model)
        self.model.getImageData(self.selectedFile)

    @traits.on_trait_change('model')
    def update_view(self):
        if self.model is not None:
            self.update(self.model)
Exemple #18
0
class ADCChannel(traits.HasTraits):

    voltage = traits.Float(desc="The voltage of the channel")
    channelName = traits.Str(desc="Human defined name of channel")
    channelNumber = traits.Int(
        desc="channel number on box Can be integer from 0 to 7")
    channelMessage = traits.Str(desc="message to denote status of channel")
    criticalValue = traits.Float(
        desc="the value at which message will change and alarm will sound")
    plotScale = traits.Float(
        desc="scale factor to multiply voltage by on plot")
    logBool = traits.Bool(desc="if true data logged to a file")
    channelMessageHigh = "high"
    channelMessageLow = "low"
    statusHigh = traits.Bool(False)
    connection = None  #It must be passed a connection in initialisation
    checkValueBool = traits.Bool(True)
    highIsGood = traits.Bool(True)
    highSoundFile = None
    lowSoundFile = None

    currentLocalTime = time.localtime()
    currentYear = currentLocalTime.tm_year
    currentMonth = currentLocalTime.tm_mon

    def _voltage_get(self):
        """Uses PyHWI connection to ADC server to return voltage """
        #print "latest=%s" %  self.connection.latestResults
        if self.channelNumber in self.connection.latestResults:
            return self.connection.latestResults[self.channelNumber]
        else:
            return -999

    def check_status(self):
        """check if voltage is higher than critical value and change message """
        if self.voltage > self.criticalValue and not self.statusHigh:  #just went high
            self.statusHigh = True
            self.channelMessage = self.channelMessageHigh
            if ss is not None:
                if self.highSoundFile is not None:  #specific high soundfile
                    ss.playFile(os.path.join("sounds", self.highSoundFile), 1,
                                60.0)
                elif self.highIsGood:
                    winsound.MessageBeep(
                        winsound.MB_ICONASTERISK
                    )  #high is good and we just went high so nice sound
                else:
                    winsound.MessageBeep(
                        winsound.MB_ICONHAND
                    )  #high is bad and we just went high so bad sound

        elif self.voltage < self.criticalValue and self.statusHigh:  #just went low
            self.statusHigh = False
            self.channelMessage = self.channelMessageLow
            if ss is not None:
                if self.lowSoundFile is not None:  #specific high soundfile
                    ss.playFile(os.path.join("sounds", self.lowSoundFile), 1,
                                60.0)
                if not self.highIsGood:
                    winsound.MessageBeep(
                        winsound.MB_ICONASTERISK
                    )  #high is bad and we just went low so good sound
                else:
                    winsound.MessageBeep(
                        winsound.MB_ICONHAND
                    )  #high is good and we just went low so bad sound

    def _voltage_changed(self):
        """whenever voltage is changed automatically update the status """
        if self.checkValueBool:
            self.check_status()

    def _voltage_update(self):
        self.voltage = self._voltage_get()

    def format_function_voltage(value):
        """Format function for voltage """
        if value == -999:
            return "Not in Use"
        else:
            return "%0.3f V" % (value)

    channelGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item('channelNumber',
                          label="Channel Number",
                          style="readonly",
                          editor=traitsui.EnumEditor()),
            traitsui.Item('checkValueBool', label="Check Value")),
        traitsui.Item('channelName', label="Channel Name", style="readonly"),
        traitsui.Item('channelMessage',
                      show_label=False,
                      style="readonly",
                      style_sheet='* { font-size: 16px;  }'),
        traitsui.Item('voltage',
                      show_label=False,
                      style="readonly",
                      format_func=format_function_voltage,
                      style_sheet='* { font-size: 18px;  }'),
        traitsui.Item('criticalValue',
                      label="Critical Voltage",
                      show_label=True,
                      style_sheet='* { font-size: 8px;  }'),
        traitsui.Item('plotScale',
                      label="Plot Scale Factor",
                      show_label=True,
                      style_sheet='* { font-size: 8px;  }'),
        show_border=True)

    def __init__(self, channelNumber, connection, **traitsDict):
        super(ADCChannel, self).__init__(**traitsDict)
        self.connection = connection
        self.channelNumber = channelNumber
        if self.channelName is "":
            self.channelName = "Channel %s" % channelNumber

    traits_view = traitsui.View(channelGroup)
Exemple #19
0
class Oscilloscope(traits.HasTraits):
    """Oscilloscope style plot of the selected channels. Rolling mode/ auto trigger """
    masterContainer = traits.Instance(chaco.Plot)
    arrayPlotData = traits.Instance(chaco.ArrayPlotData)
    visibleChannels = traits.List([0])
    connection = None
    numberOfPoints = traits.Int(
        10000,
        desc=
        "number of points displayed on plot. number of Points*resolution = timespan of plot"
    )
    verticalLimit = traits.Range(low=0.0, high=5.0, value=3.3)
    resolution = traits.Float(
        0.1,
        desc=
        "number of points displayed on plot. number of Points*resolution = timespan of plot"
    )

    settingsGroup = traitsui.Group(
        traitsui.Item("numberOfPoints"),
        traitsui.Item("verticalLimit", label="Vertical Scale"))

    traits_view = traitsui.View(
        traitsui.VGroup(
            settingsGroup,
            traitsui.Group(
                traitsui.Item('masterContainer',
                              editor=ComponentEditor(),
                              show_label=False))))

    def __init__(self, **traitsDict):
        """initialise the plot"""
        super(Oscilloscope, self).__init__(**traitsDict)
        self.colors = ["black", "red", "blue"]
        self.initialiseData()
        self.initialisePlots()
        self._visibleChannels_changed()

    def _visibleChannels_changed(self):
        """make channels visible or not depending on list """
        for i in range(0, 8):
            if i in self.visibleChannels:
                self.masterContainer.plots["channel" +
                                           str(i)][0].visible = True
            else:
                print i
                self.masterContainer.plots["channel" +
                                           str(i)][0].visible = False

    def _numberOfPoints_changed(self):
        """when number of points changes re-initialise the data """
        self.reinitialiseData()

    def _resolution_changed(self):
        """when resolution of points changes re-initialise the data """
        self.reinitialiseData()

    def _verticalLimit_changed(self):
        """"changes y scale of vertical axis """
        self.masterContainer.range2d.y_range.high = self.verticalLimit

    def initialisePlots(self):
        """draw plots """
        self.masterContainer = chaco.Plot(self.arrayPlotData,
                                          padding=100,
                                          bgcolor="white",
                                          use_backbuffer=True,
                                          border_visible=False,
                                          fill_padding=True)
        self.masterContainer.plot(("xs", "channel0"),
                                  type="line",
                                  name="channel0",
                                  color=self.colors[0 % len(self.colors)])

        self.masterContainer.plot(("xs", "channel1"),
                                  type="line",
                                  name="channel1",
                                  color=self.colors[1 % len(self.colors)])

        self.masterContainer.plot(("xs", "channel2"),
                                  type="line",
                                  name="channel2",
                                  color=self.colors[2 % len(self.colors)])
        self.masterContainer.plot(("xs", "channel3"),
                                  type="line",
                                  name="channel3",
                                  color=self.colors[3 % len(self.colors)])

        self.masterContainer.plot(("xs", "channel4"),
                                  type="line",
                                  name="channel4",
                                  color=self.colors[4 % len(self.colors)])
        self.masterContainer.plot(("xs", "channel5"),
                                  type="line",
                                  name="channel5",
                                  color=self.colors[5 % len(self.colors)])

        self.masterContainer.plot(("xs", "channel6"),
                                  type="line",
                                  name="channel6",
                                  color=self.colors[6 % len(self.colors)])
        self.masterContainer.plot(("xs", "channel7"),
                                  type="line",
                                  name="channel7",
                                  color=self.colors[7 % len(self.colors)])
        self.masterContainer.plot(("cursorXS", "cursorVertical"),
                                  type="line",
                                  line_style="dash",
                                  name="cursor",
                                  color="green")

    def getCurrentPositionAsFloat(self):
        return self.currentPosition * self.resolution

    def getCurrentPositionArray(self):
        return scipy.array([self.currentPosition * self.resolution] * 2)

    def initialiseData(self):
        """sets up data arrays and fills arrayPlotData """
        self.currentPosition = 0
        self.xs = scipy.linspace(0.0, self.numberOfPoints * self.resolution,
                                 self.numberOfPoints)
        self.cursorXS = self.getCurrentPositionArray()
        self.cursorVertical = scipy.array([self.verticalLimit, 0.0])
        self.array0 = scipy.zeros(self.numberOfPoints)
        self.array1 = scipy.zeros(self.numberOfPoints)
        self.array2 = scipy.zeros(self.numberOfPoints)
        self.array3 = scipy.zeros(self.numberOfPoints)
        self.array4 = scipy.zeros(self.numberOfPoints)
        self.array5 = scipy.zeros(self.numberOfPoints)
        self.array6 = scipy.zeros(self.numberOfPoints)
        self.array7 = scipy.zeros(self.numberOfPoints)
        self.channels = [
            self.array0, self.array1, self.array2, self.array3, self.array4,
            self.array5, self.array6, self.array7
        ]
        self.arrayPlotData = chaco.ArrayPlotData(
            xs=self.xs,
            channel0=self.array0,
            channel1=self.array1,
            channel2=self.array2,
            channel3=self.array3,
            channel4=self.array4,
            channel5=self.array5,
            channel6=self.array6,
            channel7=self.array7,
            cursorXS=self.cursorXS,
            cursorVertical=self.cursorVertical
        )  #will be the ArrayPlotData We need

    def reinitialiseData(self):
        """sets up data arrays and fills arrayPlotData """
        if self.arrayPlotData is not None:
            self.currentPosition = 0
            self.xs = scipy.linspace(0.0,
                                     self.numberOfPoints * self.resolution,
                                     self.numberOfPoints)
            self.cursorXS = self.getCurrentPositionArray()
            self.cursorVertical = scipy.array([self.verticalLimit, 0.0])
            self.arrayPlotData.set_data("xs", self.xs)
            self.array0 = scipy.zeros(self.numberOfPoints)
            self.array1 = scipy.zeros(self.numberOfPoints)
            self.array2 = scipy.zeros(self.numberOfPoints)
            self.array3 = scipy.zeros(self.numberOfPoints)
            self.array4 = scipy.zeros(self.numberOfPoints)
            self.array5 = scipy.zeros(self.numberOfPoints)
            self.array6 = scipy.zeros(self.numberOfPoints)
            self.array7 = scipy.zeros(self.numberOfPoints)
            self.channels = [
                self.array0, self.array1, self.array2, self.array3,
                self.array4, self.array5, self.array6, self.array7
            ]
            self.updateArrayPlotData()

    def _voltage_get(self, channelNumber):
        """Uses PyHWI connection to ADC server to return voltage """
        #print "latest=%s" %  self.connection.latestResults
        if channelNumber in self.connection.latestResults:
            return self.connection.latestResults[channelNumber]
        else:
            return scipy.NaN

    def updateArrays(self):
        """update all arrays with the latest value """
        for channelNumber in range(0, 8):
            self.channels[channelNumber][
                self.currentPosition] = self._voltage_get(
                    channelNumber)  #update next element in each array
        self.currentPosition += 1
        if self.currentPosition >= self.numberOfPoints:  #reset position to beginning when we hit max number of points (like rolling oscilloscope)
            self.currentPosition = 0
        self.cursorXS = self.getCurrentPositionArray()
        #could also set the next points to NaN's to make a gap!

    def updateArrayPlotData(self):
        """push changes of arrays to the plot """
        self.arrayPlotData.set_data("channel0", self.array0)
        self.arrayPlotData.set_data("channel1", self.array1)
        self.arrayPlotData.set_data("channel2", self.array2)
        self.arrayPlotData.set_data("channel3", self.array3)
        self.arrayPlotData.set_data("channel4", self.array4)
        self.arrayPlotData.set_data("channel5", self.array5)
        self.arrayPlotData.set_data("channel6", self.array6)
        self.arrayPlotData.set_data("channel7", self.array7)
        self.arrayPlotData.set_data("cursorXS", self.cursorXS)
Exemple #20
0
class ADC(traits.HasTraits):

    refreshTime = traits.Float(
        0.1, desc="how often to update the frequencies in seconds")
    logFile = traits.File
    rpiADCLogFolder = traits.String
    averageN = traits.Int(100)
    VMax = traits.Enum(3.3, 5.0)
    channelList = traits.List(
        [1, 3, 5, 6],
        desc="list of channels to show frequencies for and query")
    channelValues = [(0, 'Ch 0'), (1, 'Ch 1'), (2, 'Ch 2'), (3, 'Ch 3'),
                     (4, 'Ch 4'), (5, 'Ch 5'), (6, 'Ch 6'), (7, 'Ch 7')]
    #THIS ONLY WORKS IF PyHWI can be found! it is in the python path manager for lab-Monitoring-0
    connection = rpiADCClient.Connection()
    #if there are problems check the server is running on 192.168.0.111
    icon_trait = pyface.image_resource.ImageResource('icons/wavemeter.png')
    #oscilloscope = None

    currentLocalTime = time.localtime()
    currentYear = currentLocalTime.tm_year
    currentMonth = currentLocalTime.tm_mon
    currentDay = currentLocalTime.tm_mday

    channel0 = ADCChannel(channelNumber=0,
                          connection=connection,
                          channelName="Na Cavity Lock",
                          channelMessageHigh="Na Cavity Locked",
                          channelMessageLow="Na Cavity Out of Lock",
                          criticalValue=1.5,
                          highIsGood=True,
                          highSoundFile="NaLocked.wav",
                          lowSoundFile="NaOutOfLock.wav")

    channel1 = ADCChannel(channelNumber=1,
                          connection=connection,
                          channelName="Li MOT Fluorescence",
                          channelMessageHigh="MOT Loading",
                          channelMessageLow="No MOT",
                          criticalValue=0.1)
    channel2 = ADCChannel(
        channelNumber=2,
        connection=connection,
        channelName="Li MOT Power (stable)")  #changed by Martin
    channel3 = ADCChannel(channelNumber=3,
                          connection=connection,
                          channelName="Li MOT (unstable)")
    channel4 = ADCChannel(channelNumber=4,
                          connection=connection,
                          channelName="Na MOT Power (stable)")
    channel5 = ADCChannel(channelNumber=5,
                          connection=connection,
                          channelName="Na MOT Flourescence")
    channel6 = ADCChannel(channelNumber=6,
                          connection=connection,
                          channelName="ZS light Power")
    channel7 = ADCChannel(channelNumber=7,
                          connection=connection,
                          channelName="disconnected")

    channels = {
        0: channel0,
        1: channel1,
        2: channel2,
        3: channel3,
        4: channel4,
        5: channel5,
        6: channel6,
        7: channel7
    }

    def __init__(self, **traitsDict):
        """Called when object initialises. Starts timer etc. """
        print "Instantiating GUI.."
        super(ADC, self).__init__(**traitsDict)
        self.connection.connect()
        self.oscilloscope = Oscilloscope(connection=self.connection,
                                         resolution=self.refreshTime,
                                         visibleChannels=self.channelList)
        self.start_timer()

    def start_timer(self):
        """Called in init if user selected live update mode, otherwise called from menu action.
        Every self.wizard.updateRateSeconds, self._refresh_data_action will be called"""
        print "Timer Object Started. Will update ADC Information every %s seconds" % self.refreshTime
        self.timer = Timer(
            float(self.refreshTime) * 1000, self._refresh_Visible_channels)

    def _refreshTime_changed(self):
        self.timer.setInterval(float(self.refreshTime) * 1000)
        print "will update ADC every %s seconds" % (float(self.refreshTime))
        self.oscilloscope.resolution = self.refreshTime  #use refresh time to set resolution of oscilloscope

    def _logFile_changed(self):
        self._create_log_file()

    def _channelList_changed(self):
        """push changes to visible channels in oscilloscope """
        self.oscilloscope.visibleChannels = self.channelList

    def _logFile_default(self):
        """default log file has date stamp. log file is changed once a day """
        print "choosing default log file"
        return os.path.join(
            self.rpiADCLogFolder,
            time.strftime("rpiADC-%Y-%m-%d.csv", self.currentLocalTime))

    def getGroupFolder(self):
        """returns the location of the group folder. supports both
         linux and windows. assumes it is mounted to /media/ursa/AQOGroupFolder
         for linux"""
        if platform.system() == "Windows":
            groupFolder = os.path.join("\\\\ursa", "AQOGroupFolder")
        if platform.system() == "Linux":
            groupFolder = os.path.join("/media", "ursa", "AQOGroupFolder")
        return groupFolder

    def _rpiADCLogFolder_default(self):
        return os.path.join(self.getGroupFolder(), "Experiment Humphry",
                            "Experiment Control And Software", "rpiADC",
                            "data")

    def _create_log_file(self):
        if not os.path.exists(os.path.join(self.rpiADCLogFolder,
                                           self.logFile)):
            with open(self.logFile, 'a+') as csvFile:
                csvWriter = csv.writer(csvFile)
                csvWriter.writerow([
                    "epochSeconds", "Channel 0", "Channel 1", "Channel 2",
                    "Channel 3", "Channel 4", "Channel 5", "Channel 6",
                    "Channel 7"
                ])

    def checkDateForFileName(self):
        """gets current date and time and checks if we should change file name
        if we should it creates the new file and the name"""
        #self.currentLocalTime was already changed in log Temperatures
        if self.currentLocalTime.tm_mday != self.currentDay:
            #the day has changed we should start a new log file!
            self.logFile = self._logFile_default()
            self._create_log_file()

    def _log_channels(self):
        self.currentLocalTime = time.localtime()
        self.checkDateForFileName()
        self.currentMonth = self.currentLocalTime.tm_mon
        self.currentDay = self.currentLocalTime.tm_mday

        if not os.path.exists(os.path.join(self.rpiADCLogFolder,
                                           self.logFile)):
            self._create_log_file()

        voltages = [self.channels[i]._voltage_get() for i in range(0, 8)]
        with open(self.logFile, 'a+') as csvFile:
            csvWriter = csv.writer(csvFile)
            csvWriter.writerow([time.time()] + voltages)

    def _refresh_Visible_channels(self):
        self.connection.getResults()  #updates dictionary in connection object
        for channelNumber in self.channelList:
            channel = self.channels[channelNumber]
            channel._voltage_update()
        self.oscilloscope.updateArrays()
        self.oscilloscope.updateArrayPlotData()
        self._log_channels()

    settingsGroup = traitsui.VGroup(
        traitsui.Item("logFile", label="Log File"),
        traitsui.HGroup(
            traitsui.Item('refreshTime', label='refreshTime'),
            traitsui.Item(
                'averageN',
                label='averaging Number',
                tooltip=
                "Number of measurements taken and averaged for value shown"),
            traitsui.Item('VMax',
                          label='Maximum Voltage Setting',
                          tooltip="Whether the box is set to 3.3V or 5V max")),
    )

    selectionGroup = traitsui.Group(
        traitsui.Item('channelList',
                      editor=traitsui.CheckListEditor(values=channelValues,
                                                      cols=4),
                      style='custom',
                      label='Show'))

    groupLeft = traitsui.VGroup(
        traitsui.Item('channel0',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(0 in channelList)"),
        traitsui.Item('channel1',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(1 in channelList)"),
        traitsui.Item('channel2',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(2 in channelList)"),
        traitsui.Item('channel3',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(3 in channelList)"))

    groupRight = traitsui.VGroup(
        traitsui.Item('channel4',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(4 in channelList)"),
        traitsui.Item('channel5',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(5 in channelList)"),
        traitsui.Item('channel6',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(6 in channelList)"),
        traitsui.Item('channel7',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False,
                      visible_when="(7 in channelList)"))

    groupOscilloscope = traitsui.Group(
        traitsui.Item('oscilloscope',
                      editor=traitsui.InstanceEditor(),
                      style='custom',
                      show_label=False))

    groupAll = traitsui.VGroup(
        settingsGroup, selectionGroup,
        traitsui.VSplit(traitsui.HGroup(groupLeft, groupRight),
                        groupOscilloscope))

    traits_view = traitsui.View(groupAll,
                                resizable=True,
                                title="ADC Monitor",
                                handler=ADCHandler(),
                                icon=icon_trait)
Exemple #21
0
class CSVJoiner(tr.HasStrictTraits):
    open_csv_files = tr.Button
    csv_files = tr.List(CSVFile)
    num_of_first_lines_to_show = tr.Range(low=0,
                                          high=10**9,
                                          value=10,
                                          mode='spinner')
    num_of_last_lines_to_show = tr.Range(low=0,
                                         high=10**9,
                                         value=10,
                                         mode='spinner')
    selected = tr.Instance(CSVFile)
    join_csv_files = tr.Button
    accumulate_time = tr.Bool
    files_end_with_empty_line = tr.Bool(True)
    columns_headers = tr.List
    time_column = tr.Enum(values='columns_headers')
    progress = tr.Int

    def _join_csv_files_fired(self):
        output_file_path = self.get_output_file_path()
        with open(output_file_path, 'w') as outfile:
            for csv_file, i in zip(self.csv_files, range(len(self.csv_files))):
                current_line = 1
                num_of_first_lines_to_skip = csv_file.first_lines_to_skip
                num_of_last_lines_to_skip = csv_file.last_lines_to_skip
                last_line_to_write = csv_file.get_lines_number(
                ) - num_of_last_lines_to_skip
                progress_of_a_file = 1.0 / len(self.csv_files)
                initial_progress = i / len(self.csv_files)
                with open(csv_file.path) as opened_csv_file:
                    for line in opened_csv_file:
                        if current_line > num_of_first_lines_to_skip and current_line <= last_line_to_write:
                            outfile.write(line)
                            self.progress = int(
                                (initial_progress + progress_of_a_file *
                                 (current_line / last_line_to_write)) * 100)
                        current_line += 1
                if not self.files_end_with_empty_line:
                    outfile.write('\n')
        self.progress = 100
        dialog = MessageDialog(title='Finished!',
                               message='Files joined successfully, see "' +
                               output_file_path + '"')
        dialog.open()

    def get_output_file_path(self):
        file_path = self.csv_files[0].path
        file_path_without_ext = os.path.splitext(file_path)[0]
        file_ext = os.path.splitext(file_path)[1]
        return file_path_without_ext + '_joined' + file_ext

    def _accumulate_time_changed(self):
        pass

    #         if self.csv_files == []:
    #             return
    #         np.array(pd.read_csv(
    #                     self.file_csv, delimiter=self.delimiter, decimal=self.decimal,
    #                     nrows=1, header=None
    #                 )
    #             )[0]
    #         if self.accumulate_time:
    #             class TimeColumnChooser(tr.HasTraits):
    #                 time_column = tr.Enum(values = 'columns_headers')
    #             chooser = TimeColumnChooser()
    #             chooser.configure_traits(kind='modal')

    def _num_of_first_lines_to_show_changed(self):
        for file in self.csv_files:
            file.num_of_first_lines_to_show = self.num_of_first_lines_to_show

    def _num_of_last_lines_to_show_changed(self):
        for file in self.csv_files:
            file.num_of_last_lines_to_show = self.num_of_last_lines_to_show

    def _open_csv_files_fired(self):
        extensions = ['*.csv', '*.txt']  # handle only one extension...
        wildcard = ';'.join(extensions)
        dialog = pf.FileDialog(title='Select csv files',
                               action='open files',
                               wildcard=wildcard,
                               default_path=os.path.expanduser("~"))
        result = dialog.open()

        csv_files_paths = []
        # Test if the user opened a file to avoid throwing an exception
        # if he doesn't
        if result == pf.OK:
            csv_files_paths = dialog.paths
        else:
            return

        self.csv_files = []
        for file_path in csv_files_paths:
            csv_file = CSVFile(
                path=file_path,
                num_of_first_lines_to_show=self.num_of_first_lines_to_show,
                num_of_last_lines_to_show=self.num_of_last_lines_to_show,
            )
            self.csv_files.append(csv_file)

    # =========================================================================
    # Configuration of the view
    # =========================================================================
    traits_view = ui.View(
        ui.VGroup(
            ui.UItem('open_csv_files', width=150),
            ui.HGroup(ui.Item('num_of_first_lines_to_show'), ui.spring),
            ui.HGroup(ui.Item('num_of_last_lines_to_show'), ui.spring),
            ui.HGroup(
                ui.Item('files_end_with_empty_line'),
                # ui.Item('accumulate_time', enabled_when='False'),
                ui.spring),
            ui.VGroup(
                ui.Item('csv_files',
                        show_label=False,
                        style='custom',
                        editor=ui.ListEditor(use_notebook=True,
                                             deletable=False,
                                             selected='selected',
                                             export='DockWindowShell',
                                             page_name='.name'))),
            ui.HGroup(
                ui.UItem('join_csv_files', width=150),
                ui.UItem('progress', editor=ProgressEditor(min=0, max=100))),
            show_border=True),
        title='CSV files joiner',
        resizable=True,
        width=0.6,
        height=0.7)
Exemple #22
0
class Librarian(traits.HasTraits):
    """Librarian provides a way of writing useful information into the 
    log folder for eagle logs. It is designed to make the information inside
    an eagle log easier to come back to. It mainly writes default strings into
    the comments file in the log folder"""

    logType = traits.Enum("important", "debug", "calibration")
    writeToOneNoteButton = traits.Button("save")
    refreshInformation = traits.Button("refresh")
    saveImage = traits.Button("save plot")
    axisList = AxisSelector()
    purposeBlock = EntryBlock(fieldName="What is the purpose of this log?")
    resultsBlock = EntryBlock(
        fieldName=
        "Explain what the data shows (important parameters that change, does it make sense etc.)?"
    )
    commentsBlock = EntryBlock(fieldName="Anything Else?")
    saveButton = traits.Button("Save")
    #    notebooks = traits.Enum(values = "notebookNames") # we could let user select from a range of notebooks
    #    notebookNames = traits.List
    notebookName = traits.String("Humphry's Notebook")
    sectionName = traits.String("Eagle Logs")
    logName = traits.String("")
    xAxis = traits.String("")
    yAxis = traits.String("")

    traits_view = traitsui.View(traitsui.VGroup(
        traitsui.Item("logName", show_label=False, style="readonly"),
        traitsui.Item("axisList",
                      show_label=False,
                      editor=traitsui.InstanceEditor(),
                      style='custom'),
        traitsui.Item("purposeBlock",
                      show_label=False,
                      editor=traitsui.InstanceEditor(),
                      style='custom'),
        traitsui.Item("resultsBlock",
                      show_label=False,
                      editor=traitsui.InstanceEditor(),
                      style='custom'),
        traitsui.Item("commentsBlock",
                      show_label=False,
                      editor=traitsui.InstanceEditor(),
                      style='custom'),
        traitsui.HGroup(
            traitsui.Item("writeToOneNoteButton", show_label=False),
            traitsui.Item("refreshInformation", show_label=False)),
    ),
                                resizable=True,
                                kind="live",
                                title="Eagle OneNote")

    def __init__(self, **traitsDict):
        """Librarian object requires the log folder it is referring to. If a .csv
        file is given as logFolder argument it will use parent folder as the 
        logFolder"""
        super(Librarian, self).__init__(**traitsDict)
        if os.path.isfile(self.logFolder):
            self.logFolder = os.path.split(self.logFolder)[0]
        else:
            logger.debug("found these in %s: %s" %
                         (self.logFolder, os.listdir(self.logFolder)))

        self.logName = os.path.split(self.logFolder)[1]
        self.logFile = os.path.join(self.logFolder,
                                    os.path.split(self.logFolder)[1] + ".csv")
        self.axisList.logFile = self.logFile  #needs a copy so it can calculate valid values
        self.axisList.masterList = self.axisList._masterList_default()
        self.axisList.masterListWithNone = self.axisList._masterListWithNone_default(
        )
        if self.xAxis != "":
            self.axisList.xAxis = self.xAxis
        if self.yAxis != "":
            self.axisList.yAxis = self.yAxis

        self.eagleOneNote = oneNotePython.eagleLogsOneNote.EagleLogOneNote(
            notebookName=self.notebookName, sectionName=self.sectionName)
        logPage = self.eagleOneNote.setPage(self.logName)
        #
        #        except Exception as e:
        #            logger.error("failed to created an EagleOneNote Instance. This could happen for many reasons. E.g. OneNote not installed or most likely, the registry is not correct. See known bug and fix in source code of onenotepython module:%s" % e.message)
        if logPage is not None:  #page exists
            self.purposeBlock.textBlock = self.eagleOneNote.getOutlineText(
                "purpose")
            self.resultsBlock.textBlock = self.eagleOneNote.getOutlineText(
                "results")
            self.commentsBlock.textBlock = self.eagleOneNote.getOutlineText(
                "comments")
            xAxis, yAxis, series = self.eagleOneNote.getParametersOutlineValues(
            )
            try:
                self.axisList.xAxis, self.axisList.yAxis, self.axisList.series = xAxis, yAxis, series
            except Exception as e:
                logger.error(
                    "error when trying to read analysis parameters: %s" %
                    e.message)
            self.pageExists = True
        else:
            self.pageExists = False
            self.purposeBlock.textBlock = ""
            self.resultsBlock.textBlock = ""
            self.commentsBlock.textBlock = ""
            #could also reset axis list but it isn't really necessary

    def _writeToOneNoteButton_fired(self):
        """writes content of librarian to one note page """
        if not self.pageExists:
            self.eagleOneNote.createNewEagleLogPage(self.logName,
                                                    refresh=True,
                                                    setCurrent=True)
            self.pageExists = True
        self.eagleOneNote.setOutline("purpose",
                                     self.purposeBlock.textBlock,
                                     rewrite=False)
        self.eagleOneNote.setOutline("results",
                                     self.resultsBlock.textBlock,
                                     rewrite=False)
        self.eagleOneNote.setOutline("comments",
                                     self.commentsBlock.textBlock,
                                     rewrite=False)
        self.eagleOneNote.setDataOutline(self.logName, rewrite=False)
        self.eagleOneNote.setParametersOutline(self.axisList.xAxis,
                                               self.axisList.yAxis,
                                               self.axisList.series,
                                               rewrite=False)
        self.eagleOneNote.currentPage.rewritePage()
        #now to get resizing done well we want to completely repull the XML and data
        #brute force method:
        self.eagleOneNote = oneNotePython.eagleLogsOneNote.EagleLogOneNote(
            notebookName=self.notebookName, sectionName=self.sectionName)
        logPage = self.eagleOneNote.setPage(
            self.logName)  #this sets current page of eagleOneNote
        self.eagleOneNote.organiseOutlineSizes()
Exemple #23
0
class InputParameter(trapi.HasTraits):
    """Class the is used to input all of the user parameters through a guy"""
    tickers_input = trapi.Str
    time_windows_input = trapi.Array(trapi.Int, (1, nbr_max_time_windows))
    data_source = trapi.Enum("Yahoo", "Bloomberg", "Telemaco")
    date_start = trapi.Date
    date_end = trapi.Date
    get_data_button = trapi.Button
    plot_chart_button = trapi.Button
    corr_data = pd.DataFrame
    correlpairs = trapi.List
    selected_correl_pair_indices = trapi.List
    corr_pairs_combinations = trapi.List
    v = trui.View(trui.HGroup(trui.Item(name='tickers_input', style='custom'),
                              trui.VGroup(
                                  trui.Item(name='date_start'),
                                  trui.Item(name='date_end'),
                                  trui.Item(name='time_windows_input'),
                                  trui.Item(name='data_source'),
                                  trui.Item(name='get_data_button',
                                            label='Process Data',
                                            show_label=False),
                                  trui.Item('correlpairs',
                                            show_label=False,
                                            editor=correl_pair_editor),
                                  trui.Item(name='plot_chart_button',
                                            label='Plot Selected Data',
                                            show_label=False),
                              ),
                              show_border=True,
                              label='Input Data'),
                  resizable=True,
                  title='Correlation Tool',
                  height=screen_height,
                  width=screen_width,
                  icon='corr.png',
                  image='corr.png')

    def _plot_chart_button_fired(self):
        """Method to plot the selected data"""
        # Read TableEditor to see what the user has chosen to
        data_to_plot = []
        for i in range(0, len(self.correlpairs)):
            if i == len(self.correlpairs) - 1:
                pair_name = ['BASKET CORREL', 'BASKET CORREL']
            else:
                pair_name = self.correlpairs[i].correl_pair.split('-')

            if self.correlpairs[i].time_window_1:
                data_to_plot.append(
                    (pair_name[0].strip(), pair_name[1].strip(),
                     self.time_windows_input[0][0]))
            if self.correlpairs[i].time_window_2:
                data_to_plot.append(
                    (pair_name[0].strip(), pair_name[1].strip(),
                     self.time_windows_input[0][1]))
            if self.correlpairs[i].time_window_3:
                data_to_plot.append(
                    (pair_name[0].strip(), pair_name[1].strip(),
                     self.time_windows_input[0][2]))
            if self.correlpairs[i].time_window_4:
                data_to_plot.append(
                    (pair_name[0].strip(), pair_name[1].strip(),
                     self.time_windows_input[0][3]))
            if self.correlpairs[i].time_window_5:
                data_to_plot.append(
                    (pair_name[0].strip(), pair_name[1].strip(),
                     self.time_windows_input[0][4]))

        # Plot
        pl.plot_data(self.corr_data[0], self.corr_data[1], data_to_plot)

    def check_data_retrieval_error(self, raw_data, tickers_list):
        """Check whether there was an error retrieving data"""
        # Check whether data was retrieved successfully:
        if self.data_source == 'Yahoo':
            if len(tickers_list) > 1:
                empty_col = []
                for column_name in raw_data.columns:
                    if raw_data[column_name].isna().all():
                        empty_col.append(column_name)
                        raw_data[column_name].drop
                if empty_col:
                    message(
                        'There was a problem loading data for the following underlyings:\n'
                        + '\n'.join(empty_col))
                    return [x for x in tickers_list if x not in empty_col]
                else:
                    return tickers_list
            else:
                return tickers_list

        elif self.data_source == 'Bloomberg':
            if len(tickers_list) > 1:
                if len(raw_data.columns) < len(tickers_list):
                    und_errors = np.setdiff1d(tickers_list, raw_data.columns)
                    message(
                        'There was a problem loading data for the following underlyings:\n'
                        + '\n'.join(und_errors))
                    return [x for x in tickers_list if x not in und_errors]
                else:
                    return tickers_list
            else:
                return tickers_list

    def _get_data_button_fired(self):
        """Method to download the relevant data and then compute the relevant correlations"""
        tickers_list = self.tickers_input.strip().split('\n')

        time_windows = self.time_windows_input[0, :].astype(int)

        # Get raw data
        raw_data = dr.get_relevant_data(tickers_list, self.date_start,
                                        self.date_end, self.data_source)

        # Check whether there was an error retrieving data
        tickers_list = self.check_data_retrieval_error(raw_data, tickers_list)
        if len(tickers_list) <= 1:
            message(
                'You need at least two underlyings to compute correlations')
            return

        # Process raw data
        log_returns = cc.process_raw_data(raw_data)

        # Filter log returns
        log_returns = cc.filter_log_returns(log_returns)

        # Compute pairwise correlations
        self.corr_data = cc.get_correlations(log_returns, time_windows)

        # Generate TableEditor
        for i in range(0, len(time_windows)):
            correl_pair_editor.columns[i + 1].label = str(time_windows[i])
        self.corr_pairs_combinations = [
            pair[0] + ' - ' + pair[1]
            for pair in it.combinations(tickers_list, 2)
        ]
        self.corr_pairs_combinations.append('BASKET CORREL')
        self.correlpairs = [
            generate_correl_pair(pair) for pair in self.corr_pairs_combinations
        ]
Exemple #24
0
class Fit(traits.HasTraits):

    name = traits.Str(desc="name of fit")
    function = traits.Str(desc="function we are fitting with all parameters")
    variablesList = traits.List(Parameter)
    calculatedParametersList = traits.List(CalculatedParameter)
    xs = None  # will be a scipy array
    ys = None  # will be a scipy array
    zs = None  # will be a scipy array
    performFitButton = traits.Button("Perform Fit")
    getInitialParametersButton = traits.Button("Guess Initial Values")
    usePreviousFitValuesButton = traits.Button("Use Previous Fit")
    drawRequestButton = traits.Button("Draw Fit")
    setSizeButton = traits.Button("Set Initial Size")
    chooseVariablesButtons = traits.Button("choose logged variables")
    logAllVariables = traits.Bool(True)
    logLibrarianButton = traits.Button("librarian")
    logLastFitButton = traits.Button("log current fit")
    removeLastFitButton = traits.Button("remove last fit")
    autoFitBool = traits.Bool(
        False,
        desc=
        "Automatically perform this Fit with current settings whenever a new image is loaded"
    )
    autoDrawBool = traits.Bool(
        True,
        desc=
        "Once a fit is complete update the drawing of the fit or draw the fit for the first time"
    )
    autoGuessBool = traits.Bool(False,
                                desc="Perform a new guess before fitting")
    autoSizeBool = traits.Bool(
        False,
        desc=
        "If TOF variable is read from latest XML and is equal to 0.11ms (or time set in Physics) then it will automatically update the physics sizex and sizey with the Sigma x and sigma y from the gaussian fit"
    )
    autoPreviousBool = traits.Bool(
        False,
        desc=
        "Whenever a fit is completed replace the guess values with the calculated values (useful for increasing speed of the next fit)"
    )
    logBool = traits.Bool(
        False, desc="Log the calculated and fitted values with a timestamp")
    logName = traits.String(
        desc="name of the scan - will be used in the folder name")
    logToNas = traits.Bool(
        True, desc="If true, log goes to Humphry-NAS instead of ursa")
    ##    logDirectory = os.path.join("\\\\ursa","AQOGroupFolder","Experiment Humphry","Data","eagleLogs")
    logDirectory = os.path.join("G:", os.sep, "Experiment Humphry", "Data",
                                "eagleLogs")
    logDirectoryNas = os.path.join("\\\\192.168.16.71", "Humphry", "Data",
                                   "eagleLogs")
    latestSequence = os.path.join("\\\\ursa", "AQOGroupFolder",
                                  "Experiment Humphry",
                                  "Experiment Control And Software",
                                  "currentSequence", "latestSequence.xml")
    conditionalFitBool = traits.Bool(
        False,
        desc=
        "If true, fit is only executed, if current sequence contains matching variable 'eagleID'"
    )
    conditionalFitID = traits.Int(0)

    logFile = traits.File(desc="file path of logFile")

    logAnalyserBool = traits.Bool(
        False, desc="only use log analyser script when True")
    logAnalysers = [
    ]  #list containing full paths to each logAnalyser file to run
    logAnalyserDisplayString = traits.String(
        desc=
        "comma separated read only string that is a list of all logAnalyser python scripts to run. Use button to choose files"
    )
    logAnalyserSelectButton = traits.Button("sel. analyser",
                                            image='@icons:function_node',
                                            style="toolbar")
    xmlLogVariables = []
    imageInspectorReference = None  #will be a reference to the image inspector
    fitting = traits.Bool(False)  #true when performing fit
    fitted = traits.Bool(
        False)  #true when current data displayed has been fitted
    fitSubSpace = traits.Bool(True)
    drawSubSpace = traits.Bool(True)
    startX = traits.Int(230)
    startY = traits.Int(230)
    endX = traits.Int(550)
    endY = traits.Int(430)
    fittingStatus = traits.Str()
    fitThread = None
    fitTimeLimit = traits.Float(
        10.0,
        desc=
        "Time limit in seconds for fitting function. Only has an effect when fitTimeLimitBool is True"
    )
    fitTimeLimitBool = traits.Bool(
        True,
        desc=
        "If True then fitting functions will be limited to time limit defined by fitTimeLimit "
    )
    physics = traits.Instance(
        physicsProperties.physicsProperties.PhysicsProperties)
    #status strings
    notFittedForCurrentStatus = "Not Fitted for Current Image"
    fittedForCurrentImageStatus = "Fit Complete for Current Image"
    currentlyFittingStatus = "Currently Fitting..."
    failedFitStatus = "Failed to finish fit. See logger"
    timeExceededStatus = "Fit exceeded user time limit"

    lmfitModel = traits.Instance(
        lmfit.Model
    )  #reference to the lmfit model  must be initialised in subclass
    mostRecentModelResult = None  # updated to the most recent ModelResult object from lmfit when a fit thread is performed

    fitSubSpaceGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("fitSubSpace", label="Fit Sub Space",
                          resizable=True), traitsui.Item("drawSubSpace")),
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("startX", resizable=True),
            traitsui.Item("startY", resizable=True)),
                        traitsui.HGroup(traitsui.Item("endX", resizable=True),
                                        traitsui.Item("endY", resizable=True)),
                        visible_when="fitSubSpace"),
        label="Fit Sub Space",
        show_border=True)

    generalGroup = traitsui.VGroup(traitsui.Item("name",
                                                 label="Fit Name",
                                                 style="readonly",
                                                 resizable=True),
                                   traitsui.Item("function",
                                                 label="Fit Function",
                                                 style="readonly",
                                                 resizable=True),
                                   fitSubSpaceGroup,
                                   label="Fit",
                                   show_border=True)

    variablesGroup = traitsui.VGroup(traitsui.Item(
        "variablesList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True),
                                     show_border=True,
                                     label="parameters")

    derivedGroup = traitsui.VGroup(traitsui.Item(
        "calculatedParametersList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True),
                                   show_border=True,
                                   label="derived values")

    buttons = traitsui.HGroup(
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("autoFitBool", label="Auto fit?", resizable=True),
            traitsui.Item("performFitButton", show_label=False,
                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoGuessBool",
                                          label="Auto guess?",
                                          resizable=True),
                            traitsui.Item("getInitialParametersButton",
                                          show_label=False,
                                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoPreviousBool",
                                          label="Auto previous?",
                                          resizable=True),
                            traitsui.Item("usePreviousFitValuesButton",
                                          show_label=False,
                                          resizable=True)),
                        show_border=True),
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("autoDrawBool", label="Auto draw?", resizable=True),
            traitsui.Item("drawRequestButton",
                          show_label=False,
                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoSizeBool",
                                          label="Auto size?",
                                          resizable=True),
                            traitsui.Item("setSizeButton",
                                          show_label=False,
                                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("conditionalFitBool",
                                          label="Conditional Fit?",
                                          resizable=True),
                            traitsui.Item("conditionalFitID",
                                          label="Fit ID",
                                          resizable=True)),
                        show_border=True))

    logGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("logBool", resizable=True),
            traitsui.Item("logAllVariables", resizable=True),
            traitsui.Item("chooseVariablesButtons",
                          show_label=False,
                          resizable=True,
                          enabled_when="not logAllVariables")),
        traitsui.HGroup(traitsui.Item("logName", resizable=True)),
        traitsui.HGroup(traitsui.Item("logToNas", resizable=True)),  #changed
        traitsui.HGroup(
            traitsui.Item("removeLastFitButton",
                          show_label=False,
                          resizable=True),
            traitsui.Item("logLastFitButton", show_label=False,
                          resizable=True)),
        traitsui.HGroup(
            traitsui.Item("logAnalyserBool", label="analyser?",
                          resizable=True),
            traitsui.Item("logAnalyserDisplayString",
                          show_label=False,
                          style="readonly",
                          resizable=True),
            traitsui.Item("logAnalyserSelectButton",
                          show_label=False,
                          resizable=True)),
        label="Logging",
        show_border=True)

    actionsGroup = traitsui.VGroup(traitsui.Item("fittingStatus",
                                                 style="readonly",
                                                 resizable=True),
                                   logGroup,
                                   buttons,
                                   label="Fit Actions",
                                   show_border=True)
    traits_view = traitsui.View(traitsui.VGroup(generalGroup, variablesGroup,
                                                derivedGroup, actionsGroup),
                                kind="subpanel")

    def __init__(self, **traitsDict):
        super(Fit, self).__init__(**traitsDict)
        # self.startX = 0
        # self.startY = 0
        self.lmfitModel = lmfit.Model(self.fitFunc)

        # load config
        with open(configFile, 'r') as f:
            settings = json.load(f)
            if 'logAnalysers' in settings:
                self.logAnalysers = settings['logAnalysers']
                self.logAnalyserDisplayString = str(
                    [os.path.split(path)[1] for path in self.logAnalysers])
            if 'logAnalyserBool' in settings:
                self.logAnalyserBool = settings['logAnalyserBool']

    def _set_xs(self, xs):
        self.xs = xs

    def _set_ys(self, ys):
        self.ys = ys

    def _set_zs(self, zs):
        self.zs = zs

    def _fittingStatus_default(self):
        return self.notFittedForCurrentStatus

    def _getInitialValues(self):
        """returns ordered list of initial values from variables List """
        return [_.initialValue for _ in self.variablesList]

    def _getParameters(self):
        """creates an lmfit parameters object based on the user input in variablesList """
        return lmfit.Parameters(
            {_.name: _.parameter
             for _ in self.variablesList})

    def _getCalculatedValues(self):
        """returns ordered list of fitted values from variables List """
        return [_.calculatedValue for _ in self.variablesList]

    def _intelligentInitialValues(self):
        """If possible we can auto set the initial parameters to intelligent guesses user can always overwrite them """
        self._setInitialValues(self._getIntelligentInitialValues())

    def _get_subSpaceArrays(self):
        """returns the arrays of the selected sub space. If subspace is not
        activated then returns the full arrays"""
        if self.fitSubSpace:
            xs = self.xs[self.startX:self.endX]
            ys = self.ys[self.startY:self.endY]
            logger.info("xs array sliced length %s " % (xs.shape))
            logger.info("ys array sliced length %s  " % (ys.shape))
            zs = self.zs[self.startY:self.endY, self.startX:self.endX]
            logger.info("zs sub space array %s,%s " % (zs.shape))

            return xs, ys, zs
        else:
            return self.xs, self.ys, self.zs

    def _getIntelligentInitialValues(self):
        """If possible we can auto set the initial parameters to intelligent guesses user can always overwrite them """
        logger.warning("Dummy function should not be called directly")
        return
        #in python this should be a pass statement. I.e. user has to overwrite this

    def fitFunc(self, data, *p):
        """Function that we are trying to fit to. """
        logger.error("Dummy function should not be called directly")
        return
        #in python this should be a pass statement. I.e. user has to overwrite this

    def _setCalculatedValues(self, modelFitResult):
        """updates calculated values with calculated argument """
        parametersResult = modelFitResult.params
        for variable in self.variablesList:
            variable.calculatedValue = parametersResult[variable.name].value

    def _setCalculatedValuesErrors(self, modelFitResult):
        """given the covariance matrix returned by scipy optimize fit
        convert this into stdeviation errors for parameters list and updated
        the stdevError attribute of variables"""
        parametersResult = modelFitResult.params
        for variable in self.variablesList:
            variable.stdevError = parametersResult[variable.name].stderr

    def _setInitialValues(self, guesses):
        """updates calculated values with calculated argument """
        c = 0
        for variable in self.variablesList:
            variable.initialValue = guesses[c]
            c += 1

    def deriveCalculatedParameters(self):
        """Wrapper for subclass definition of deriving calculated parameters
        can put more general calls in here"""
        if self.fitted:
            self._deriveCalculatedParameters()

    def _deriveCalculatedParameters(self):
        """Should be implemented by subclass. should update all variables in calculate parameters list"""
        logger.error("Should only be called by subclass")
        return

    def _fit_routine(self):
        """This function performs the fit in an appropriate thread and 
        updates necessary values when the fit has been performed"""
        self.fitting = True
        if self.fitThread and self.fitThread.isAlive():
            logger.warning(
                "Fitting is already running. You should wait till this fit has timed out before a new thread is started...."
            )
            #logger.warning("I will start a new fitting thread but your previous thread may finish at some undetermined time. you probably had bad starting conditions :( !")
            return
        self.fitThread = FitThread()  #new fitting thread
        self.fitThread.fitReference = self
        self.fitThread.isCurrentFitThread = True  # user can create multiple fit threads on a particular fit but only the latest one will have an effect in the GUI
        self.fitThread.start()
        self.fittingStatus = self.currentlyFittingStatus

    def _perform_fit(self):
        """Perform the fit using scipy optimise curve fit.
        We must supply x and y as one argument and zs as anothger. in the form
        xs: 0 1 2 0 1 2 0 
        ys: 0 0 0 1 1 1 2
        zs: 1 5 6 1 9 8 2
        Hence the use of repeat and tile in  positions and unravel for zs
        initially xs,ys is a linspace array and zs is a 2d image array
        """
        if self.xs is None or self.ys is None or self.zs is None:
            logger.warning(
                "attempted to fit data but had no data inside the Fit object. set xs,ys,zs first"
            )
            return ([], [])
        params = self._getParameters()
        if self.fitSubSpace:  #fit only the sub space
            #create xs, ys and zs which are appropriate slices of the arrays
            xs, ys, zs = self._get_subSpaceArrays()
        else:  #fit the whole array of data (slower)
            xs, ys, zs = self.xs, self.ys, self.zs
        positions = scipy.array([
            scipy.tile(xs, len(ys)),
            scipy.repeat(ys, len(xs))
        ])  #for creating data necessary for gauss2D function
        if self.fitTimeLimitBool:
            modelFitResult = self.lmfitModel.fit(scipy.ravel(zs),
                                                 positions=positions,
                                                 params=params,
                                                 iter_cb=self.getFitCallback(
                                                     time.time()))
        else:  #no iter callback
            modelFitResult = self.lmfitModel.fit(scipy.ravel(zs),
                                                 positions=positions,
                                                 params=params)
        return modelFitResult

    def getFitCallback(self, startTime):
        """returns the callback function that is called at every iteration of fit to check if it 
        has been running too long"""
        def fitCallback(params, iter, resid, *args, **kws):
            """check the time and compare to start time """
            if time.time() - startTime > self.fitTimeLimit:
                raise FitException("Fit time exceeded user limit")

        return fitCallback

    def _performFitButton_fired(self):
        self._fit_routine()

    def _getInitialParametersButton_fired(self):
        self._intelligentInitialValues()

    def _drawRequestButton_fired(self):
        """tells the imageInspector to try and draw this fit as an overlay contour plot"""
        self.imageInspectorReference.addFitPlot(self)

    def _setSizeButton_fired(self):
        """use the sigmaX and sigmaY from the current fit to overwrite the 
        inTrapSizeX and inTrapSizeY parameters in the Physics Instance"""
        self.physics.inTrapSizeX = abs(self.sigmax.calculatedValue)
        self.physics.inTrapSizeY = abs(self.sigmay.calculatedValue)

    def _getFitFuncData(self):
        """if data has been fitted, this returns the zs data for the ideal
        fitted function using the calculated paramters"""
        positions = [
            scipy.tile(self.xs, len(self.ys)),
            scipy.repeat(self.ys, len(self.xs))
        ]  #for creating data necessary for gauss2D function
        zsravelled = self.fitFunc(positions, *self._getCalculatedValues())
        return zsravelled.reshape(self.zs.shape)

    def _logAnalyserSelectButton_fired(self):
        """open a fast file editor for selecting many files """
        fileDialog = FileDialog(action="open files")
        fileDialog.open()
        if fileDialog.return_code == pyface.constant.OK:
            self.logAnalysers = fileDialog.paths
            logger.info("selected log analysers: %s " % self.logAnalysers)
        self.logAnalyserDisplayString = str(
            [os.path.split(path)[1] for path in self.logAnalysers])

    def runSingleAnalyser(self, module):
        """runs the logAnalyser module calling the run function and returns the 
        columnNames and values as a list"""
        exec("import logAnalysers.%s as currentAnalyser" % module)
        reload(
            currentAnalyser
        )  #in case it has changed..#could make this only when user requests
        #now the array also contains the raw image as this may be different to zs if you are using a processor
        if hasattr(self.imageInspectorReference, "rawImage"):
            rawImage = self.imageInspectorReference.rawImage
        else:
            rawImage = None
        return currentAnalyser.run([self.xs, self.ys, self.zs, rawImage],
                                   self.physics.variables, self.variablesList,
                                   self.calculatedParametersList)

    def runAnalyser(self):
        """ if logAnalyserBool is true we perform runAnalyser at the end of _log_fit
        runAnalyser checks that logAnalyser exists and is a python script with a valid run()function
        it then performs the run method and passes to the run function:
        -the image data as a numpy array
        -the xml variables dictionary
        -the fitted paramaters
        -the derived values"""
        for logAnalyser in self.logAnalysers:
            if not os.path.isfile(logAnalyser):
                logger.error(
                    "attempted to runAnalyser but could not find the logAnalyser File: %s"
                    % logAnalyser)
                return
        #these will contain the final column names and values
        finalColumns = []
        finalValues = []
        #iterate over each selected logAnalyser get the column names and values and add them to the master lists
        for logAnalyser in self.logAnalysers:
            directory, module = os.path.split(logAnalyser)
            module, ext = os.path.splitext(module)
            if ext != ".py":
                logger.error("file was not a python module. %s" % logAnalyser)
            else:
                columns, values = self.runSingleAnalyser(module)
                finalColumns.extend(columns)
                finalValues.extend(values)
        return finalColumns, finalValues

    def mostRecentModelFitReport(self):
        """returns the lmfit fit report of the most recent 
        lmfit model results object"""
        if self.mostRecentModelResult is not None:
            return lmfit.fit_report(self.mostRecentModelResult) + "\n\n"
        else:
            return "No fit performed"

    def getCalculatedParameters(self):
        """useful for print returns tuple list of calculated parameter name and value """
        return [(_.name, _.value) for _ in self.calculatedParametersList]

    def _log_fit(self):

        if self.logName == "":
            logger.warning("no log file defined. Will not log")
            return
        #generate folders if they don't exist
        if self.logToNas is not True:
            logFolder = os.path.join(self.logDirectory, self.logName)
        else:
            logFolder = os.path.join(self.logDirectoryNas, self.logName)
        if not os.path.isdir(logFolder):
            logger.info("creating a new log folder %s" % logFolder)
            os.mkdir(logFolder)

        imagesFolder = os.path.join(logFolder, "images")
        if not os.path.isdir(imagesFolder):
            logger.info("creating a new images Folder %s" % imagesFolder)
            os.mkdir(imagesFolder)

        commentsFile = os.path.join(logFolder, "comments.txt")
        if not os.path.exists(commentsFile):
            logger.info("creating a comments file %s" % commentsFile)
            open(commentsFile,
                 "a+").close()  #create a comments file in every folder!

        firstSequenceCopy = os.path.join(logFolder,
                                         "copyOfInitialSequence.ctr")
        if not os.path.exists(firstSequenceCopy):
            logger.info("creating a copy of the first sequence %s -> %s" %
                        (self.latestSequence, firstSequenceCopy))
            shutil.copy(self.latestSequence, firstSequenceCopy)

        if self.imageInspectorReference.model.imageMode == "process raw image":  #if we are using a processor, save the details of the processor used to the log folder
            processorParamtersFile = os.path.join(logFolder,
                                                  "processorOptions.txt")
            processorPythonScript = os.path.join(logFolder,
                                                 "usedProcessor.py")  #TODO!
            if not os.path.exists(processorParamtersFile):
                with open(processorParamtersFile, "a+") as processorParamsFile:
                    string = str(self.imageInspectorReference.model.
                                 chosenProcessor) + "\n"
                    string += str(self.imageInspectorReference.model.processor.
                                  optionsDict)
                    processorParamsFile.write(string)

        logger.debug("finished all checks on log folder")
        #copy current image
        try:
            shutil.copy(self.imageInspectorReference.selectedFile,
                        imagesFolder)
            if self.imageInspectorReference.selectedFile.endswith("_X2.tif"):
                shutil.copy(
                    self.imageInspectorReference.selectedFile.replace(
                        "_X2.tif", "_X1.tif"), imagesFolder)
        except IOError as e:
            logger.error("Could not copy image. Got IOError: %s " % e.message)
        except Exception as e:
            logger.error("Could not copy image. Got %s: %s " %
                         (type(e), e.message))
            raise e
        logger.info("copying current image")
        self.logFile = os.path.join(logFolder, self.logName + ".csv")

        #analyser logic
        if self.logAnalyserBool:  #run the analyser script as requested
            logger.info(
                "log analyser bool enabled... will attempt to run analyser script"
            )
            analyserResult = self.runAnalyser()
            logger.info("analyser result = %s " % list(analyserResult))
            if analyserResult is None:
                analyserColumnNames = []
                analyserValues = []
                #analyser failed. continue as if nothing happened
            else:
                analyserColumnNames, analyserValues = analyserResult
        else:  #no analyser enabled
            analyserColumnNames = []
            analyserValues = []

        if not os.path.exists(self.logFile):
            variables = [_.name for _ in self.variablesList]
            calculated = [_.name for _ in self.calculatedParametersList]
            times = ["datetime", "epoch seconds"]
            info = ["img file name"]
            xmlVariables = self.getXmlVariables()
            columnNames = times + info + variables + calculated + xmlVariables + analyserColumnNames
            with open(
                    self.logFile, 'ab+'
            ) as logFile:  # note use of binary file so that windows doesn't write too many /r
                writer = csv.writer(logFile)
                writer.writerow(columnNames)
        #column names already exist so...
        logger.debug("copying current image")
        variables = [_.calculatedValue for _ in self.variablesList]
        calculated = [_.value for _ in self.calculatedParametersList]
        now = time.time()  #epoch seconds
        timeTuple = time.localtime(now)
        date = time.strftime("%Y-%m-%dT%H:%M:%S", timeTuple)
        times = [date, now]
        info = [self.imageInspectorReference.selectedFile]
        xmlVariables = [
            self.physics.variables[varName]
            for varName in self.getXmlVariables()
        ]
        data = times + info + variables + calculated + xmlVariables + analyserValues

        with open(self.logFile, 'ab+') as logFile:
            writer = csv.writer(logFile)
            writer.writerow(data)

    def _logLastFitButton_fired(self):
        """logs the fit. User can use this for non automated logging. i.e. log
        particular fits"""
        self._log_fit()

    def _removeLastFitButton_fired(self):
        """removes the last line in the log file """
        logFolder = os.path.join(self.logDirectory, self.logName)
        self.logFile = os.path.join(logFolder, self.logName + ".csv")
        if self.logFile == "":
            logger.warning("no log file defined. Will not log")
            return
        if not os.path.exists(self.logFile):
            logger.error(
                "cant remove a line from a log file that doesn't exist")
        with open(self.logFile, 'r') as logFile:
            lines = logFile.readlines()
        with open(self.logFile, 'wb') as logFile:
            logFile.writelines(lines[:-1])

    def saveLastFit(self):
        """saves result of last fit to a txt/csv file. This can be useful for live analysis
        or for generating sequences based on result of last fit"""
        try:
            with open(
                    self.imageInspectorReference.cameraModel + "-" +
                    self.physics.species + "-" + "lastFit.csv",
                    "wb") as lastFitFile:
                writer = csv.writer(lastFitFile)
                writer.writerow(["time", time.time()])
                for variable in self.variablesList:
                    writer.writerow([variable.name, variable.calculatedValue])
                for variable in self.calculatedParametersList:
                    writer.writerow([variable.name, variable.value])
        except Exception as e:
            logger.error("failed to save last fit to text file. message %s " %
                         e.message)

    def _chooseVariablesButtons_fired(self):
        self.xmlLogVariables = self.chooseVariables()

    def _usePreviousFitValuesButton_fired(self):
        """update the guess initial values with the value from the last fit """
        logger.info(
            "use previous fit values button fired. loading previous initial values"
        )
        self._setInitialValues(self._getCalculatedValues())

    def getXmlVariables(self):
        if self.logAllVariables:
            return sorted(self.physics.variables.keys())
        else:
            return self.xmlLogVariables

    def chooseVariables(self):
        """Opens a dialog asking user to select columns from a data File that has
        been selected. THese are then returned as a string suitable for Y cols input"""
        columns = self.physics.variables.keys()
        columns.sort()
        values = zip(range(0, len(columns)), columns)

        checklist_group = traitsui.Group(
            '10',  # insert vertical space
            traitsui.Label('Select the additional variables you wish to log'),
            traitsui.UItem('columns',
                           style='custom',
                           editor=traitsui.CheckListEditor(values=values,
                                                           cols=6)),
            traitsui.UItem('selectAllButton'))

        traits_view = traitsui.View(checklist_group,
                                    title='CheckListEditor',
                                    buttons=['OK'],
                                    resizable=True,
                                    kind='livemodal')

        col = ColumnEditor(numberOfColumns=len(columns))
        try:
            col.columns = [
                columns.index(varName) for varName in self.xmlLogVariables
            ]
        except Exception as e:
            logger.error(
                "couldn't selected correct variable names. Returning empty selection"
            )
            logger.error("%s " % e.message)
            col.columns = []
        col.edit_traits(view=traits_view)
        logger.debug("value of columns selected = %s ", col.columns)
        logger.debug("value of columns selected = %s ",
                     [columns[i] for i in col.columns])
        return [columns[i] for i in col.columns]

    def _logLibrarianButton_fired(self):
        """opens log librarian for current folder in logName box. """
        logFolder = os.path.join(self.logDirectory, self.logName)
        if not os.path.isdir(logFolder):
            logger.error(
                "cant open librarian on a log that doesn't exist.... Could not find %s"
                % logFolder)
            return
        librarian = plotObjects.logLibrarian.Librarian(logFolder=logFolder)
        librarian.edit_traits()

    def _drawSubSpace_changed(self):
        newVisibility = self.drawSubSpace and self.fitSubSpace
        self.imageInspectorReference.ROIPolyPlot.visible = newVisibility
        self._startX_changed()  # update ROI data for plot

    def _fitSubSpace_changed(self):
        self._drawSubSpace_changed()

    def _startX_changed(self):
        if self.imageInspectorReference is None:
            return  # not yet initialized yet
        self.imageInspectorReference.ROIPolyPlot.index = chaco.ArrayDataSource(
            [self.startX, self.endX, self.endX, self.startX])
        self.imageInspectorReference.ROIPolyPlot.value = chaco.ArrayDataSource(
            [self.startY, self.startY, self.endY, self.endY])

    _endX_changed = _startX_changed
    _startY_changed = _startX_changed
    _endY_changed = _startX_changed
Exemple #25
0
class LogFilePlotFitter(traits.HasTraits):
    """This class allows the user to fit the data in log file plots with standard 
    functions or a custom function"""

    model = traits.Trait(
        "Gaussian", {
            "Linear": Model(fittingFunctions.linear),
            "Quadratic": Model(fittingFunctions.quadratic),
            "Gaussian": Model(fittingFunctions.gaussian),
            "lorentzian": Model(fittingFunctions.lorentzian),
            "parabola": Model(fittingFunctions.parabola),
            "exponential": Model(fittingFunctions.exponentialDecay),
            "sineWave": Model(fittingFunctions.sineWave),
            "sineWaveDecay1": Model(fittingFunctions.sineWaveDecay1),
            "sineWaveDecay2": Model(fittingFunctions.sineWaveDecay2),
            "sincSquared": Model(fittingFunctions.sincSquared),
            "sineSquared": Model(fittingFunctions.sineSquared),
            "sineSquaredDecay": Model(fittingFunctions.sineSquaredDecay),
            "custom": Model(custom)
        },
        desc="model selected for fitting the data"
    )  # mapped trait. so model --> string and model_ goes to Model object. see http://docs.enthought.com/traits/traits_user_manual/custom.html#mapped-traits
    parametersList = traits.List(
        Parameter, desc="list of parameters for fitting in chosen model")

    customCode = traits.Code(
        "def custom(x, param1, param2):\n\treturn param1*param2*x",
        desc="python code for a custom fitting function")
    customCodeCompileButton = traits.Button(
        "compile",
        desc=
        "defines the above function and assigns it to the custom model for fitting"
    )
    fitButton = traits.Button(
        "fit",
        desc="runs fit on selected data set using selected parameters and model"
    )
    usePreviousFitButton = traits.Button(
        "use previous fit",
        desc="use the fitted values as the initial guess for the next fit")
    guessButton = traits.Button(
        "guess",
        desc=
        "guess initial values from data using _guess function in library. If not defined button is disabled"
    )
    saveFitButton = traits.Button(
        "save fit",
        desc="writes fit parameters values and tolerances to a file")
    cycleAndFitButton = traits.Button(
        "cycle fit",
        desc=
        "fits using current initial parameters, saves fit, copies calculated values to initial guess and moves to next dataset in ordered dict"
    )
    dataSets = collections.OrderedDict(
    )  #dict mapping dataset name (for when we have multiple data sets) --> (xdata,ydata ) tuple (scipy arrays) e.g. {"myData": (array([1,2,3]), array([1,2,3]))}
    dataSetNames = traits.List(traits.String)
    selectedDataSet = traits.Enum(values="dataSetNames")
    modelFitResult = None
    logFilePlotReference = None
    modelFitMessage = traits.String("not yet fitted")
    isFitted = traits.Bool(False)
    maxFitTime = traits.Float(
        10.0, desc="maximum time fitting can last before abort")
    statisticsButton = traits.Button("stats")
    statisticsString = traits.String("statistics not calculated")
    plotPoints = traits.Int(200, label="Number of plot points")

    predefinedModelGroup = traitsui.VGroup(
        traitsui.Item("model", show_label=False),
        traitsui.Item("object.model_.definitionString",
                      style="readonly",
                      show_label=False,
                      visible_when="model!='custom'"))
    customFunctionGroup = traitsui.VGroup(traitsui.Item("customCode",
                                                        show_label=False),
                                          traitsui.Item(
                                              "customCodeCompileButton",
                                              show_label=False),
                                          visible_when="model=='custom'")
    modelGroup = traitsui.VGroup(predefinedModelGroup,
                                 customFunctionGroup,
                                 show_border=True)
    dataAndFittingGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("selectedDataSet", label="dataset"),
            traitsui.Item("fitButton", show_label=False),
            traitsui.Item("usePreviousFitButton", show_label=False),
            traitsui.Item("guessButton",
                          show_label=False,
                          enabled_when="model_.guessFunction is not None")),
        traitsui.HGroup(traitsui.Item("cycleAndFitButton", show_label=False),
                        traitsui.Item("saveFitButton", show_label=False),
                        traitsui.Item("statisticsButton", show_label=False)),
        traitsui.Item("plotPoints"),
        traitsui.Item("statisticsString", style="readonly"),
        traitsui.Item("modelFitMessage", style="readonly"),
        show_border=True)
    variablesGroup = traitsui.VGroup(traitsui.Item(
        "parametersList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True),
                                     show_border=True,
                                     label="parameters")

    traits_view = traitsui.View(traitsui.Group(modelGroup,
                                               dataAndFittingGroup,
                                               variablesGroup,
                                               layout="split"),
                                resizable=True)

    def __init__(self, **traitsDict):
        super(LogFilePlotFitter, self).__init__(**traitsDict)
        self._set_parametersList()

    def _set_parametersList(self):
        """sets the parameter list to the correct values given the current model """
        self.parametersList = [
            Parameter(name=parameterName, parameter=parameterObject)
            for (parameterName,
                 parameterObject) in self.model_.parameters.iteritems()
        ]

    def _model_changed(self):
        """updates model and hences changes parameters appropriately"""
        self._set_parametersList()
        self._guessButton_fired(
        )  # will only guess if there is a valid guessing function

    def _customCodeCompileButton_fired(self):
        """defines function as defined by user """
        exec(self.customCode)
        self.model_.__init__(custom)
        self._set_parametersList()

    def setFitData(self, name, xData, yData):
        """updates the dataSets dictionary """
        self.dataSets[name] = (xData, yData)

    def cleanValidNames(self, uniqueValidNames):
        """removes any elements from datasets dictionary that do not 
        have a key in uniqueValidNames"""
        for dataSetName in self.dataSets.keys():
            if dataSetName not in uniqueValidNames:
                del self.dataSets[dataSetName]

    def setValidNames(self):
        """sets list of valid choices for datasets """
        self.dataSetNames = self.dataSets.keys()

    def getParameters(self):
        """ returns the lmfit parameters object for the fit function"""
        return lmfit.Parameters(
            {_.name: _.parameter
             for _ in self.parametersList})

    def _setCalculatedValues(self, modelFitResult):
        """updates calculated values with calculated argument """
        parametersResult = modelFitResult.params
        for variable in self.parametersList:
            variable.calculatedValue = parametersResult[variable.name].value

    def _setCalculatedValuesErrors(self, modelFitResult):
        """given the covariance matrix returned by scipy optimize fit
        convert this into stdeviation errors for parameters list and updated
        the stdevError attribute of variables"""
        parametersResult = modelFitResult.params
        for variable in self.parametersList:
            variable.stdevError = parametersResult[variable.name].stderr

    def fit(self):
        params = self.getParameters()
        x, y = self.dataSets[self.selectedDataSet]
        self.modelFitResult = self.model_.model.fit(y, x=x, params=params)
        #self.modelFitResult = self.model_.model.fit(y, x=x, params=params,iter_cb=self.getFitCallback(time.time()))#can also pass fit_kws= {"maxfev":1000}
        self._setCalculatedValues(
            self.modelFitResult)  #update fitting paramters final values
        self._setCalculatedValuesErrors(self.modelFitResult)
        self.modelFitMessage = self.modelFitResult.message
        if not self.modelFitResult.success:
            logger.error("failed to fit in LogFilePlotFitter")
        self.isFitted = True
        if self.logFilePlotReference is not None:
            self.logFilePlotReference.plotFit()

    def getFitCallback(self, startTime):
        """returns the callback function that is called at every iteration of fit to check if it 
        has been running too long"""
        def fitCallback(params, iter, resid, *args, **kws):
            """check the time and compare to start time """
            if time.time() - startTime > self.maxFitTime:
                return True

        return fitCallback

    def _fitButton_fired(self):
        self.fit()

    def _usePreviousFitButton_fired(self):
        """update the initial guess value with the fitted values of the parameter """
        for parameter in self.parametersList:
            parameter.initialValue = parameter.calculatedValue

    def _guessButton_fired(self):
        """calls _guess function and updates initial fit values accordingly """
        print "guess button clicked"
        if self.model_.guessFunction is None:
            print "attempted to guess initial values but no guess function is defined. returning without changing initial values"
            logger.error(
                "attempted to guess initial values but no guess function is defined. returning without changing initial values"
            )
            return
        logger.info("attempting to guess initial values using %s" %
                    self.model_.guessFunction.__name__)
        xs, ys = self.dataSets[self.selectedDataSet]
        guessDictionary = self.model_.guessFunction(xs, ys)
        logger.debug("guess results = %s" % guessDictionary)
        print "guess results = %s" % guessDictionary
        for parameterName, guessValue in guessDictionary.iteritems():
            for parameter in self.parametersList:
                if parameter.name == parameterName:
                    parameter.initialValue = guessValue

    def _saveFitButton_fired(self):
        saveFolder, filename = os.path.split(self.logFilePlotReference.logFile)
        parametersResult = self.modelFitResult.params
        logFileName = os.path.split(saveFolder)[1]
        functionName = self.model_.function.__name__
        saveFileName = os.path.join(
            saveFolder, logFileName + "-" + functionName + "-fitSave.csv")

        #parse selected data set name to get column names
        #selectedDataSet is like "aaaa=1.31 bbbb=1.21"
        seriesColumnNames = [
            seriesString.split("=")[0]
            for seriesString in self.selectedDataSet.split(" ")
        ]

        if not os.path.exists(saveFileName):  #create column names
            with open(saveFileName, "ab+") as csvFile:
                writer = csv.writer(csvFile)
                writer.writerow(
                    seriesColumnNames +
                    [variable.name for variable in self.parametersList] + [
                        variable.name + "-tolerance"
                        for variable in self.parametersList
                    ])
        with open(saveFileName, "ab+") as csvFile:  #write save to file
            writer = csv.writer(csvFile)
            seriesValues = [
                seriesString.split("=")[1]
                for seriesString in self.selectedDataSet.split(" ")
            ]  #values of the legend keys so you know what fit was associated with
            writer.writerow(seriesValues + [
                parametersResult[variable.name].value
                for variable in self.parametersList
            ] + [
                parametersResult[variable.name].stderr
                for variable in self.parametersList
            ])

    def _cycleAndFitButton_fired(self):
        logger.info("cycle and fit button pressed")
        self._fitButton_fired()
        self._saveFitButton_fired()
        self._usePreviousFitButton_fired()
        currentDataSetIndex = self.dataSets.keys().index(self.selectedDataSet)
        self.selectedDataSet = self.dataSets.keys()[currentDataSetIndex + 1]

    def _statisticsButton_fired(self):
        from scipy.stats import pearsonr
        xs, ys = self.dataSets[self.selectedDataSet]
        mean = scipy.mean(ys)
        median = scipy.median(ys)
        std = scipy.std(ys)
        minimum = scipy.nanmin(ys)
        maximum = scipy.nanmax(ys)
        peakToPeak = maximum - minimum
        pearsonCorrelation = pearsonr(xs, ys)
        resultString = "mean=%G , median=%G stdev =%G\nmin=%G,max=%G, pk-pk=%G\nPearson Correlation=(%G,%G)\n(stdev/mean)=%G" % (
            mean, median, std, minimum, maximum, peakToPeak,
            pearsonCorrelation[0], pearsonCorrelation[1], std / mean)
        self.statisticsString = resultString

    def getFitData(self):
        dataX = self.dataSets[self.selectedDataSet][0]
        # resample x data
        dataX = np.linspace(min(dataX), max(dataX), self.plotPoints)
        dataY = self.modelFitResult.eval(x=dataX)
        return dataX, dataY
Exemple #26
0
class CreasePatternViz3D(Viz3D):
    '''Visualize the crease Pattern
    '''
    N_selection = Array(int)
    L_selection = Array(int)
    F_selection = Array(int)

    lines = Bool(True)

    N_L_F = Property(Tuple)
    '''Geometry with applied selection arrays.
    '''
    def _get_N_L_F(self):
        cp = self.vis3d
        x, L, F = cp.x, cp.L, cp.F
        if len(self.N_selection):
            x = x[self.N_selection]
        if len(self.L_selection):
            L = L[self.L_selection]
        if len(self.F_selection):
            F = F[self.F_selection]
        return x, L, F

    min_max = Property
    '''Rectangular bounding box. 
    '''

    def _get_min_max(self):
        vis3d = self.vis3d
        return np.min(vis3d.x, axis=0), np.max(vis3d.x, axis=0)

    facet_color = Color((0.6, 0.625, 0.683))

    #    facet_color = Color((0.0, 0.425, 0.683))
    #    facet_color = Color((0.4, 0.4, 0.7))
    #    facet_color = Color((0.0 / 255.0, 84.0 / 255.0, 159.0 / 255.0))
    #   facet_color = Color((64.0 / 255.0, 127.0 / 255.0, 183.0 / 255.0))
    #    facet_color = Color((0.0 / 255.0, 97.0 / 255.0, 101.0 / 255.0))

    def plot(self):

        m = self.ftv.mlab
        N, L, F = self.N_L_F
        x, y, z = N.T
        if len(F) > 0:
            cp_pipe = m.triangular_mesh(
                x,
                y,
                z,
                F,
                line_width=3,
                # color=self.facet_color.toTuple()[:-1],
                color=(0.6, 0.625, 0.683),
                #                                        color=(0.0, 0.425, 0.683),
                name='Crease pattern')
            #                                        color=self.facet_color.toTuple()[:-1])
            if self.lines is True:
                cp_pipe.mlab_source.dataset.lines = L
                tube = m.pipeline.tube(cp_pipe, tube_radius=self.tube_radius)
                lines = m.pipeline.surface(tube, color=(0.1, 0.1, 0.1))
                self.pipes['lines'] = lines
        else:
            cp_pipe = m.points3d(x, y, z, scale_factor=0.2)
            cp_pipe.mlab_source.dataset.lines = L
        self.pipes['cp_pipe'] = cp_pipe

    def update(self, vot=0.0):
        N = self.N_L_F[0]
        cp_pipe = self.pipes['cp_pipe']
        cp_pipe.mlab_source.set(points=N)

    def _get_bounding_box(self):
        N = self.N_L_F[0]
        return np.min(N, axis=0), np.max(N, axis=0)

    def _get_max_length(self):
        return np.linalg.norm(self._get_bounding_box())

    tube_radius = Float(0.03)

    line_width_factor = Float(0.0024)

    def _get_line_width(self):
        return self._get_max_length() * self.line_width_factor

    traits_view = tui.View(
        tui.VGroup(tui.Include('viz3d_view'), tui.UItem('tube_radius'),
                   tui.UItem('line_width_factor')))

    selection_view = traits_view
Exemple #27
0
class Parameter(traits.HasTraits):
    """represents a lmfit variable in a fit. E.g. the standard deviation in a gaussian
    fit"""
    parameter = traits.Instance(lmfit.Parameter)
    name = traits.Str

    initialValue = traits.Float
    calculatedValue = traits.Float
    vary = traits.Bool(True)

    minimumEnable = traits.Bool(False)
    minimum = traits.Float

    maximumEnable = traits.Bool(False)
    maximum = traits.Float

    stdevError = traits.Float

    def __init__(self, **traitsDict):
        super(Parameter, self).__init__(**traitsDict)
        self.parameter = lmfit.Parameter(name=self.name)

    def _initialValue_changed(self):
        self.parameter.set(value=self.initialValue)

    def _vary_changed(self):
        self.parameter.set(vary=self.vary)

    def _minimum_changed(self):
        if self.minimumEnable:
            self.parameter.set(min=self.minimum)

    def _maximum_changed(self):
        if self.maximumEnable:
            self.parameter.set(max=self.maximum)

    traits_view = traitsui.View(traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("vary", label="vary?", resizable=True),
            traitsui.Item("name",
                          show_label=False,
                          style="readonly",
                          width=0.2,
                          resizable=True),
            traitsui.Item("initialValue",
                          label="initial",
                          show_label=True,
                          resizable=True),
            traitsui.Item("calculatedValue",
                          label="calculated",
                          show_label=True,
                          format_str="%G",
                          style="readonly",
                          width=0.2,
                          resizable=True),
            traitsui.Item("stdevError",
                          show_label=False,
                          format_str=u"\u00B1%G",
                          style="readonly",
                          resizable=True)),
        traitsui.HGroup(
            traitsui.Item("minimumEnable", label="min?", resizable=True),
            traitsui.Item("minimum",
                          label="min",
                          resizable=True,
                          visible_when="minimumEnable"),
            traitsui.Item("maximumEnable", label="max?", resizable=True),
            traitsui.Item("maximum",
                          label="max",
                          resizable=True,
                          visible_when="maximumEnable"))),
                                kind="subpanel")
class PlotProperties(traits.HasTraits):
    """when doing a dual or later maybe multiple combined log File plots,
    there are often many parameters i want to repeat for each log file plot
    by making a class it reduce repetition in Matplotlibify"""
    logFilePlot = traits.Instance(
        plotObjects.logFilePlot.LogFilePlot
    )  #gives access to most of the required attributes
    xAxisLabel = traits.String("")
    yAxisLabel = traits.String("")
    setXLimitsBool = traits.Bool(False)
    setYLimitsBool = traits.Bool(False)
    xMin = traits.Float
    xMax = traits.Float
    yMin = traits.Float
    yMax = traits.Float
    scaleXBool = traits.Bool(False)
    scaleYBool = traits.Bool(False)
    scaleX = traits.Float(1.0)
    scaleY = traits.Float(1.0)
    offsetX = traits.Float(0.0)
    offsetY = traits.Float(0.0)
    plotFormatString = traits.String
    plotErrorBars = traits.Bool(True)
    legendReplacements = traits.Dict(key_trait=traits.String,
                                     value_trait=traits.String)
    useFitFile = traits.Bool(
        False,
        desc=
        'select to choose a fit file to use with the same series. will draw all fits'
    )
    fitFile = traits.File

    labelsGroup = traitsui.VGroup(
        traitsui.HGroup(traitsui.Item("xAxisLabel"),
                        traitsui.Item("yAxisLabel")))
    limitsGroup = traitsui.VGroup(
        traitsui.Item("setXLimitsBool", label="set x limits?"),
        traitsui.Item("setYLimitsBool", label="set y limits?"),
        traitsui.HGroup(
            traitsui.Item("xMin", label="x min",
                          visible_when="setXLimitsBool"),
            traitsui.Item("xMax", label="x max",
                          visible_when="setXLimitsBool"),
            traitsui.Item("yMin", label="y min",
                          visible_when="setYLimitsBool"),
            traitsui.Item("yMax", label="y max",
                          visible_when="setYLimitsBool")))
    scalingGroup = traitsui.VGroup(
        traitsui.HGroup(traitsui.Item('scaleXBool', label='scale x?'),
                        traitsui.Item('scaleX', visible_when="scaleXBool"),
                        traitsui.Item('offsetX', visible_when="scaleXBool")),
        traitsui.HGroup(traitsui.Item('scaleYBool', label='scale y?'),
                        traitsui.Item('scaleY', visible_when="scaleYBool"),
                        traitsui.Item('offsetY', visible_when="scaleYBool")))
    generalGroup = traitsui.VGroup(
        traitsui.Item("plotErrorBars", label="show error bars:"),
        traitsui.Item("legendReplacements"),
        traitsui.Item('plotFormatString', label="format string"))
    fitGroup = traitsui.HGroup(traitsui.Item('useFitFile',
                                             label='use fit file?'),
                               traitsui.Item('fitFile',
                                             show_label=False,
                                             visible_when='useFitFile'),
                               visible_when='logFilePlot.fitLogFileBool')

    fullGroup = traitsui.VGroup(labelsGroup,
                                limitsGroup,
                                scalingGroup,
                                generalGroup,
                                fitGroup,
                                show_border=True,
                                label='object.logFilePlot.logFilePlotsTabName')

    traits_view = traitsui.View(fullGroup, kind='live')

    def __init__(self, logFilePlot, **traitsDict):
        self.logFilePlot = logFilePlot
        super(PlotProperties, self).__init__(**traitsDict)

    def _xAxisLabel_default(self):
        return self.logFilePlot.xAxis

    def _yAxisLabel_default(self):
        return self.logFilePlot.yAxis

    def _legendReplacements_default(self):
        return {_: _ for _ in self.logFilePlot.parseSeries()}

    def _fitFile_default(self):
        return self.logFilePlot.logFile

    def _plotFormatString_default(self):
        if self.logFilePlot.mode == "XY Scatter":
            return "o"
        else:
            return "-o"

    def _xMin_default(self):
        return self.logFilePlot.firstPlot.x_axis.mapper.range.low

    def _xMax_default(self):
        return self.logFilePlot.firstPlot.x_axis.mapper.range.high

    def _yMin_default(self):
        return self.logFilePlot.firstPlot.y_axis.mapper.range.low

    def _yMax_default(self):
        return self.logFilePlot.firstPlot.y_axis.mapper.range.high

    def getFitFunction(self):
        """if fitting defined then it returns the string of the fitting function. Otherwise
        returns None"""
        if self.logFilePlot.fitLogFileBool:
            return self.logFilePlot.logFilePlotFitterReference.model
        else:
            return None

    def geFitFunctionSource(self, identifier=''):
        if self.logFilePlot.fitLogFileBool:
            source = self.logFilePlot.logFilePlotFitterReference.model_.definitionString
            name = (source.split('def '))[1].split('(')[0]
            if '2' in identifier:
                replacement = 'fitFunction2'
            else:
                replacement = 'fitFunction'
            return source.replace(name, replacement)
        else:
            return None

    def getFittedParameters(self):
        """returns a dictionary of parameter names --> fitted values  """
        if self.logFilePlot.fitLogFileBool:
            return {
                _.name: _.calculatedValue
                for _ in
                self.logFilePlot.logFilePlotFitterReference.parametersList
            }
        else:
            return None

    def getReplacementStringsSpecific(self, identifier=""):
        """generates the replacement strings that are specific to a log file plot.
        indentifier is used inside key to make it unique to that lfp and should have the format
        {{lfp.mode}}. Identifier must include the . character"""
        return {
            '{{%smode}}' % identifier:
            self.logFilePlot.mode,
            '{{%serrorBarMode}}' % identifier:
            self.logFilePlot.errorBarMode,
            '{{%slogFile}}' % identifier:
            self.logFilePlot.logFile,
            '{{%sxAxis}}' % identifier:
            self.logFilePlot.xAxis,
            '{{%syAxis}}' % identifier:
            self.logFilePlot.yAxis,
            '{{%saggregateAxis}}' % identifier:
            self.logFilePlot.aggregateAxis,
            '{{%sseries}}' % identifier:
            self.logFilePlot.series,
            '{{%sfiterYs}}' % identifier:
            self.logFilePlot.filterYs,
            '{{%sfilterMinYs}}' % identifier:
            self.logFilePlot.filterMinYs,
            '{{%sfilterMaxYs}}' % identifier:
            self.logFilePlot.filterMaxYs,
            '{{%sfilterXs}}' % identifier:
            self.logFilePlot.filterXs,
            '{{%sfilterMinXs}}' % identifier:
            self.logFilePlot.filterMinXs,
            '{{%sfilterMaxXs}}' % identifier:
            self.logFilePlot.filterMaxXs,
            '{{%sfilterNaN}}' % identifier:
            self.logFilePlot.filterNaN,
            '{{%sfilterSpecific}}' % identifier:
            self.logFilePlot.filterSpecific,
            '{{%sfilterSpecificString}}' % identifier:
            self.logFilePlot.filterSpecificString,
            '{{%sxLogScale}}' % identifier:
            self.logFilePlot.xLogScale,
            '{{%syLogScale}}' % identifier:
            self.logFilePlot.yLogScale,
            '{{%sinterpretAsTimeAxis}}' % identifier:
            self.logFilePlot.interpretAsTimeAxis,
            '{{%sisFitted}}' % identifier:
            self.logFilePlot.fitLogFileBool,
            '{{%sfitFunction}}' % identifier:
            self.getFitFunction(),
            '{{%sfitValues}}' % identifier:
            self.getFittedParameters(),
            '{{%sfitFunctionSource}}' % identifier:
            self.geFitFunctionSource(identifier),
            '{{%suseFitFile}}' % identifier:
            self.useFitFile,
            '{{%sfitFile}}' % identifier:
            self.fitFile,
            '{{%sxAxisLabel}}' % identifier:
            self.xAxisLabel,
            '{{%syAxisLabel}}' % identifier:
            self.yAxisLabel,
            '{{%slegendReplacements}}' % identifier:
            self.legendReplacements,
            '{{%ssetXLimitsBool}}' % identifier:
            self.setXLimitsBool,
            '{{%ssetYLimitsBool}}' % identifier:
            self.setYLimitsBool,
            '{{%sxlimits}}' % identifier: (self.xMin, self.xMax),
            '{{%sylimits}}' % identifier: (self.yMin, self.yMax),
            '{{%sscaleXBool}}' % identifier:
            self.scaleXBool,
            '{{%sscaleYBool}}' % identifier:
            self.scaleYBool,
            '{{%sscaleX}}' % identifier:
            self.scaleX,
            '{{%sscaleY}}' % identifier:
            self.scaleY,
            '{{%soffsetX}}' % identifier:
            self.offsetX,
            '{{%soffsetY}}' % identifier:
            self.offsetY,
            '{{%splotErrorBars}}' % identifier:
            self.plotErrorBars,
            '{{%splotFormatString}}' % identifier:
            self.plotFormatString
        }
Exemple #29
0
def create_model_plot(sources, handler=None, metadata=None):
    """Create the plot window

    Parameters
    ----------

    """
    if not isinstance(sources, (list)):
        stop("*** error: sources must be list of files")

    def genrunid(path):
        return os.path.splitext(os.path.basename(path))[0]

    if metadata is not None:
        stop("*** error: call create_view directly")
        metadata.plot.configure_traits(view=view)
        return

    if [source for source in sources if F_EVALDB in os.path.basename(source)]:
        if len(sources) > 1:
            stop(
                "*** error: only one source allowed with {0}".format(F_EVALDB))
        source = sources[0]
        if not os.path.isfile(source):
            stop("*** error: {0}: no such file".format(source))
        filepaths, variables = readtabular(source)
        runid = genrunid(filepaths[0])

    else:
        filepaths = []
        for source in sources:
            if not os.path.isfile(source):
                logerr("{0}: {1}: no such file".format(iam, source))
                continue
            fname, fext = os.path.splitext(source)
            if fext not in L_REC_EXT:
                logerr("{0}: unrecognized file extension".format(source))
                continue
            filepaths.append(source)
        if logerr():
            stop("***error: stopping due to previous errors")
        variables = [""] * len(filepaths)
        runid = ("Material Model Laboratory"
                 if len(filepaths) > 1 else genrunid(filepaths[0]))

    view = tuiapi.View(tuiapi.HSplit(
        tuiapi.VGroup(
            tuiapi.Item('Multi_Select', show_label=False),
            tuiapi.Item('Change_Axis', show_label=False),
            tuiapi.Item('Reset_Zoom', show_label=False),
            tuiapi.Item('Reload_Data', show_label=False),
            tuiapi.Item('Print_to_PDF', show_label=False),
            tuiapi.VGroup(tuiapi.HGroup(
                tuiapi.Item("X_Scale",
                            label="X Scale",
                            editor=tuiapi.TextEditor(multi_line=False)),
                tuiapi.Item("Y_Scale",
                            label="Y Scale",
                            editor=tuiapi.TextEditor(multi_line=False))),
                          show_border=True),
            tuiapi.VGroup(tuiapi.HGroup(
                tuiapi.Item('Load_Overlay', show_label=False, springy=True),
                tuiapi.Item('Close_Overlay', show_label=False, springy=True),
            ),
                          tuiapi.Item('Single_Select_Overlay_Files',
                                      show_label=False,
                                      resizable=False),
                          show_border=True)),
        tuiapi.VGroup(
            tuiapi.Item('Plot_Data',
                        show_label=False,
                        width=800,
                        height=568,
                        springy=True,
                        resizable=True),
            tuiapi.Item('Step',
                        editor=tuiapi.RangeEditor(low_name='low_step',
                                                  high_name='high_step',
                                                  format='%d',
                                                  label_width=28,
                                                  mode='slider')),
        )),
                       style='custom',
                       width=1124,
                       height=868,
                       resizable=True,
                       title=runid)

    main_window = ModelPlot(filepaths=filepaths, file_variables=variables)
    main_window.configure_traits(view=view, handler=handler)
    return main_window
class Matplotlibify(traits.HasTraits):
    logFilePlotReference = traits.Instance(
        logFilePlots.plotObjects.logFilePlot.LogFilePlot)
    plotPropertiesList = traits.List(PlotProperties)
    logFilePlot1 = traits.Any()
    logFilePlot2 = traits.Any()
    logFilePlotsReference = traits.Instance(
        logFilePlots.LogFilePlots)  #refernce to logFilePlots object
    isPriviliged = traits.Bool(False)
    hardCodeLegendBool = traits.Bool(
        False,
        desc=
        "click if you want to write your own legend otherwise it will generate legend based on series and legend replacement dict"
    )
    hardCodeLegendString = traits.String(
        "", desc="comma seperated string for each legend entry")
    #xLim = traits.Tuple()
    replacementStrings = {}
    savedPrintsDirectory = traits.Directory(
        os.path.join("\\\\ursa", "AQOGroupFolder", "Experiment Humphry",
                     "Data", "savedPrints"))
    showWaterMark = traits.Bool(True)

    matplotlibifyMode = traits.Enum("default", "dual plot")
    generatePlotScriptButton = traits.Button("generate plot")
    showPlotButton = traits.Button("show")
    #templatesFolder = os.path.join( os.path.expanduser('~'),"Google Drive","Thesis","python scripts","matplotlibify")
    templatesFolder = os.path.join("\\\\ursa", "AQOGroupFolder",
                                   "Experiment Humphry",
                                   "Experiment Control And Software",
                                   "LogFilePlots", "matplotlibify",
                                   "templates")
    templateFile = traits.File(
        os.path.join(templatesFolder, "matplotlibifyDefaultTemplate.py"))
    generatedScriptLocation = traits.File(
        os.path.join(os.path.expanduser('~'), "Google Drive", "Thesis",
                     "python scripts", "matplotlibify", "debug.py"))
    saveToOneNote = traits.Button("Save to OneNote")
    printButton = traits.Button("print")
    dualPlotMode = traits.Enum('sharedXY', 'sharedX', 'sharedY', 'stacked',
                               'stackedX', 'stackedY')
    logLibrarianReference = None

    secondPlotGroup = traitsui.VGroup(
        traitsui.Item("matplotlibifyMode", label="mode"),
        traitsui.HGroup(
            traitsui.Item("logFilePlot1",
                          visible_when="matplotlibifyMode=='dual plot'"),
            traitsui.Item("logFilePlot2",
                          visible_when="matplotlibifyMode=='dual plot'"),
            traitsui.Item('dualPlotMode',
                          visible_when="matplotlibifyMode=='dual plot'",
                          show_label=False)),
    )
    plotPropertiesGroup = traitsui.Item(
        "plotPropertiesList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True)

    generalGroup = traitsui.VGroup(
        traitsui.Item("showWaterMark", label="show watermark"),
        traitsui.HGroup(
            traitsui.Item("hardCodeLegendBool", label="hard code legend?"),
            traitsui.Item("hardCodeLegendString",
                          show_label=False,
                          visible_when="hardCodeLegendBool")),
        traitsui.Item("templateFile"),
        traitsui.Item("generatedScriptLocation", visible_when='isPriviliged'),
        traitsui.Item('generatePlotScriptButton', visible_when='isPriviliged'),
        traitsui.Item('showPlotButton'),
        traitsui.Item(
            'saveToOneNote', enabled_when='True'
        ),  # was deactivated for some time, probably there was an error, I try to debug this now
        traitsui.Item('printButton'))

    traits_view = traitsui.View(secondPlotGroup,
                                plotPropertiesGroup,
                                generalGroup,
                                resizable=True,
                                kind='live')

    def __init__(self, **traitsDict):
        super(Matplotlibify, self).__init__(**traitsDict)
        self.plotPropertiesList = [PlotProperties(self.logFilePlotReference)]
        self.generateReplacementStrings()
        self.add_trait(
            "logFilePlot1",
            traits.Trait(
                self.logFilePlotReference.logFilePlotsTabName, {
                    lfp.logFilePlotsTabName: lfp
                    for lfp in self.logFilePlotsReference.lfps
                }))
        self.add_trait(
            "logFilePlot2",
            traits.Trait(
                self.logFilePlotReference.logFilePlotsTabName, {
                    lfp.logFilePlotsTabName: lfp
                    for lfp in self.logFilePlotsReference.lfps
                }))

    def generateReplacementStrings(self):
        self.replacementStrings = {}
        if self.matplotlibifyMode == 'default':
            specific = self.plotPropertiesList[
                0].getReplacementStringsSpecific(identifier="")
            generic = self.getGlobalReplacementStrings()
            self.replacementStrings.update(specific)
            self.replacementStrings.update(generic)

        elif self.matplotlibifyMode == 'dual plot':
            specific1 = self.plotPropertiesList[
                0].getReplacementStringsSpecific(identifier="lfp1.")
            specific2 = self.plotPropertiesList[
                1].getReplacementStringsSpecific(identifier="lfp2.")
            generic = self.getGlobalReplacementStrings()
            self.replacementStrings.update(specific1)
            self.replacementStrings.update(specific2)
            self.replacementStrings.update(generic)

        for key in self.replacementStrings.keys(
        ):  #wrap strings in double quotes
            logger.info("%s = %s" % (self.replacementStrings[key],
                                     type(self.replacementStrings[key])))
            if isinstance(self.replacementStrings[key], (str, unicode)):
                if self.replacementStrings[key].startswith("def "):
                    continue  #if it is a function definition then dont wrap in quotes!
                else:
                    self.replacementStrings[key] = unicode(
                        self.wrapInQuotes(self.replacementStrings[key]))

    def getGlobalReplacementStrings(self, identifier=""):
        """generates the replacement strings that are specific to a log file plot """
        return {
            '{{%shardCodeLegendBool}}' % identifier: self.hardCodeLegendBool,
            '{{%shardCodeLegendString}}' % identifier:
            self.hardCodeLegendString,
            '{{%smatplotlibifyMode}}' % identifier: self.matplotlibifyMode,
            '{{%sshowWaterMark}}' % identifier: self.showWaterMark,
            '{{%sdualPlotMode}}' % identifier: self.dualPlotMode
        }

    def wrapInQuotes(self, string):
        return '"%s"' % string

    def _isPriviliged_default(self):
        if os.path.exists(
                os.path.join("C:", "Users", "tharrison", "Google Drive",
                             "Thesis", "python scripts", "matplotlibify")):
            return True
        else:
            return False

    def _generatedScriptLocation_default(self):
        root = os.path.join("C:", "Users", "tharrison", "Google Drive",
                            "Thesis", "python scripts", "matplotlibify")
        head, tail = os.path.split(self.logFilePlotReference.logFile)
        matplotlibifyName = os.path.splitext(tail)[0] + "-%s-vs-%s" % (
            self.plotPropertiesList[0]._yAxisLabel_default(),
            self.plotPropertiesList[0]._xAxisLabel_default())
        baseName = os.path.join(root, matplotlibifyName)
        filename = baseName + ".py"
        c = 0
        while os.path.exists(filename + ".py"):
            filename = baseName + "-%s.py" % c
            c += 1
        return filename

    def replace_all(self, text, replacementDictionary):
        for placeholder, new in replacementDictionary.iteritems():
            text = text.replace(placeholder, str(new))
        return text

    def _generatePlotScriptButton_fired(self):
        self.writePlotScriptToFile(self.generatedScriptLocation)

    def writePlotScriptToFile(self, path):
        """writes the script that generates the plot to the path """
        logger.info("attempting to generate matplotlib script...")
        self.generateReplacementStrings()
        with open(self.templateFile, "rb") as template:
            text = self.replace_all(template.read(), self.replacementStrings)
        with open(self.generatedScriptLocation, "wb") as output:
            output.write(text)
        logger.info("succesfully generated matplotlib script at location %s " %
                    self.generatedScriptLocation)

    def autoSavePlotWithMatplotlib(self, path):
        """runs the script with an appended plt.save() and plt.close("all")"""
        logger.info("attempting to save matplotlib plot...")
        self.generateReplacementStrings()
        with open(self.templateFile, "rb") as template:
            text = self.replace_all(template.read(), self.replacementStrings)
        ns = {}
        saveCode = "\n\nplt.savefig(r'%s', dpi=300)\nplt.close('all')" % path
        logger.info("executing save statement:%s" % saveCode)
        text += saveCode
        exec text in ns
        logger.info("exec completed succesfully...")

    def _showPlotButton_fired(self):
        logger.info("attempting to show matplotlib plot...")
        self.generateReplacementStrings()
        with open(self.templateFile, "rb") as template:
            text = self.replace_all(template.read(), self.replacementStrings)
        ns = {}
        exec text in ns
        logger.info("exec completed succesfully...")

    def _saveToOneNote_fired(self):
        """calls the lfp function to save the file in the log folder and then
        save it to oneNote. THis way there is no oneNote code in matplotlibify"""
        if self.logLibrarianReference is None:
            self.logFilePlotReference.savePlotAsImage(self)
        else:
            self.logFilePlotReference.savePlotAsImage(
                self, self.logLibrarianReference)

    def _matplotlibifyMode_changed(self):
        """change default template depending on whether or not this is a double axis plot """
        if self.matplotlibifyMode == "default":
            self.templateFile = os.path.join(
                self.templatesFolder, "matplotlibifyDefaultTemplate.py")
            self.plotPropertiesList = [
                PlotProperties(self.logFilePlotReference)
            ]
        elif self.matplotlibifyMode == "dual plot":
            self.templateFile = os.path.join(
                self.templatesFolder, "matplotlibifyDualPlotTemplate.py")
            if len(self.plotPropertiesList) > 1:
                self.plotPropertiesList[1] = PlotProperties(
                    self.logFilePlot2_)  #or should it be logFilePlot2_???
                logger.info("chanigng second element of plot properties list")
            elif len(self.plotPropertiesList) == 1:
                self.plotPropertiesList.append(
                    PlotProperties(self.logFilePlot2_))
                logger.info("appending to plot properties list")
            else:
                logger.error(
                    "there only be 1 or 2 elements in plot properties but found %s elements"
                    % len(self.plotPropertiesList))

    def _logFilePlot1_changed(self):
        """logFilePlot1 changed so update plotPropertiesList """
        logger.info("logFilePlot1 changed. updating plotPropertiesList")
        self.plotPropertiesList[0] = PlotProperties(self.logFilePlot1_)

    def _logFilePlot2_changed(self):
        logger.info("logFilePlot2 changed. updating plotPropertiesList")
        self.plotPropertiesList[1] = PlotProperties(self.logFilePlot2_)

    def dualPlotModeUpdates(self):
        """called when either _logFilePlot1 or _logFilePLot2 change """
        if (self.logFilePlot1_.xAxis == self.logFilePlot2_.xAxis
            ):  #Twin X 2 y axes mode
            if self.logFilePlot1_.yAxis == self.logFilePlot2_.yAxis:
                self.dualPlotMode = 'sharedXY'
            else:
                self.dualPlotMode = 'sharedX'
        elif self.logFilePlot1_.yAxis == self.logFilePlot2_.yAxis:
            self.dualPlotMode = 'sharedY'
        else:
            self.dualPlotMode = 'stacked'

    def _printButton_fired(self):
        """uses windows built in print image functionality to send png of plot to printer """
        logFolder, tail = os.path.split(self.logFilePlotReference.logFile)
        #logName = tail.strip(".csv")+" - "+str(self.selectedLFP.xAxis)+" vs "+str(self.selectedLFP.yAxis)
        imageFileName = os.path.join(logFolder, "temporary_print.png")
        self.logFilePlotReference.savePlotAsImage(self,
                                                  name=imageFileName,
                                                  oneNote=False)
        logger.info("attempting to use windows native printing dialog")
        os.startfile(os.path.normpath(imageFileName), "print")
        logger.info("saving to savedPrints folder")
        head, tail = os.path.split(self._generatedScriptLocation_default())
        tail = tail.replace(".py", ".png")
        dst = os.path.join(self.savedPrintsDirectory, tail)
        shutil.copyfile(os.path.normpath(imageFileName), dst)
        logger.info("saved to savedPrints folder")