33import dash
44import pandas
55from urllib .error import HTTPError
6- from dash import dcc , html , Input , Output , callback , Patch , ctx , no_update
6+ from dash import dcc , html , Input , Output , callback , Patch , ctx , no_update , State
77import plotly .graph_objects as go
88import dash_bootstrap_components as dbc
99import numpy as np
1010from numpy import sqrt , linspace , vstack , hstack , pi , nan , full , exp , square , arange , array , sin , cos , diff , matmul , log10 , deg2rad , identity , ones , zeros , diag , cov , mean
1111from numpy .random import randn , randint
1212from numpy .linalg import cholesky , eig , det , inv
1313from scipy .special import erfinv
14-
14+ import deterministic_gaussian_sampling_fibonacci as dgsf
1515
1616from components .popup_box import PopupBox
1717from model .selfcontained_distribution import SelfContainedDistribution
@@ -33,7 +33,7 @@ def get_data(url):
3333
3434class Gaus2D (SelfContainedDistribution ):
3535 def __init__ (self ):
36- self .smethods = ['iid' , 'Fibonacci' , 'LCD' , 'SP-Julier04' , 'SP-Menegaz11' ] # Sampling methods
36+ self .smethods = ['iid' , 'Fibonacci' , 'LCD' , 'SP-Julier04' , 'SP-Menegaz11' , 'Classical Frolov' , 'Improved Frolov' , 'Fibonacci Frolov' ] # Sampling methods
3737 self .tmethods = ['Cholesky' , 'Eigendecomposition' ] # Transformation methods
3838
3939 # Colors
@@ -116,6 +116,8 @@ def __init__(self):
116116 value = self .smethods [randint (len (self .smethods ))],
117117 inline = True ),
118118
119+ html .Br (),
120+
119121 # Transformation Method RadioItems
120122 dbc .RadioItems (id = 'gauss2D-tmethod' ,
121123 options = [{"label" : x , "value" : x } for x in self .tmethods ],
@@ -173,27 +175,39 @@ def _register_callbacks(self):
173175 Output ('gauss2D-p' , 'step' ),
174176 Output ('gauss2D-p' , 'tooltip' ),
175177 Output ('gauss2D-L' , 'disabled' ),
178+ Output ('gauss2D-tmethod' , 'className' ),
179+ Output ('gauss2D-p' , 'className' ), # to hide when not needed
176180 Input ("gauss2D-smethod" , "value" ),
177181 )
178182 def update_smethod (smethod ):
179183 patched_tooltip = Patch ()
184+ patched_tooltip .always_visible = True
180185 match smethod :
181186 case 'iid' :
182187 patched_tooltip .template = "dice"
183188 # min, max, value, step, tooltip
184- return 0 , 1 , .5 , 0.001 , patched_tooltip , False
189+ return 0 , 1 , .5 , 0.001 , patched_tooltip , False , 'visible' , 'visible'
185190 case 'Fibonacci' :
186191 patched_tooltip .template = "z={value}"
187- return - 50 , 50 , 0 , 1 , patched_tooltip , False
192+ return - 50 , 50 , 0 , 1 , patched_tooltip , False , 'visible' , 'visible'
188193 case 'LCD' :
189194 patched_tooltip .template = "α={value}°"
190- return - 360 , 360 , 0 , 0.1 , patched_tooltip , False
195+ return - 360 , 360 , 0 , 0.1 , patched_tooltip , False , 'visible' , 'visible'
191196 case 'SP-Julier04' :
192197 patched_tooltip .template = "W₀={value}"
193- return - 2 , 1 , .1 , 0.001 , patched_tooltip , True
198+ return - 2 , 1 , .1 , 0.001 , patched_tooltip , True , 'visible' , 'visible'
194199 case 'SP-Menegaz11' :
195200 patched_tooltip .template = "Wₙ₊₁={value}"
196- return 0 , 1 , 1 / 3 , 0.001 , patched_tooltip , True
201+ return 0 , 1 , 1 / 3 , 0.001 , patched_tooltip , True , 'visible' , 'visible'
202+ case 'Classical Frolov' :
203+ patched_tooltip .always_visible = False
204+ return no_update , no_update , no_update , no_update , patched_tooltip , False , 'invisible' , 'invisible'
205+ case 'Improved Frolov' :
206+ patched_tooltip .always_visible = False
207+ return no_update , no_update , no_update , no_update , patched_tooltip , False , 'invisible' , 'invisible'
208+ case 'Fibonacci Frolov' :
209+ patched_tooltip .always_visible = False
210+ return no_update , no_update , no_update , no_update , patched_tooltip , False , 'invisible' , 'invisible'
197211 case _:
198212 raise Exception ("Wrong smethod" )
199213
@@ -214,6 +228,8 @@ def update_smethod(smethod):
214228 Input ("angle" , "value" ),
215229 )
216230 def update (smethod , tmethod , p , L0 , sigma_x , sigma_y , rho , angle ):
231+ if smethod in ['Classical Frolov' , 'Improved Frolov' , 'Fibonacci Frolov' ]:
232+ tmethod = None
217233 trig = ctx .triggered_id
218234
219235 def _rot2d (angle_deg ):
@@ -298,17 +314,28 @@ def _rot2d(angle_deg):
298314 # x1 = CC / sqrt(W1)
299315 xySND = hstack ((x0 , x1 ))
300316 weights = hstack ((p , w1 ))
317+ case 'Classical Frolov' | 'Improved Frolov' | 'Fibonacci Frolov' :
318+ method = smethod .replace (' ' , '' )
319+ method = 'Fibonacci' if method == 'FibonacciFrolov' else method
320+ if L > 0 :
321+ samples = dgsf .sample_gaussian_fibonacci (μ .flatten (), C , L , method )
322+ else :
323+ samples = np .empty ((L , 2 ))
324+ xyG = samples .T
325+
301326 case _:
302327 raise Exception ("Wrong smethod" )
303328 match tmethod :
304329 case 'Cholesky' :
305330 xyG = matmul (cholesky (C ), xySND ) + μ
306331 case 'Eigendecomposition' :
307332 xyG = matmul (C_R , sqrt (C_D ) * xySND ) + μ
333+ case None :
334+ pass
308335 case _:
309336 raise Exception ("Wrong smethod" )
310337 # Sample weights to scatter sizes
311- L2 = xySND .shape [1 ] # actual number of saamples
338+ L2 = xySND .shape [1 ] if tmethod is not None else xyG . shape [ 1 ] # actual number of saamples
312339 if L2 == 0 :
313340 sizes = 10
314341 else :
0 commit comments