Noob needs help debugging and UNDERSTANDING reactive models

Hi there
making “some” progress with julia but every now and again I hit something that I am misunderstanding. To fix this I use the REPL but right now I am having NO luck. To illustrate this I am trying to understand how to test a flag model.isready using the code provided by the splendid @hhaensel. BUT I clearly am misunderstanding the whole Reactive model approach.

timeout = 10 # or whatever your startup process needs
t0 = now()
while ! model.isready[] && now() - t0 < timeout
    sleep(200)
end
now() - t0 < timeout && model.df[] = my_brand_new_dataframe

or just do

model.isready[] && model.df[] = my_brand_new_dataframe

the code block used in the REPL looks like this

sing Stipple
using StippleUI
using StipplePlotly

using CSV, DataFrames, Dates , Logging

dash_columns = ["sym","close","price","sdmove","hv20","hv10","hv5","iv","iv%ile","prc%ile","ern_days"]

df = DataFrame([col => (col == "sym" ? String : Float64)[] for col in dash_columns])

df_table = Observable(df)

zmq_dash = Dict("LAST" => "price","CLOSE" => "close","OPTION_IMPLIED_VOL" => "iv","OPTION_HISTORICAL_VOL" => "iv",
                         "VOLUME"  => "volume","IV" => "iv","IV_PERCENTILE" => "iv%ile" ,"HV20" => "hv20",
                         "HV10" => "hv10","HV5" => "hv5" ,"PRICE_PERCENTILE" => "prc%ile","EARNDAYS" => "ern_days")

@reactive mutable struct TontineModel <: ReactiveModel
    tontine_data::R{DataTable} = DataTable(df_table[])
    tontine_data_pagination::DataTablePagination = DataTablePagination(rows_per_page=100) #9/9/22
end

function ui(model::TontineModel)
    page(
        model, class="container", title="title TONTINE2 ", head_content=Genie.Assets.favicon_support(),

        [
        heading("heading Tontine2 9/6/22")

        row([
            cell(class="st-module", [
            h5("h5 tontine data")
            table(:tontine_data;
            style="height: 2500px;",
            pagination=:tontine_data_pagination) # 9/9/22 added pagination
            ])
        ])
        ]
    )
end

function handlers(model)
    on(df_table) do _
        notify(model.tontine_data)
    end

    model
end



route("/") do
    TontineModel |> init |> handlers |> ui |> html
end

# up(9000; async = true, server = Stipple.bootstrap())

up()

Could someone take a look at my thrashing around in the REPL to tell me:

How I could examine the flag model.isready[]

give me some REPL model debugging tips that I can use to get to grips with this.

julia> using Stipple

julia> using StippleUI

julia> using StipplePlotly

julia> using CSV, DataFrames, Dates , Logging

julia> using ZMQ

julia> # 9/6/22 OLD WAY   io = open("/home/dave/tontine_2022/data/logs/logfile.log", "w+")

       log_date = Dates.format(now(),"yyyy_mm_dd_HH_MM")
"2022_09_10_08_46"

julia> log_name = "/home/dave/tontine_2022/data/logs/tontine2_log_" * log_date * ".log"
"/home/dave/tontine_2022/data/logs/tontine2_log_2022_09_10_08_46.log"

julia> io = open( log_name, "w+")
IOStream(<file /home/dave/tontine_2022/data/logs/tontine2_log_2022_09_10_08_46.log>)

julia> logger = SimpleLogger(io)
Base.CoreLogging.SimpleLogger(IOStream(<file /home/dave/tontine_2022/data/logs/tontine2_log_2022_09_10_08_46.log>), Info, Dict{Any, Int64}())

julia> global_logger(logger)
ConsoleLogger(IOBuffer(data=UInt8[...], readable=false, writable=false, seekable=false, append=false, size=0, maxsize=0, ptr=1, mark=-1), Info, Logging.default_metafmt, true, 0, Dict{Any, Int64}())

julia> dash_columns = ["sym","close","price","sdmove","hv20","hv10","hv5","iv","iv%ile","prc%ile","ern_days"]
11-element Vector{String}:
 "sym"
 "close"
 "price"
 "sdmove"
 "hv20"
 "hv10"
 "hv5"
 "iv"
 "iv%ile"
 "prc%ile"
 "ern_days"

