Skip to content
Advertisement

Matplotlib, what to plot in a loop with user input

this is the first time i ask a question in here, so i hope i can ask it correctly any feedback on clarity is also appriciated.

I am forced to use matplotlib’s plot function in the code i am currently writing, due to the datastructure i am working with. But it does not do well with plotting in loops. What i aim to do, with my plot, is to be able to modify a background window determined by the user, and either accept or reject the output. But as i understand there is some conflict between matplotlibs interactive function and the use of a loop. I am relativly new to python, so the code might not be the prittiest, but useually i gets the job done. I am however at a complete loss for the particular problem. I have seen similair problems on the internet, which have been solved with plt.pause(‘timeinterval’) but this is not an option in my case. or atleast i cannot see how i can use it, since i want to wait for user input. I have also tried plt.waitforbuttonpress() but this is not very intuetive, i cannot choose which button it should wait for.

I guess a third option is to extract the data from the format hyperspy uses and then make a canvas of my own, which forfills my needs, but this is very tidious for me, due to my lack of experience.

Do anyone have any alternative ways of producing a plot, preferably with matplotlib such that i can achive what i am trying?

By the way, i have also tried turning off interactive mode, and this does not do the trick unfurtunatly.

Some information about the specs: This is running on a windows pc, using jupyterlab and python 3.10

I hope my dilemma is clear.

def set_background(self):
    """
    This function is ment to let the user define the background of each element, and then save the background for later use
    if working with multiple images of particles with the same composition.
    This function could be expanded to have interactive features so background would be clickable.
    """
    
    
    self.Background_tree = {}
    elements_in_sample = deepcopy(self.Data.metadata.Sample['elements'])
    Xray_in_sample = self.weighted_Xray_line_list
    data_sample = deepcopy(self.Data)
    integration_window = 1.3
    for element in elements_in_sample:
        data_sample.set_elements(elements=[element])
        for xray_line in (self.Data.metadata.Sample["xray_lines"]):
            if element in xray_line:   
                data_sample.set_lines([xray_line])
                background_points = input('please input the background points seperated by a space').split(' ')
                background_window = list(map(float,background_points))
                bw = data_sample.estimate_background_windows(background_window)
                iw = data_sample.estimate_integration_windows(integration_window)
                data_sample.sum().plot(True,bakcground_windows=background_window)
                happy = input('are you happy with the result?')
                if happy == 'y':
                #self.Data.get_lines_intensity(xray_lines=[xray_line], background_windows=bw, integration_windows=iw)
                    self.Background_tree[element+"_"+xray_line] = bw  

Advertisement

Answer

import pandas as pd
import numpy as np
import ipywidgets as wg
from ipywidgets import HBox, VBox
import matplotlib.pyplot as plt
from IPython.display import display
%matplotlib widget

a = np.arange(50)
b = np.random.rand(50) + a
c = np.sin(a)
d = np.cos(b)

df = pd.DataFrame({'a': a,
                   'b': b,
                   'c': c,
                   'd': d})

userinput1 = wg.Text(value="", placeholder='Type something', description='x axis')
userinput2 = wg.Text(value="", placeholder='Type something', description='y axis')
buttonplot = wg.Button(description='Plot', disabled=False, button_style='', tooltip='Click me',icon='check')
buttonout = wg.Output()
display(HBox((userinput1, userinput2, buttonplot)))
display(buttonout)
plt.close()
fig, ax = plt.subplots()
def on_click_event(change):
    with buttonout:
        x = (userinput1.value)
        y = (userinput2.value)
        ax.plot(df[x], df[y], label=f'{y}')
        ax.legend()
buttonplot.on_click(on_click_event)

Output:

enter image description here

After user input and clicking the button:

enter image description here

More user input:

enter image description here

Does it satisfy your need or am I getting further away from your initial question?

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement