Plotly - Create a callback function to use 2 buttons that affect the same fig - button

I have 2 buttons that affect the same scatter. The first button affect the 'i' and the second the 'j' in : ((np.swapaxes(AllData[j, :, :, :], 1, 2))[i, :, :])
The problem is when I clic on a dropdown button, it will set the other variable (i or j) at 0.
I think that I can solve it using a callback function right ? It's the first time that I use it and I don't really know how to do it...
I suggest to create a Callback function and call it at the end of my code in : fig.show(CallBackFct) ?
Thank you for helping :D
# Set all the Data in ALlData matrix
AllData = np.zeros((NbreOfBanks, NbreMeasure, NbreOfSamples, NbreOfNozzles))
for i in range(NbreMeasure):
AllData[:, i, :, :] = load_json(FolderPath, files[FirstToSee + i], "Sensing")
# Create the figure
fig = go.Figure(go.Scatter(x=list(range(0, NbreOfSamples)), y=((np.swapaxes(AllData[0, :, :, :], 1, 2))[0, 0, :]),
mode="lines"))
for k in range(1, NbreOfNozzles):
fig.add_scatter(x=list(range(0, NbreOfSamples)), y=((np.swapaxes(AllData[0, :, :, :], 1, 2))[NbreSelect, k, :]), mode="lines")
fig.update_layout(width=1600, height=900, title="Sensing Measure", title_x=0.5,
xaxis_title="Measure number", yaxis_title="ADC Value")
# Create button for selected JSON
buttons = []
for i in range(NbreMeasure):
buttons.append(dict(method='update',
label=files[FirstToSee + i],
visible=True,
args=[{'y': ((np.swapaxes(AllData[j, :, :, :], 1, 2))[i, :, :]),
'x': list(range(0, NbreOfSamples)),
'type': 'scatter'}, [0]],
)
)
# Create button for each bank option
buttons_bank = []
BankName = ['BankA', 'BankB', 'BankC', 'BankD']
for j in range(NbreOfBanks):
buttons_bank.append(dict(method='update',
label=str(BankName[j]),
visible=True,
args=[{'y': ((np.swapaxes(AllData[j, :, :, :], 1, 2))[i, :, :]),
'x': list(range(0, NbreOfSamples)),
'type': 'scatter'}, [0]],
)
)
# Add the dropdown button to the layout)
fig.update_layout(
updatemenus=[
dict(
buttons=buttons,
direction='down',
showactive=True,
x=0.1,
xanchor='left',
y=1.1,
yanchor='top'
),
dict(
buttons=buttons_bank,
direction='down',
showactive=True,
x=0,
xanchor='left',
y=1.1,
yanchor='top'
)
])
# add dropdown menus to the figure
fig.update_layout(showlegend=True)
fig.show()

Related

Find length of array of functions in Julia