julia> df = DataFrame([col => (col == "sym" ? String : Float64)[] for col in dash_columns])
0×11 DataFrame

julia> df_table = Observable(df)
Observable{DataFrame} with 0 listeners. Value:
0×11 DataFrame

julia> zmq_dash = Dict("LAST" => "price","CLOSE" => "close","OPTION_IMPLIED_VOL" => "iv","OPTION_HISTORICAL_VOL" => "iv",
                                "VOLUME"  => "volume","IV" => "iv","IV_PERCENTILE" => "iv%ile" ,"HV20" => "hv20",
                                "HV10" => "hv10","HV5" => "hv5" ,"PRICE_PERCENTILE" => "prc%ile","EARNDAYS" => "ern_days")
Dict{String, String} with 12 entries:
  "EARNDAYS"              => "ern_days"
  "VOLUME"                => "volume"
  "HV20"                  => "hv20"
  "LAST"                  => "price"
  "IV"                    => "iv"
  "CLOSE"                 => "close"
  "HV5"                   => "hv5"
  "HV10"                  => "hv10"
  "OPTION_HISTORICAL_VOL" => "iv"
  "PRICE_PERCENTILE"      => "prc%ile"
  "OPTION_IMPLIED_VOL"    => "iv"
  "IV_PERCENTILE"         => "iv%ile"

julia> @reactive mutable struct TontineModel <: ReactiveModel
           tontine_data::R{DataTable} = DataTable(df_table[])
           tontine_data_pagination::DataTablePagination = DataTablePagination(rows_per_page=100) #9/9/22
       end
TontineModel

julia> function ui(model::TontineModel)
           page(
               model, class="container", title="title TONTINE2 ", head_content=Genie.Assets.favicon_support(),

               [
               heading("heading Tontine2 9/6/22")

               row([
                   cell(class="st-module", [
                   h5("h5 tontine data")
                   table(:tontine_data;
                   style="height: 2500px;",
                   pagination=:tontine_data_pagination) # 9/9/22 added pagination
                   ])
               ])
               ]
           )
       end
ui (generic function with 1 method)

julia> function handlers(model)
           on(df_table) do _
               notify(model.tontine_data)
           end

           model
       end
handlers (generic function with 1 method)

julia> model
ERROR: UndefVarError: model not defined

julia> df_table
Observable{DataFrame} with 0 listeners. Value:
0×11 DataFrame

julia> route("/") do
           TontineModel |> init |> handlers |> ui |> html
       end
[GET] / => #8 | :get

julia> up()
Genie.AppServer.ServersCollection(Task (runnable) @0x00007f6848424740, nothing)

julia> model
ERROR: UndefVarError: model not defined

julia> To
Toggles       TontineModel  Toolbars      Tooltips
julia> TontineModel
TontineModel

julia> TontineModel.
flags       hash        instance    layout      name        parameters  size        super       types
julia> TontineModel.flags
0x72

julia> TontineModel.instance
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getproperty(x::Type, f::Symbol)
   @ Base ./Base.jl:33
 [2] top-level scope
   @ REPL[25]:1

julia> TontineModel.layout
Ptr{Nothing} @0x00007f6851774318

julia> TontineModel.name
typename(TontineModel)

julia> TontineModel.parameters
svec()

julia> TontineModel.types
svec(WARNING: both HttpCommon and Genie export "Headers"; uses of it in module Html must be qualified
WARNING: both Html and Base export "div"; uses of it in module Stipple must be qualified
WARNING: both Html and Base export "mark"; uses of it in module Stipple must be qualified
WARNING: both Html and Base export "summary"; uses of it in module Stipple must be qualified
WARNING: both Html and Base export "time"; uses of it in module Stipple must be qualified
WARNING: both Html and Base export "view"; uses of it in module Stipple must be qualified
Reactive{DataTable}, DataTablePagination, String, Reactive{Bool}, Reactive{Bool})

julia> TontineModel.s
size   super
julia> TontineModel.s
size   super
julia> TontineModel.size
40

julia> TontineModel.super
ReactiveModel

julia> 

Hi, it is a bit difficult to figure out what exactly the problem is.

