Plots crashes

plotting

#1

I’m having all kinds of problems with Plots and PyPlot. At this time, the following happens:

Pkg.rm("Plots")
Pkg.add("Plots")
Pkg.update()

restart

workspace() 
using Plots
plot()
Julia has stopped: null, SIGSEGV

PyPlot is a little more forgiving. It will allow me to do:

using PyPlot
plot()

But if I first load a module of mine, execute a computation that returns an vector I would like to plot, and then run using PyPlot, I get a crash. I have updated matplotlib, XQuartz, Anaconda.

Below is the output of a crash after running PyPlot: I’m getting some segmentation fault:11 crash.

What should I be looking for? Any ideas?

truncated sample:

    Process:               julia [586]
    Path:                  /Applications/Julia-0.5.app/Contents/Resources/julia/bin/julia
    Identifier:            julia
    Version:               ???
    Code Type:             X86-64 (Native)
    Parent Process:        Atom Helper [327]
    Responsible:           Atom [269]
    User ID:               502

    Date/Time:             2017-06-10 01:17:36.658 +0800
    OS Version:            Mac OS X 10.10.5 (14F2411)
    Report Version:        11
    Anonymous UUID:        492C9CB7-BC26-304E-C519-9DAE1A82CD90


    Time Awake Since Boot: 460 seconds

    Crashed Thread:        0  Dispatch queue: com.apple.main-thread

    Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000008

    VM Regions Near 0x8:
    --> 
        __TEXT                 000000010e17f000-000000010e181000 [    8K] r-x/rwx SM=COW  /Applications/Julia-0.5.app/Contents/Resources/julia/bin/julia

    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0   libjulia.0.5.2.dylib          	0x000000010e1e2c7e julia_type_to_llvm + 46
    1   libjulia.0.5.2.dylib          	0x000000010e2019d4 emit_expr(_jl_value_t*, jl_codectx_t*) + 4788
    2   libjulia.0.5.2.dylib          	0x000000010e1e7d2e emit_function(_jl_lambda_info_t*, _jl_llvm_functions_t*) + 17774
    3   libjulia.0.5.2.dylib          	0x000000010e1e34c2 jl_compile_linfo + 914
    4   libjulia.0.5.2.dylib          	0x000000010e202234 emit_expr(_jl_value_t*, jl_codectx_t*) + 6932
    5   libjulia.0.5.2.dylib          	0x000000010e20287e emit_expr(_jl_value_t*, jl_codectx_t*) + 8542
    6   libjulia.0.5.2.dylib          	0x000000010e2050f1 emit_stmtpos(_jl_value_t*, jl_codectx_t*) + 161
    7   libjulia.0.5.2.dylib          	0x000000010e1e871f emit_function(_jl_lambda_info_t*, _jl_llvm_functions_t*) + 20319
    8   libjulia.0.5.2.dylib          	0x000000010e1e34c2 jl_compile_linfo + 914
    9   libjulia.0.5.2.dylib          	0x000000010e202234 emit_expr(_jl_value_t*, jl_codectx_t*) + 6932
    10  libjulia.0.5.2.dylib          	0x000000010e20287e emit_expr(_jl_value_t*, jl_codectx_t*) + 8542
    11  libjulia.0.5.2.dylib          	0x000000010e2050f1 emit_stmtpos(_jl_value_t*, jl_codectx_t*) + 161
    12  libjulia.0.5.2.dylib          	0x000000010e1e871f emit_function(_jl_lambda_info_t*, _jl_llvm_functions_t*) + 20319
    13  libjulia.0.5.2.dylib          	0x000000010e1e34c2 jl_compile_linfo + 914
    14  libjulia.0.5.2.dylib          	0x000000010e202234 emit_expr(_jl_value_t*, jl_codectx_t*) + 6932
    15  libjulia.0.5.2.dylib          	0x000000010e206312 emit_call(jl_expr_t*, jl_codectx_t*) + 786
    16  libjulia.0.5.2.dylib          	0x000000010e201fb8 emit_expr(_jl_value_t*, jl_codectx_t*) + 6296
    17  libjulia.0.5.2.dylib          	0x000000010e2050f1 emit_stmtpos(_jl_value_t*, jl_codectx_t*) + 161
    18  libjulia.0.5.2.dylib          	0x000000010e1e871f emit_function(_jl_lambda_info_t*, _jl_llvm_functions_t*) + 20319
    19  libjulia.0.5.2.dylib          	0x000000010e1e34c2 jl_compile_linfo + 914
    20  libjulia.0.5.2.dylib          	0x000000010e19c4a6 jl_compile_for_dispatch + 918
    21  libjulia.0.5.2.dylib          	0x000000010e19b672 jl_apply_generic + 1106
    22  libjulia.0.5.2.dylib          	0x000000010e1c6b9a jl_module_run_initializer + 282
    23  libjulia.0.5.2.dylib          	0x000000010e1c30e8 _jl_restore_incremental + 2184
    24  libjulia.0.5.2.dylib          	0x000000010e1c316c jl_restore_incremental + 76
    25  sys.dylib                     	0x000000010fcbdd12 julia__include_from_serialized_22632 + 242 (.loading.jl:150)
    26  sys.dylib                     	0x000000010fcbe1ec julia__require_from_serialized_22598 + 908 (.loading.jl:187)
    27  sys.dylib                     	0x000000010fe0e011 julia__require_search_from_serialized_32311 + 705 (.loading.jl:217)
    28  sys.dylib                     	0x000000010fe0e341 jlcall__require_search_from_serialized_32311 + 33
    29  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    30  sys.dylib                     	0x000000010fcbf402 julia_require_22458 + 1282 (.loading.jl:371)
    31  sys.dylib                     	0x000000010fcc01dc jlcall_require_22458 + 12
    32  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    33  libjulia.0.5.2.dylib          	0x000000010e1c5958 read_verify_mod_list + 520
    34  libjulia.0.5.2.dylib          	0x000000010e1c29e7 _jl_restore_incremental + 391
    35  libjulia.0.5.2.dylib          	0x000000010e1c316c jl_restore_incremental + 76
    36  sys.dylib                     	0x000000010fcbdd12 julia__include_from_serialized_22632 + 242 (.loading.jl:150)
    37  sys.dylib                     	0x000000010fcbe1ec julia__require_from_serialized_22598 + 908 (.loading.jl:187)
    38  sys.dylib                     	0x000000010fe0e011 julia__require_search_from_serialized_32311 + 705 (.loading.jl:217)
    39  sys.dylib                     	0x000000010fe0e341 jlcall__require_search_from_serialized_32311 + 33
    40  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    41  sys.dylib                     	0x000000010fcbf402 julia_require_22458 + 1282 (.loading.jl:371)
    42  sys.dylib                     	0x000000010fcc01dc jlcall_require_22458 + 12
    43  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    44  libjulia.0.5.2.dylib          	0x000000010e1c8c95 eval_import_path_ + 565
    45  libjulia.0.5.2.dylib          	0x000000010e1c780d jl_toplevel_eval_flex + 797
    46  libjulia.0.5.2.dylib          	0x000000010e1a54fe jl_parse_eval_all + 1214
    47  sys.dylib                     	0x000000010fe44d1e julia_include_string_33641 + 270 (.loading.jl:441)
    48  sys.dylib                     	0x000000010fe44e80 jlcall_include_string_33641 + 16
    49  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    50  libjulia.0.5.2.dylib          	0x000000010e1b13b8 do_call + 200
    51  libjulia.0.5.2.dylib          	0x000000010e1af73c eval + 860
    52  libjulia.0.5.2.dylib          	0x000000010e1b0d5e eval_body + 462
    53  libjulia.0.5.2.dylib          	0x000000010e1b12a2 jl_interpret_call + 498
    54  libjulia.0.5.2.dylib          	0x000000010e1c7a3d jl_toplevel_eval_flex + 1357
    55  libjulia.0.5.2.dylib          	0x000000010e1a9333 jl_toplevel_eval_in_warn + 899
    56  sys.dylib                     	0x000000010fc6c64a julia_eval_19854 + 10 (.boot.jl:234)
    57  sys.dylib                     	0x000000010fc6c660 jlcall_eval_19854 + 16
    58  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    59  ???                           	0x000000031de62922 0 + 13386524962
    60  ???                           	0x000000031de62266 0 + 13386523238
    61  ???                           	0x000000031de623f3 0 + 13386523635
    62  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    63  ???                           	0x000000031de6202a 0 + 13386522666
    64  ???                           	0x000000031de62073 0 + 13386522739
    65  ???                           	0x000000031de5fe43 0 + 13386513987
    66  libjulia.0.5.2.dylib          	0x000000010e19b608 jl_apply_generic + 1000
    67  libjulia.0.5.2.dylib          	0x000000010e1b9a54 start_task + 356

    Thread 1:
    0   libsystem_kernel.dylib        	0x00007fff91a8d75a __sigwait + 10
    1   libjulia.0.5.2.dylib          	0x000000010e1e0ddd signal_listener + 45
    2   libsystem_pthread.dylib       	0x00007fff940b905a _pthread_body + 131
    3   libsystem_pthread.dylib       	0x00007fff940b8fd7 _pthread_start + 176
    4   libsystem_pthread.dylib       	0x00007fff940b63ed thread_start + 13

    Thread 2:
    0   libsystem_kernel.dylib        	0x00007fff91a884de mach_msg_trap + 10
    1   libsystem_kernel.dylib        	0x00007fff91a8764f mach_msg + 55
    2   libsystem_kernel.dylib        	0x00007fff91a87f60 mach_msg_server + 468
    3   libjulia.0.5.2.dylib          	0x000000010e1e02fd mach_segv_listener + 29
    4   libsystem_pthread.dylib       	0x00007fff940b905a _pthread_body + 131
    5   libsystem_pthread.dylib       	0x00007fff940b8fd7 _pthread_start + 176
    6   libsystem_pthread.dylib       	0x00007fff940b63ed thread_start + 13

    Thread 3:
    0   libsystem_kernel.dylib        	0x00007fff91a8d136 __psynch_cvwait + 10
    1   libopenblas64_.dylib          	0x00000003150754db blas_thread_server + 171
    2   libsystem_pthread.dylib       	0x00007fff940b905a _pthread_body + 131
    3   libsystem_pthread.dylib       	0x00007fff940b8fd7 _pthread_start + 176
    4   libsystem_pthread.dylib       	0x00007fff940b63ed thread_start + 13

    Thread 4:: Dispatch queue: com.apple.libdispatch-manager
    0   libsystem_kernel.dylib        	0x00007fff91a8e232 kevent64 + 10
    1   libdispatch.dylib             	0x00007fff8902526e _dispatch_mgr_thread + 52

    Thread 5:
    0   libsystem_kernel.dylib        	0x00007fff91a8d3fa __select + 10
    1   libsystem_pthread.dylib       	0x00007fff940b905a _pthread_body + 131
    2   libsystem_pthread.dylib       	0x00007fff940b8fd7 _pthread_start + 176
    3   libsystem_pthread.dylib       	0x00007fff940b63ed thread_start + 13

    Thread 6:
    0   libsystem_kernel.dylib        	0x00007fff91a884de mach_msg_trap + 10
    1   libsystem_kernel.dylib        	0x00007fff91a8764f mach_msg + 55
    2   com.apple.CoreFoundation      	0x00007fff942bacd4 __CFRunLoopServiceMachPort + 212
    3   com.apple.CoreFoundation      	0x00007fff942ba19b __CFRunLoopRun + 1371
    4   com.apple.CoreFoundation      	0x00007fff942b99f8 CFRunLoopRunSpecific + 296
    5   com.apple.AppKit              	0x00007fff9340756b _NSEventThread + 137
    6   libsystem_pthread.dylib       	0x00007fff940b905a _pthread_body + 131
    7   libsystem_pthread.dylib       	0x00007fff940b8fd7 _pthread_start + 176
    8   libsystem_pthread.dylib       	0x00007fff940b63ed thread_start + 13

    Thread 0 crashed with X86 Thread State (64-bit):
      rax: 0x000000010e418b58  rbx: 0x000000010e418b30  rcx: 0x0000000000000006  rdx: 0x00007fff78015070
      rdi: 0x0000000000000010  rsi: 0x0000000000000000  rbp: 0x00007fff51a76190  rsp: 0x00007fff51a76180
       r8: 0x0000000000000010   r9: 0x0000000113134670  r10: 0x00007fff51a76e00  r11: 0x0000000113134790
      r12: 0x0000000000000010  r13: 0x00007fff51a76898  r14: 0x000000011b4b9990  r15: 0x00007fff51a76898
      rip: 0x000000010e1e2c7e  rfl: 0x0000000000010202  cr2: 0x0000000000000008

    Logical CPU:     2
    Error Code:      0x00000004
    Trap Number:     14


    Binary Images:
           0x10e17f000 -        0x10e180fff +julia (???) <14C26D69-968A-330E-A43C-FA7B63AA2B19> /Applications/Julia-0.5.app/Contents/Resources/julia/bin/julia
           0x10e189000 -        0x10e312ff7 +libjulia.0.5.2.dylib (0) <4E8849D2-8A7B-3797-9EAC-8CADD9EE1BEE> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/libjulia.0.5.2.dylib
           0x10e5f9000 -        0x10f602ff7 +libLLVM-3.7.dylib (0) <05AE218C-1CE2-32C4-A7B2-952F60F4619C> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libLLVM-3.7.dylib
           0x10fb3b000 -        0x1118eeff7 +sys.dylib (0) <34ABB9C3-A8C2-3924-96FE-CAA963899C1E> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib
           0x3148cd000 -        0x3148cffff +libdSFMT.dylib (0) <7FFA0121-C161-31AA-B74B-9F0E29CDE7A3> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libdSFMT.dylib
           0x3148d2000 -        0x31490bfe7 +libquadmath.0.dylib (0) <FB40BC93-613B-3268-AC2D-8C25846F7323> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libquadmath.0.dylib
           0x31491a000 -        0x31491bff7 +libsuitesparseconfig.dylib (0) <E4FB5166-CE72-31F4-A508-84D12F766481> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libsuitesparseconfig.dylib
           0x31491e000 -        0x31491eff7 +libsuitesparse_wrapper.dylib (0) <244B1012-7E53-3084-A307-69637724EC56> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libsuitesparse_wrapper.dylib
           0x314ae5000 -        0x314b68ff7 +libpcre2-8.0.dylib (4) <DA720706-FB17-3116-904A-8EA1A46DCAB9> /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/libpcre2-8.0.dylib
           0x314c6d000 -        0x314cdafdf +libgmp.10.dylib (14) <07013073-3AE8-38B3-8AD4-7FED2F599623> 

truncated here

    VM_ALLOCATE (reserved)              7.8G        reserved VM address space (unallocated)
    __DATA                             24.5M
    __IMAGE                             528K
    __LINKEDIT                         96.7M
    __TEXT                            345.2M
    __UNICODE                           552K
    mapped file                        98.1M
    shared memory                         4K
    ===========                      =======
    TOTAL                               8.9G
    TOTAL, minus reserved VM space      1.1G


    Model: MacBookAir5,2, BootROM MBA51.00EF.B05, 2 processors, Intel Core i5, 1.8 GHz, 4 GB, SMC 2.5f9
    Graphics: Intel HD Graphics 4000, Intel HD Graphics 4000, Built-In
    Memory Module: BANK 0/DIMM0, 2 GB, DDR3, 1600 MHz, 0x802C, 0x384B54463235363634485A2D3147364D3120
    Memory Module: BANK 1/DIMM0, 2 GB, DDR3, 1600 MHz, 0x802C, 0x384B54463235363634485A2D3147364D3120
    AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0xE9), Broadcom BCM43xx 1.0 (7.15.166.24.3)
    Bluetooth: Version 4.3.6f4 17916, 3 services, 18 devices, 1 incoming serial ports
    Network Service: Wi-Fi, AirPort, en0
    Serial ATA Device: APPLE SSD SM128E, 121.33 GB
    USB Device: Hub
    USB Device: Hub
    USB Device: BRCM20702 Hub
    USB Device: Bluetooth USB Host Controller
    USB Device: Apple Internal Keyboard / Trackpad
    USB Device: Internal Memory Card Reader
    USB Device: Hub
    USB Device: FaceTime HD Camera (Built-in)
    Thunderbolt Bus: MacBook Air, Apple Inc., 23.4

#2

It shouldn’t crash!
Can you try to run it without workspace() though? (Why do you do that, by the way - it is well-known to cause crashes and has no practical use I can think of?).


#3

What is versioninfo() and Pkg.status("Plots")?


#4

Ah I didn’t know there were problems with workspace(). I see it is documented without any warning. It just says it’s for interactive use, which is what I’m doing. I use it to make sure that I don’t add methods to functions that already exist, for instance. I had some weird stuff happening once because of that and thought workspace() was a neat solution.

https://docs.julialang.org/en/stable/stdlib/base/

But now I see that if I don’t execute workspace() I don’t get the crash.

Thanks for your help Michael!


#5

Just in case it’s still relevant:

versioninfo()

Julia Version 0.5.2
Commit f4c6c9d4bb (2017-05-06 16:34 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin13.4.0)
CPU: Intel® Core™ i5-3427U CPU @ 1.80GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.7.1 (ORCJIT, ivybridge)

Pkg.status(“Plots”)
Plots 0.11.3


#6

Cool. The julia ideomatic way of dealing with the issue you mention is to use modules. If you use Juno you can follow the instructions here https://github.com/JunoLab/atom-julia-client/blob/master/manual/workflow.md , there is also a nice discussion here http://discuss.junolab.org/t/juno-workflow-with-working-module-and-variable-evaluations/612


#7

Thanks Michael, I generally do use module. But in interactive mode, as I fiddle with things I just type into the console. This is also the time I appreciate seeing a plot in the juno window. Otherwise, mostly, I print the plots to file. I’ll follow up on your links. Thanks.


#8

follow-up question, if I may.

What do you do to view a plot when the console returns something like:

PyObject <matplotlib.text.Text object at 0x32b4b9b10>

Normally I restart Juno every 5 to 10 minutes, which resolves this type of issue. But I’m trying to learn to keep it open, as per an earlier discussion we had. How do I get Juno to display the plot again rather than just returning the plot object?


#9

gui(). It’s an open issue that we’re working hard to fix.


#10

Thanks Michael. I’ll give gui() a try next time I have this problem.

So now that I have stopped using workspace() before include-ing my module, I get pages of warnings like this:

WARNING: both myMainModule and myMainModule export “myfunction”; uses of it in module Main must be qualified.

followed by a MethodError.

I’m faced with the following choice: either I stick to workspace() and give up on Plots (until now I was exporting all my data and plotting it in R, but for some reason I suddenly decided I wanted to plot in Julia) or I give up on workspace() and I need to restart Juno everytime I test code edits (approximately every 5 minutes)…


#11

I actually don’t see why you’d need to restart julia. If you’re afraid of leftover methods, you can check that with methods(foo). Excuse me for not understanding the problem, I’ve just never run into it before.
It sounds like you’re using the module rather than setting it as the working module in Juno? I prefer that latter approach.
BTW if you do prefer plotting in R (the horror!) the easiest is to do it through RCall.


#12

Thanks Michael for your patience. Let me explain what’s going on.

I have a module that computes a discretized partial differential equation problem. It loads several packages, such as Distances, Parameters and DataFrames to conduct the main computations and return solutions stored in data frames. I am currently trying to plot some of this data within Julia by appending several functions, e.g. plot_solution(ms), where ms is an instance of the model solution, where these plotting functions use packages such as Plots, PyPlot, or Gadfly (not sure which I might end up using as I am in the early stages of experimentation).

As I write my module, I edit my functions, for instance generalizing certain steps by adding a tolerance parameter or an additional conditional here and there. As I do that, at the design/debug stage, I edit 1-20 lines in my module and quickly want to see if the change has broken something. I paste something like this in the console:

include("module.jl")
include("plotting.jl")
using MyMainModule
sol = myfunction()

and that’s where one of 3 things happen:

  1. I have just restarted Juno and executed the code once: no problem

  2. I have not restarted Juno and executed the code for the second time:

     WARNING: both MyMainModule and MyMainModule export "myfunction"; uses of it in module Main must be qualified.
    
  3. I have run workspace() before executing the command above: crash if I include the Plots related module; no problem if I give do not inlude plotting.jl.


#13

If you instead follow the advice in the link I posted above and set the “working module” in Juno (lower-right corner) you shouldn’t run into this problem.

plot_solution would be easy and nice to implement using a @userplot recipe: https://juliaplots.github.io/recipes/ , which only requires you to import RecipesBase in your module (it needs Plots to be loaded by the user for actual plotting). If you import Plots, PyPlot or Gadfly instead, you may be creating namespace clash issues for a user of your package who wants to use a different plotting package (maybe for something else while they’ve got your package loaded).


#14

Thanks Michael.

  1. On PlotRecipes, I need to look into this. I haven’t come across it yet. Will experiment and get back to you if I run into problems.

  2. To be perfectly honest, I hadn’t read the Juno link beyond about halfway, as the instructions seemed pretty daunting and it wasn’t obvious what the gain was supposed to be. But having read it now (and with apologies for being lazy the first time around), I see some hope. I have followed the instructions and all seems to have gone well: for instance, I do see Tmp instead of Main/Tmp. When I tested my code, I had to change a few things, e.g. cd() didn’t work and I had to change MyMainModule.solve!() to solve(), which is explained clearly also. So Let me experiment further with this. Thanks again!

Update But if I call using Plots, I get

Julia has stopped: null, SIGSEGV

and this time without a hint of workspace()

Update 2 Tried again and it worked. I’ll report back if I notice more instability.

Update 3 After some time, possibly a restart of Juno, the association with MyMainModule got changed to Main, but as it is a tiny thing in the bottom right corner of the screen I hadn’t noticed it. I started to get a bunch of errors, which I assumed were related to my edits, so I rolled back stuff, spent close to an hour looking for the problems until I got the brilliant idea of executing the module in the console, which worked without errors. At that point I realized what the problem was. So something I’ll have to keep an eye on. A hawk eye.


#15

Great. The Plots error is remarkable, as I’ve never seen anyone else report it. If it continues, the best is possibly to open an issue on Plots.
oh, and it’s RecipesBase, not PlotRecipes.


#16

Thanks, how did I get so mixed up with the names?! the power of the Google maybe and a lazy mind!


#17

In Juno, if you evaluate into the module you will update the code. So just make changes to the script, evaluate them, and use the change version directly without any workspace() or restarting silliness.

plot_solution should be a type recipe so that way plot(sol) for your solution object “just works”. Type recipes essentially define a dispatch to plot. For example, this one takes an AbstractMonteCarloSolution (N solutions of the same diffeq) and plots each one:

That’s a simple example of a type recipe. Type recipes are just a data translation. “How do I take my type and build the vectors to plot”. Another example is the type recipe for the diffeq solution type. It just takes in your solution, and has a bunch of logic to spit out what vectors you “should” be plotting:

Sometimes a type recipe can be much simpler though. If just you want to plot sol.t,sol.u from your solution, then you would do

using RecipesBase
@recipe function f(sol::MySolutionType)
  sol.t,sol.u
end

Note that here you never actually had to require Plots (or any plotting library for that matter). Instead, now the user can:

using Plots
plotly() # user chooses their favorite backend
plot(sol)

and your data transformation will allow them to directly plot what they need using the plotting backend of their choice. You can even add your own keyword arguments to the plot command as shown in the real codes, and note that all of the Plots.jl attributes “just work”.


#18

Thanks a lot Chris for taking the time. This looks very promising. I’ll have to process it, as I can’t quite get my mind around it just yet. Thanks.