Package: butterpy
ButterpySimulate starspot evolution and the corresponding lightcurves.Primary author of Python implementation:Zachary ClaytorThe code is written in both Python and Julia. See the Butterfly.jl section for the Julia documentation. The Python code can be found under thebutterpydirectory.To cite the code, please use the introductory paper byClaytor et al. (2022)and the Zenodo DOI10.5281/zenodo.4722052.Butterpy installationYou can installbutterpyusing pip. I'm hoping to have 1.0.0 on PyPI soon, but for now use this:pipinstallgit+https://github.com/zclaytor/butterpyButterpy usageSeenotebooks/surface_fig.ipynbfor general usage, but here's a quick guide to simulating a Solar-like star.importbutterpyasbpimportmatplotlib.pyplotasplt# Initialize surface. You almost never need to supply arguments.s=bp.Surface()# Emerge active regionsregions=s.emerge_regions(ndays=1000,activity_level=1,cycle_period=11,cycle_overlap=2,)# From active regions, compute spot evolution and light curvelightcurve=s.evolve_spots(incl=80,period=24.5,shear=0.2,)# Plot butterfly diagram and light curves.plot_butterfly()plt.tight_layout()s.plot_lightcurve()plt.tight_layout()You can also make animations usingSurface.animate_spots. Check the documentation for more!Butterfly.jlPrimary author of Julia implementation:Miles LucasThe Julia implementation is derived from the python work but applies Julian best practices. The Julia code can be found under thesrcdirectory. This requires Julia 1.2 or greater, and greatly benefits from the stability in multithreading found in Julia 1.3. Visit theJulia websitefor information on how to get Julia set up.Butterfly.jl installationOnce you have Julia set up, enter the REPLjuliaand set up the environmentjulia>](v1.2)pkg>dev.(v1.2)pkg><backspace>julia>usingButterflyButterfly.jl usageThe main workflow is similar to the python implementationGenerate and evolve starspotsjulia>spots=evolve()# Solar values by default for 10 year time-span3371-elementArray{Spot,1}:Spot{Float64}(25,-0.16473381557930752,0.6011891165889124,151.63266492815836,0.0)Spot{Float64}(28,-0.1513712338337426,6.279352287829287,151.63266492815836,0.0)Spot{Float64}(35,-0.1678121828423019,0.1170635115755915,250.0,0.0)Spot{Float64}(46,-0.1087039654086646,0.5784711270698818,33.833820809153174,0.0)Spot{Float64}(47,-0.1223988077838112,3.248376887285918,33.833820809153174,0.0)Spot{Float64}(56,0.16106980965050208,4.880251878214368,91.96986029286062,0.0)Spot{Float64}(56,-0.20579341905391327,4.482267038663841,33.833820809153174,0.0)⋮Spot{Float64}(3645,0.30590153485394156,3.004852147666298,151.63266492815836,0.0)Spot{Float64}(3645,-0.18449038285124816,6.089091009925041,33.833820809153174,0.0)Spot{Float64}(3646,0.18567945472506195,4.543798473242256,151.63266492815836,0.0)Spot{Float64}(3646,-0.23634723943652297,0.6475271827528074,91.96986029286062,0.0)Spot{Float64}(3648,-0.0974766691802325,4.791006457613271,33.833820809153174,0.0)Spot{Float64}(3648,0.253768420357385,5.710141733818553,33.833820809153174,0.0)Spot{Float64}(3649,0.21079744615702228,1.0139028758201174,33.833820809153174,0.0)julia>spots=evolve(butterfly=true,activity_rate=1,cycle_length=11,cycle_overlap=2,max_ave_lat=35,min_ave_lat=7,tsim=3650,tstart=0)# equivalent to aboveyou can view the docstring by pressing?and then typing inevolvelike sohelp?>evolvesearch:evolveevolve(;butterfly=true,activity_rate=1,cycle_length=11,cycle_overlap=2,max_ave_lat=35,min_ave_lat=7,tsim=3650,tstart=0)Simulatestheemergenceandevolutionofstarspots.Outputisalistofactiveregions.Parameters≡≡≡≡≡≡≡≡≡≡≡≡•butterfly=bool-havespotsdecreasefrommaxlattominlatorberandomlylocatedinlatitude•activityrate=Numberofmagneticbipoles,normalizedsuchthatfortheSun,activityrate=1.•cycle_length-lengthofcycleinyears(Sunis11)•cycle_overlap-overlapofcyclesinyears•maxavelat=maximumaveragelatitudeofspotemergence(deg)•minavelat=minimumaveragelatitutdeofemergence(deg)•tsim=howmanydaystoemergespotsfor•tstart=FirstdaytosimulatebipolesBasedonSection4ofvanBallegooijen1998,ApJ501:866andSchrijverandHarvey1994,SoPh150:1SWrittenbyJoeLlama(joe.llama@lowell.edu)V11/1/16ConvertedtoPython39/5/2017AccordingtoSchrijverandHarvey(1994),thenumberofactiveregionsemergingwithareasintherange[A,A+dA]intimeintervaldtisgivenbyn(A,t)dAdt=a(t)A^(-2)dAdt,whereAisthe"initial"bipoleareainsquaredegrees,andtisthetimeindays;a(t)variesfrom1.23atcycleminimumto10atcyclemaximum.Thebipoleareaistheareawiththe25-Gausscontourinthe"initial"state,i.e.,atthetimeofmaximumdevelopmentoftheactiveregion.Theassumedpeakfluxdensityintheinitialstateis100G,andwidth=0.4bsiz.Simulate Light CurvesStart by creating aSpotDynamicsobjectjulia>sd=SpotDynamics(spots)SpotDynamics{Float64}nspots:3370duration:3649.0inclination:0.24972224678784558ω:2.9682470272012405e-6Δω:5.936494054402481e-7equatorial_period:24.5τ_emergence:24.5τ_decay:122.5help?>SpotDynamicssearch:SpotDynamicsSpotDynamics(spots::AbstractVector{Spot};duration=maximum([s.ndayforsinspots]),alpha_med=0.0001,inclination=asin(rand()),ω=1.0,Δω=0.2,τ_decay=5.0,threshold=0.1)Acontainerforthedynamicsofstarspots.Parameters≡≡≡≡≡≡≡≡≡≡≡≡•spots-ThelistofSpotsevolvedovertime•duration-Thelengthoftheevolutiontime•alpha_med-Anactivationparameterforthemagneticflux•inclination-Inclinationofthestarfromourlineofsightinradians•ω-Rotationalvelocityofthestarinsolarunits•Δω-changeinrotationalvelocityoverthetimeinsolaruntis•τ_decay-Thedecaytimescale•threshold-Thethresholdinmagneticfluxforfilteringstarspotsto view the modulation of the star's flux at a given timestep, usemodulatejulia>df=modulate(sd,0)-3.7839717125012525e-5julia>dfs=modulate.(sd,0:0.01:1)101-elementArray{Float64,1}:-3.7839717125012525e-5-3.779490759845662e-5-3.7749334907885015e-5-3.7702998398295e-5-3.765589741966958e-5-3.760803132698725e-5-3.755939948023161e-5⋮-3.025936981252681e-5-3.014146726718377e-5-3.0022765393355793e-5-2.9903264042371397e-5-2.978296307128816e-5-2.9661862342899073e-5-2.953996172573867e-5help?>modulatesearch:modulatemodulate(::SpotDynamics,time)Modulatethefluxduestarspotsatthegiventimestepindays.we can simulate using multithreading usingsimulate. Note, you must have the environment variableJULIA_NUM_THREADSset to make use of multithreading.julia>dfs=simulate(sd,duration=365,cadence=60)8761-elementArray{Float64,1}:-3.7839717125012525e-5-3.764797288782288e-5-3.744294368105203e-5-3.7224583843915496e-5-3.6992849236707684e-5-3.674769725267416e-5-3.648908682971768e-5⋮-0.00017763548300495392-0.0001785040018698553-0.00017945659679677306-0.00018040299273987162-0.00018134308150915572-0.00018227675569909986-0.00018320390870043565help?>simulatesearch:simulatesimulate(::SpotDynamics;duration=3650,cadence=30)Simulatethelightcurvemodulationoverdurationdayseverycadenceminutes.───────────────────────────────────────────────────────simulate(::DataFrameRow;duration=3650,cadence=30)Givenarowfromadataframewithsimulationdata,willsimulatethelightcurvemodulationoverdurationdayseverycadenceminutes.───────────────────────────────────────────────────────simulate(::DataFrame;duration=3650,cadence=30)Givenafulldataframewithsimulationdata,willreturnaVectoroflightcurvemodulationsoverdurationdayseverycadenceminutes.Generating Simulation SetsUsinggenerate_simdatawe can produce a dataframe of simulation data that can be saved and passed directly tosimulatehelp?>generate_simdatasearch:generate_simdatagenerate_simdata(n::Integer)GeneratensimulationdatasetsreturnedinaDataFrame.BenchmarksIn the directorybenchthere are some benchmarks comparing Python performance to Julia. In general, Julia is ~2x faster than Python when using multithreading.