It seems that the key problem in the REPL session is that after you call up()
it does not create the variable model in the REPL session.

Probably you need to call

route("/") do
    model = TontineModel |> init |> handlers
    html(ui(model), context = @__MODULE__)
end

In order to get the model variable into the REPL. (However, I cannot run code right now, I just looked at this as a template: GitHub - GenieFramework/Stipple.jl: The reactive UI library for interactive data applications with pure Julia.

1 Like

thank you @SteffenPL I tried your suggestion out but it didn’t work.

julia> route("/") do
           model = TontineModel |> init |> handlers
           html(ui(model), context = @__MODULE__)
       end
[GET] / => #10 | :get

julia> model
ERROR: UndefVarError: model not defined

julia> up()
Genie.AppServer.ServersCollection(Task (failed) @0x00007f699cf6fc70, nothing)

julia> down()
2-element Vector{Genie.AppServer.ServersCollection}:
 Genie.AppServer.ServersCollection(Task (done) @0x00007f6848424740, nothing)
 Genie.AppServer.ServersCollection(Task (failed) @0x00007f699cf6fc70, nothing)

julia> up()
Genie.AppServer.ServersCollection(Task (runnable) @0x00007f68548c0d00, nothing)

julia> model
ERROR: UndefVarError: model not defined

I also saw your observation that it was difficult to read the REPL so I added the code block to the OP. Thanks for pointing that out. I HAD looked at the Stipple docs but to be honest when the example they gave didn’t work I was disheartened. So much so I actually accepted the carbon chaps offer for a sitdown chat next week.

julia> using Stipple

julia> @reactive mutable struct Name <: ReactiveModel
         name::R{String} = "World!"
       end
Name

julia> function ui(model)
         page( model, class="container", [
             h1([
               "Hello "
               span("", @text(:name))
             ])

             p([
               "What is your name? "
               input("", placeholder="Type your name", @bind(:name))
             ])
           ]
         )
       end
ui (generic function with 1 method)

julia> route("/") do
         model = Name |> init
         html(ui(model), context = @__MODULE__)
       end
[GET] / => #4 | :get

julia> up()
┌ Info: 
└ Web Server starting at http://127.0.0.1:8000 
Genie.AppServer.ServersCollection(Task (runnable) @0x00007f2b95cabde0, nothing)

julia> model
ERROR: UndefVarError: model not defined

julia> model.name[]
ERROR: UndefVarError: model not defined
Stacktrace:
 [1] top-level scope
   @ REPL[7]:1

julia> model.name[][ Info: GET / 200
julia> [ Info: GET /stipple.jl/master/assets/css/stipplecore.css 200
[ Info: GET /genie.jl/master/assets/js/channels.js 200
[ Info: GET /stipple.jl/master/assets/js/underscore-min.js 200
julia> [ Info: GET /stipple.jl/master/assets/js/vue.js 200
[ Info: GET /stipple.jl/master/assets/js/stipplecore.js 200
[ Info: GET /stipple.jl/master/assets/js/name.js 200
[ Info: GET /stipple.jl/master/assets/js/vue_filters.js 200
[ Info: GET /stipple.jl/master/assets/js/watchers.js 200
[ Info: GET /stipple.jl/master/assets/js/keepalive.js 200
julia> model
ERROR: UndefVarError: model not defined

julia> model.name[]
ERROR: UndefVarError: model not defined
Stacktrace:
 [1] top-level scope
   @ REPL[9]:1

julia> 


I tend to like to use worked examples to get my head round concepts. When they don’t work it’s disappointing.

I’ll go back and take another look. If you have any REPL model tips I would be REALLY happy to look at them. Thanks again.

You need to declare the model global

route("/") do
         global model
         model = Name |> init
         html(ui(model), context = @__MODULE__)
end
3 Likes

hi there @hhaensel

I tried cut and pasting your worked example from https://github.com/GenieFramework/Stipple.jl#example-1 which doesn’t have the global mod so I made the mod you suggested

route("/") do
         global model
         model = Name |> init
         html(ui(model), context = @__MODULE__)
end

and after opening the web page it worked. Great relief. Now I have to see why my code keeps dumping out of stipple. This works for the example code BUT not for mine. I made the global mod ( see below)

sing Stipple
using StippleUI
using StipplePlotly

using CSV, DataFrames, Dates , Logging

dash_columns = ["sym","close","price","sdmove","hv20","hv10","hv5","iv","iv%ile","prc%ile","ern_days"]

df = DataFrame([col => (col == "sym" ? String : Float64)[] for col in dash_columns])

df_table = Observable(df)

zmq_dash = Dict("LAST" => "price","CLOSE" => "close","OPTION_IMPLIED_VOL" => "iv","OPTION_HISTORICAL_VOL" => "iv",
                         "VOLUME"  => "volume","IV" => "iv","IV_PERCENTILE" => "iv%ile" ,"HV20" => "hv20",
                         "HV10" => "hv10","HV5" => "hv5" ,"PRICE_PERCENTILE" => "prc%ile","EARNDAYS" => "ern_days")

@reactive mutable struct TontineModel <: ReactiveModel
    tontine_data::R{DataTable} = DataTable(df_table[])
    tontine_data_pagination::DataTablePagination = DataTablePagination(rows_per_page=100) #9/9/22
end

function ui(model::TontineModel)
    page(
        model, class="container", title="title TONTINE2 ", head_content=Genie.Assets.favicon_support(),

        [
        heading("heading Tontine2 9/6/22")

        row([
            cell(class="st-module", [
            h5("h5 tontine data")
            table(:tontine_data;
            style="height: 2500px;",
            pagination=:tontine_data_pagination) # 9/9/22 added pagination
            ])
        ])
        ]
    )
end

function handlers(model)
    on(df_table) do _
        notify(model.tontine_data)
    end

    model
end



route("/") do
    global TontineModel
    TontineModel |> init |> handlers |> ui |> html
end

# up(9000; async = true, server = Stipple.bootstrap())

up()

and I still get this

ave@deepthought:~$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.8.1 (2022-09-06)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using Stipple
[ Info: Precompiling Stipple [4acbeb90-81a0-11ea-1966-bdaff8155998]

julia> using StippleUI
[ Info: Precompiling StippleUI [a3c5d34a-b254-4859-a8fa-b86abb7e84a3]

julia> using StipplePlotly
[ Info: Precompiling StipplePlotly [ec984513-233d-481d-95b0-a3b58b97af2b]

julia> using CSV, DataFrames, Dates , Logging
[ Info: Precompiling CSV [336ed68f-0bac-5ca0-87d4-7b16caf5d00b]

julia> dash_columns = ["sym","close","price","sdmove","hv20","hv10","hv5","iv","iv%ile","prc%ile","ern_days"]
11-element Vector{String}:
 "sym"
 "close"
 "price"
 "sdmove"
 "hv20"
 "hv10"
 "hv5"
 "iv"
 "iv%ile"
 "prc%ile"
 "ern_days"

julia> df = DataFrame([col => (col == "sym" ? String : Float64)[] for col in dash_columns])
0×11 DataFrame

julia> df_table = Observable(df)
Observable{DataFrame} with 0 listeners. Value:
0×11 DataFrame

julia> zmq_dash = Dict("LAST" => "price","CLOSE" => "close","OPTION_IMPLIED_VOL" => "iv","OPTION_HISTORICAL_VOL" => "iv",
                                "VOLUME"  => "volume","IV" => "iv","IV_PERCENTILE" => "iv%ile" ,"HV20" => "hv20",
                                "HV10" => "hv10","HV5" => "hv5" ,"PRICE_PERCENTILE" => "prc%ile","EARNDAYS" => "ern_days")
Dict{String, String} with 12 entries:
  "EARNDAYS"              => "ern_days"
  "VOLUME"                => "volume"
  "HV20"                  => "hv20"
  "LAST"                  => "price"
  "IV"                    => "iv"
  "CLOSE"                 => "close"
  "HV5"                   => "hv5"
  "HV10"                  => "hv10"
  "OPTION_HISTORICAL_VOL" => "iv"
  "PRICE_PERCENTILE"      => "prc%ile"
  "OPTION_IMPLIED_VOL"    => "iv"
  "IV_PERCENTILE"         => "iv%ile"

julia> @reactive mutable struct TontineModel <: ReactiveModel
           tontine_data::R{DataTable} = DataTable(df_table[])
       end
TontineModel

julia> function ui(model::TontineModel)
           page(
               model, class="container", title="title TONTINE2 ", head_content=Genie.Assets.favicon_support(),

               [
               heading("heading Tontine2 9/6/22")

               row([
                   cell(class="st-module", [
                   h5("h5 tontine data")
                   table(:tontine_data;
                   style="height: 2000px;",)
                   ])
               ])
               ]
           )
       end
ui (generic function with 1 method)

julia> function handlers(model)
           on(df_table) do _
               notify(model.tontine_data)
           end

           model
       end
handlers (generic function with 1 method)

julia> route("/") do
           global TontineModel # 9/10/22
           TontineModel |> init |> handlers |> ui |> html
       end
[GET] / => #8 | :get

julia> # up(9000; async = true, server = Stipple.bootstrap())
       up()
┌ Info: 
└ Web Server starting at http://127.0.0.1:8000 
Genie.AppServer.ServersCollection(Task (runnable) @0x00007fe92e6770f0, nothing)

julia> T[ Info: GET / 200
julia> Tononti[ Info: GET /stippleui.jl/master/assets/css/quasar.min.css 200
[ Info: GET /stippleui.jl/master/assets/js/quasar.umd.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/plotly2.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/resizesensor.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/lodash.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/vueresize.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/vueplotly.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/sentinel.min.js 200
[ Info: GET /stippleplotly.jl/master/assets/js/syncplot.js 200
[ Info: GET /stipple.jl/master/assets/js/tontinemodel.js 200
[ Info: GET /stipple.jl/master/assets/css/stipplecore.css 200
[ Info: GET /genie.jl/master/assets/js/channels.js 200
[ Info: GET /stipple.jl/master/assets/js/underscore-min.js 200
[ Info: GET /stipple.jl/master/assets/js/vue.js 200
[ Info: GET /stipple.jl/master/assets/js/stipplecore.js 200
[ Info: GET /stipple.jl/master/assets/js/vue_filters.js 200
[ Info: GET /stipple.jl/master/assets/js/watchers.js 200
[ Info: GET /stipple.jl/master/assets/js/keepalive.js 200


julia> TontineModel.isready
ERROR: type DataType has no field isready
Stacktrace:
 [1] getproperty(x::Type, f::Symbol)
   @ Base ./Base.jl:33
 [2] top-level scope
   @ REPL[18]:1
julia> TontineModel.
flags       hash        instance    layout      name        parameters  size        super       types
route("/") do
    global model
    model = TontineModel |> init |> handlers |> ui |> html
end

TontineModel is the type and not the variable, so you want to make model global since it actually stored the data. That’s something independent or reactive models here.

1 Like

Almost, it should be

route("/") do
    global model
    model = TontineModel |> init |> handlers
    model |> ui |> html
end
2 Likes

@hhaensel that got it, Thank you so much for helping out a frustrated and , I am sure, frustrating noob and on a weekend no less.

I don’t really see the difference between

route("/") do
    global model
    model = TontineModel |> init |> handlers |> ui |> html
end

and

route("/") do
    global model
    model = TontineModel |> init |> handlers
    model |> ui |> html
end

what is the functionality of

  model = TontineModel |> init |> handlers |> ui |> html

vs

route("/") do
    global model
    model = TontineModel |> init |> handlers
    model |> ui |> html
end

I would like to thank @SteffenPL for helping me as well. This kindness keeps me trying to learn julia.

model |> ui is no longer a model.

You could do

(model = TontineModel |> init |> handlers) |> ui |> html

or

(model = init(TontineModel)) |> handlers |> ui |> html
end
1 Like

but

(model = TontineModel |> init |> handlers) |> ui |> html

is what I had in the first place? I STILL don’t get it.

is this a precedence thing? where the pipe parentheses get executed then the ui |> html pipe?

I ask because the I’m about to start testing isready to resolve what I think is a realtime update issue in my stipple code. The timing of these events are important to me. Something breaks and I want to make sure I have a clear idea as to the sequencing

That’s right, = has lowest precedence

1 Like

thank you, both you and the splendid @SteffenPL have given me the will to carry on with julia. Discourse and it’s denizens are what makes julia great. Thank you for ALL your contributions.

2 Likes