I want to find the length, nc, of this "vector of functions". I should be 2.
comp(x) = [([x[5], x[6], x[7], x[8],x[9], x[10]], tmp(x)) ; ([x[1],x[2]], [x[3],x[4]])];
nc = ....
I tried with length(comp) and length(comp(x)) but it doesn't work. I get "x not defined" and "no method matching length(::typeof(comp))", respectively.
Pulling together some of the comments to hopefully make things clearer:
What you have written is essentially
function comp(x)
a = [x[5], x[6], x[7], x[8],x[9], x[10]]
b = [x[1],x[2]]
c = [x[3],x[4]]
return [(a, tmp(x)); (b, c)]
end
that is, you have defined a function comp which takes one argument x and then returns a 2-element vector of 2-element tuples, with the first tuple holding values 5 to 10 of x and the result of tmp(x) (this function is not defined in your code so we don't know what it returns), and the second tuple holding the first and second, and third and fourth elements of x, respectively.
To illustrate, assume tmp(x) just sums up the elements of x, then we can pass some array (in the below example a range) of numbers to comp and see it in action:
julia> tmp(x) = sum(x)
tmp (generic function with 1 method)
julia> comp(1:20)
2-element Vector{Tuple{Vector{Int64}, Any}}:
([5, 6, 7, 8, 9, 10], 210)
([1, 2], [3, 4])
and you can get the result of the return value:
julia> length(comp(1:20))
2

Module caution: In 'Show' occurs where it is probably not going to be evaluated before going out of scope

I have tried to make my own Manipulate module that draws numerical trajectories in 2D space depending on 1 parameter.
The problem is that I have this caution in title for every variable in Show.
I understand that it is related to some dynamic functionality, but I still don't know how to get rid of it.
Also, it will be great if I can get rid of the local variable name (k$8245) in output of this module.
MyManipulatePlot2D[list_, opts : OptionsPattern[]] :=
Module[{mv, pr, rt, constPlots, k},
{rt, mv, pr} = Dimensions[list];
constPlots = Table[ListPlot[list[[i,;;, 1 ;; 2]], opts], {i, rt}];
Manipulate[
Show[constPlots[[k]]], {k, 1, rt, 1}]
]
P.S. I don't want to take Manipulate out of the Module, because in my code this function is way more complex and it actually draws trajectories depending on 2 parameters.
Right here if someone is interested
MyManipulatePlot2D[list_, opts : OptionsPattern[]] :=
Module[{rt, mv1, pr, constPlots, k1, mv2, i, k2, pointsPlot},
{rt, mv1, mv2, pr} = Dimensions[list];
constPlots =
Table[ListPlot[
ArrayReshape[list[[;; , i, ;; , ;;]], {rt*mv2, pr}][[;; ,
1 ;; 2]], PlotStyle -> ColorData[97, "ColorList"][[2]],
opts], {i, mv1}];
pointsPlot = list[[;; , ;; , ;; , 1 ;; 2]];
pointsPlot = ArrayReshape[pointsPlot, {rt, mv1, mv2, 1, 2}];
Manipulate[
Show[{constPlots[[k1]],
ListPlot[pointsPlot[[;; , k1, k2]],
PlotLegends ->
Placed[ToString[{list[[1, k1, k2, 3]], list[[1, k1, k2, 4]]}],
Top]]}], {k1, 1, mv1, 1}, {k2, 1, mv2, 1}]
]
I have tried experementing with Evaluate funtion but it didn't work out.
You can fix the k$8245 problem by using Block instead of Module, or you can use a label "k" as below. k$8245 is the module's local variable name so it is showing as expected, even though not what you want. No other problems observed.
MyManipulatePlot2D[list_, opts : OptionsPattern[]] :=
Module[{mv, pr, rt, constPlots, k}, {rt, mv, pr} = Dimensions[list];
constPlots = Table[ListPlot[list[[i, ;; , 1 ;; 2]], opts], {i, rt}];
Manipulate[Show[constPlots[[k]]], {{k, 1, "k"}, 1, rt, 1}]]
The second manipulate just errors disasterously.

Returning list containing combinations of numbers in python using recursion only

This program prints out the different combinations of elements from the list. the idea is to either select the element or don't. The "print(store)" prints out the correct answers, however, if I try to make a list out of these answers it appears something is going wrong.
From what I understand from debugging, when "store.append(lst[i])" executes in the current function call at that instant "ans" is updated in the previous call. I am not sure how to go about returning a list of all the combinations.
ans = []
def comb(lst,i,store):
if i ==len(lst):
print(store)
global ans
ans.append(store)
else:
comb(lst,i+1,store) # dont select element
store.append(lst[i])
comb(lst,i+1,store) # select the element
store.pop()
def driver(lst):
comb(lst,0,[])
return ans
print(driver([1,2,3]))
#OUTPUT:
[]
[3]
[2]
[2, 3]
[1]
[1, 3]
[1, 2]
[1, 2, 3]
# return ans output:
[[], [], [], [], [], [], [], []]
Here is what I would do:
def comb(lst, i = 0, store = []):
if i == len(lst):
return [store]
x = comb(lst, i + 1, store)
y = comb(lst, i + 1, store + [lst[i]])
return x + y
I prefer not appending to a global ans or popping the store. Also, as far as possible don't use mutation.

How to use reverse Scaling function with error bars in mathematica?

I have data which I would like to plot along with the corresponding error bars:
{{{54927.7, -1.91044}, ErrorBar[38.2664, 0.0538982]},
{{55320.9, -1.97673}, ErrorBar[45.3592, 0.101486]},
{{55671.4, -2.15716}, ErrorBar[41.2234, 0.0258249]},
{{56032.9, -2.15957}, ErrorBar[38.8805, 0.0191277]},
{{56410.6, -2.14289}, ErrorBar[41.5501, 0.0189911]},
{{56787.2, -2.19703}, ErrorBar[38.1972, 0.00632055]},
{{57137.5, -2.1839}, ErrorBar[35.6098, 0.0084108]},
{{57493.3, -2.19994}, ErrorBar[38.0298, 0.00651633]},
{{57859.5, -2.19687}, ErrorBar[40.9682, 0.00658857]}}
I can use the "ErrorListPlot" function in *Mathematica just fine, however if I would like to reverse the y axis scale with the function "ScalingFunctions->"Reverse" " the error bars do not get plotted along with the data.....any suggestions on how to fix this?
Similar to this question. Some messing around to get the ticks looking right.
Needs["ErrorBarPlots`"]
data = {
{{54927.7, -1.91044}, ErrorBar[38.2664, 0.0538982]},
{{55320.9, -1.97673}, ErrorBar[45.3592, 0.101486]},
{{55671.4, -2.15716}, ErrorBar[41.2234, 0.0258249]},
{{56032.9, -2.15957}, ErrorBar[38.8805, 0.0191277]},
{{56410.6, -2.14289}, ErrorBar[41.5501, 0.0189911]},
{{56787.2, -2.19703}, ErrorBar[38.1972, 0.00632055]},
{{57137.5, -2.18390}, ErrorBar[35.6098, 0.0084108]},
{{57493.3, -2.19994}, ErrorBar[38.0298, 0.00651633]},
{{57859.5, -2.19687}, ErrorBar[40.9682, 0.00658857]}};
data[[All, 1, 2]] = -data[[All, 1, 2]];
ep = ErrorListPlot[data];
newTicks = AbsoluteOptions[ep, Ticks][[1, 2, 2]] /.
{x1_, x2_, x3_, x4_} :> If[x1 == x2,
{x1, NumberForm[-x2, {3, 2}], {0.014, 0}, x4},
{x1, x2, {0.007, 0}, x4}];
newTicks = newTicks /. {
GrayLevel[0.] -> GrayLevel[0.5],
AbsoluteThickness[0.25] -> AbsoluteThickness[0.18],
AbsoluteThickness[0.125] -> AbsoluteThickness[0.08]};
ErrorListPlot[data, Ticks -> {Automatic, newTicks}]
Needs["ErrorBarPlots`"]
data = {
{{54927.7, -1.91044}, ErrorBar[38.2664, 0.0538982]},
{{55320.9, -1.97673}, ErrorBar[45.3592, 0.101486]},
{{55671.4, -2.15716}, ErrorBar[41.2234, 0.0258249]},
{{56032.9, -2.15957}, ErrorBar[38.8805, 0.0191277]},
{{56410.6, -2.14289}, ErrorBar[41.5501, 0.0189911]},
{{56787.2, -2.19703}, ErrorBar[38.1972, 0.00632055]},
{{57137.5, -2.18390}, ErrorBar[35.6098, 0.0084108]},
{{57493.3, -2.19994}, ErrorBar[38.0298, 0.00651633]},
{{57859.5, -2.19687}, ErrorBar[40.9682, 0.00658857]}};
(* Invert the error bars, visible in InputForm *)
ep = InputForm[ErrorListPlot[data]] /.
{Line[{{a_, b_}, {c_, d_}}] :> Line[{{a, -b}, {c, -d}}],
Line[{Offset[e_, {f_, g_}], Offset[h_, {i_, j_}]}] :>
Line[{Offset[e, {f, -g}], Offset[h, {i, -j}]}]};
(* Discard the InputForm wrapper *)
ep2 = First[ep];
Show[ErrorListPlot[data, ScalingFunctions -> "Reverse"],
Delete[ep2, Most#First#Position[ep2, Point]]]

filter max of N

Could it be possible to write in FFL a version of filter that stops filtering after the first negative match, i.e. the remaining items are assumed to be positive matches? more generally, a filter.
Example:
removeMaxOf1([1,2,3,4], value>=2)
Expected Result:
[1,3,4]
This seems like something very difficult to write in a pure functional style. Maybe recursion or let could acheive it?
Note: the whole motivation for this question was hypothesizing about micro-optimizations. so performance is very relevant. I am also looking for something that is generally applicable to any data type, not just int.
I have recently added find_index to the engine which allows this to be done easily:
if(n = -1, [], list[:n] + list[n+1:])
where n = find_index(list, value<2)
where list = [1,2,3,4]
find_index will return the index of the first match, or -1 if no match is found. There is also find_index_or_die which returns the index of the first match, asserting if none is found for when you're absolutely certain there is an instance in the list.
You could also implement something like this using recursion:
def filterMaxOf1(list ls, function(list)->bool pred, list result=[]) ->list
base ls = []: result
base not pred(ls[0]): result + ls[1:]
recursive: filterMaxOf1(ls[1:], pred, result + [ls[0]])
Of course recursion can! :D
filterMaxOf1(input, target)
where filterMaxOf1 = def
([int] l, function f) -> [int]
if(size(l) = 0,
[],
if(not f(l[0]),
l[1:],
flatten([
l[0],
recurse(l[1:], f)
])
)
)
where input = [
1, 2, 3, 4, ]
where target = def
(int i) -> bool
i < 2
Some checks:
--> filterOfMax1([1, ]) where filterOfMax1 = [...]
[1]
--> filterOfMax1([2, ]) where filterOfMax1 = [...]
[]
--> filterOfMax1([1, 2, ]) where filterOfMax1 = [...]
[1]
--> filterOfMax1([1, 2, 3, 4, ]) where filterOfMax1 = [...]
[1, 3, 4]
This flavor loses some strong type safety, but is nearer to tail recursion:
filterMaxOf1(input, target)
where filterMaxOf1 = def
([int] l, function f) -> [int]
flatten(filterMaxOf1i(l, f))
where filterMaxOf1i = def
([int] l, function f) -> [any]
if(size(l) = 0,
[],
if(not f(l[0]),
l[1:],
[
l[0],
recurse(l[1:], f)
]
)
)
where input = [
1, 2, 3, 4, ]
where target = def
(int i) -> bool
i < 2

Resources