Salabim

Latest version: v25.0.8

Safety actively analyzes 723400 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 10 of 28

22.0.2

==========================
Added functionality (0)
-----------------------
All methods that set a scheduled time now have a parameter cap_now:
- Environment.run
- Component.hold
- Componentactivate
- Component.request
- Component.wait
- creation of a new component

Normally, a scheduled time in the past raises a exception.
If cap_now is True, a scheduled time in the past will change that time into now. E.g.
yield self.hold(sim.Normal(2,1))
would normally raise an exception after a couple of samples. But
yield self.hold(sim.Normal(2,1), cap_now=True)
would cap the negative samples to 0, thus avoiding an exception.
Be careful using this feature as you might miss a serious problem.

It is even possible to set cap_now globaly with sim.default_cap_now(True).

And there's a context manager sim.cap_now to temporarily override the global default_cap_now:
with sim.cap_now():
yield self.hold(-1)
This will hold for a duration of 0!

The documentation has a section on this functionality, now.

Added functionality (1)
-----------------------
The ComponentGenerator() class now suppports a disturbance for iat type generators.
This can be very useful to define a recurring event (e.g. a regular arrival of a bus),
which deviates from the 'timetable'. Like
sim.ComponentGenerator(Bus, iat=60, disturbance=sim.Uniform(-1, 5))

Added functionality (2)
-----------------------
ComponentGenerator now supports any callable as the component_class.
If disturbance is specified (see above), component_class has to be a subclass of
ComponentClass, however.

Added functionality (3)
-----------------------
The function interp offers the same basic functionality as numpy.interp. In fact it uses numpy if available.
This can be very useful for animations where the location changes at certain point in time, like
AnimationRectangle((-10,-10,10,10), x=100, y=lambda t: sim.interp(t, (0,10,20,30),(100,200,500,1000)))

Added functionality (4)
-----------------------
Salabim can now optionally show times and durations as dates/timedeltas.
Therefore, sim.Environment() has a new parameter datetime0.
If datetime0 is set to True, the base date will be 1 January 1970. Alternatively, a
datetime.datatime date can be given.
Note that if no time unit is specified, and datetime0 is given, the time unit will
be set to seconds automatically.
If datetime0 is set, the methods Environment.time_to_str and Environment.duration_to_str
will return a nicely formatted date/time or duration,
like Fri 2022-04-29 20:55:06 for a date/time or 00:04:45 for a duration.
Note that these are used in the trace and in animations (to show the time).
Of course, it is still possible to override these two methods.

Furthermore, the following methods are added to salabim
- Environment.datetime_to_t
- Environment.timedelta_to_duration
- Environment.t_to_datetime
- Environment.duration_to_timedelta
- Environment.datetime0

Particulary datetime_to_t can be very useful to read information from an
external source (file, API, ...) and translated into simulation time.
In order to output these times, just use t_to_datetime with an
appropriate format.

Also, the method Environment.reset_now is now also datetime0 aware.

The documentation has a section on this functionality, now.

Added functionality (5)
-----------------------
Under Pythonista, salabim can now also run correctly in retina mode (native resolution)
on iPhones and other screens with a scale factor that is not 2.
Note that the buttons are still not shown.

Bug fix (0)
-----------
When stopping an animation from the menu (with the Stop button), the SimulationStopped exception
was incorrectly not raised in case synced is False. Fixed.

22.0.1

==========================

Added functionality (0)
-----------------------
Monitors now have an x_map method, which makes it possible to create a new monitor:
- for non level monitors: apply a function to each x-value
- for level monitors: apply a function to several x-values
Examples:
q = sim.Queue()
...
stay_in_hours = q.length_of_stay.x_map(lambda x: x * 3600)

containers20 = sim.Monitor(level=True)
containers40 = sim.Monitor(level=True)
...
teu = containers20.x_map(lambda n20, n40: (n20 + 2 * n40) / (n1 + n2), monitors=[containers40], name="teu")


Also new for this version is t_multiply for level monitors.
With this method, all t values will be multiplied with a given, positive factor.
Example:
m = sim.Monitor('m', level=True)
m.tally(1)
env.run(1)
m.tally(2)
env.run(1)
m.tally(3)
env.run(8)
print(m.bin_duration(2, 3))
m10 = m.t_multiply(10)
print(m10.bin_duration(2, 3))
will print
8.0
80.0

Added functionality (1)
-----------------------
The method Component.line_number() will return the line_number in the process where the
component will become current next.
This can be extremely useful when debugging a complex model by observing the animation.
For data components, the string "N/A" will be returned.

Added functionality (2)
------------------------
The method Environment.camera_auto_print() can be used to enable/disable printing
of the changed camera parameters on a given key.
If this parameter is True, the method camera_print will be called upon each and every camera
control key, like Up, z, Ctrl-Down, etc.
This is useful to make the specification for Environment.camera_move() method (see below).

The output of camera_print, now also includes a timestamp (as a comment), like
view(x_eye=-102.5950, y_eye=-97.3592, z_eye=100, x_center=50, y_center=50, z_center=0, field_of_view_y=50) t=0
view(x_eye=-200,y_eye=-200) t=2
view(x_eye=-100,y_eye=-100) t=5

Added functionality (3)
-----------------------
The new method Environment.camera_move() can be used to automatically follow a number of recorded
camera positions. These are usualy recorded with Environment.camera_camera_auto_print(True).
The captured output can be used as a specification to this method.
The movement will be lagged by the (simulation) time specified with lag, so a nice smooth movement
is the result, which is particularly useful for presentation quality videos.

Normally, the spec parameter will be a triple quoted string, like:
env.camera_move("""\
view(x_eye=-102.5950, y_eye=-97.3592, z_eye=100, x_center=50, y_center=50, z_center=0, field_of_view_y=50) t=0
view(x_eye=-200,y_eye=-200) t=2
view(x_eye=-100,y_eye=-100) t=5
""", lag=1.5)

Added functionality (4)
-----------------------
It is now possible to make the tkinter animation window invisible with the visible parameter of
Environment.animation():
env.animation_parameters(visible=False)
The same can be realized with Environment.visible:
env.visible(False)
With the latter method, you can also query the current status.

This functionality can be useful when doing realtime simulations with a custom GUI or similar.

Added functionality (5)
-----------------------
It is now possible to exclude certain animation objects from a video by setting
visible to "not in video". Those animation objects are still shown in the normal animation window.
E.g.
sim.AnimateText(text="this will be visible in the animation window, but not in the video", x=10, y=10, visible="not in video")

Similarly, it also possible to exclude certain animation objects from the animation
window, but leave it in the video.
E.g.
sim.AnimateText(text="this will be visible in the video, but not in the animation window", x=10, y=10, visible="only in video")

Note that this functionality does not apply to 3D animation objects (including over3d animation objects).

Added functionality (6)
-----------------------
The method Environment.is_videoing() can be used to check whether a video is being recorded.
This can be useful when running dependent on whether a video is recorded. E.g.
filename = ... if filename == "", run infinitely, otherwise, run for 5 time units.
with video(filename):
if env.is_videoing():
env.run(5)
else:
env.run(sim.inf)

Improved functionality (0)
--------------------------
The trace facility now also shows the (next) line number for passivate and standby calls.
The same holds for components that are being interrupted or resumed.

Improved functionality (1)
--------------------------
The value of a state in the trace is now printed with repr() instead of str(), so it's easier to
see the value (particularly for the null string of strings with only blanks), e.g.
32 s2 create value = ''
instead of
32 s2 create value =

Bugfix (0)
----------
A bug in Monitor.sysweight() made that Monitor.x() didn't work properly. Fixed.

Bugfix (1)
----------
The line number of an activated process that was not a generator object (i.e. without a yield) was misaligned. Fixed.

Documentation fix (0)
---------------------
In several Animation classes the text_offsetx and text_offsety parameters were incorrectly documented as
textoffsetx and textoffsety. Fixed.

22.0.0

==========================
Added functionality (0)
-----------------------
It is now possible to add a 2D overlay to a 3d animation. This overlay can be extremely useful
for showing status information, like the time. And logos and ...
Particularly videos can be much more professional and instructive.

All normal 2d animation objects are available for overlaying:
Animate, AnimateCircle, AnimateImage, AnimateLine, AnimatePolygon,
AnimatePoints, AnimateRectangle and AnimateText
Also, the AnimateMonitor and AnimateQueue support overlaying.
All these classes have an optional parameter over3d.

Note that the optional parameter defaults to False, but can be overridden with the
sim.default_override() function. On top of that, it is possible to use the
sim.over3d() context manager to temporarily override the default like,
with sim.over3d():
AnimateCircle(radius=50, x=100, y=100)
AnimateRectangle((-20, -20, 20, 20), x=100, y=100)
These two animation objects will now be shown as an overlay on the 3d animation.

For AnimateQueue, the Component.animation_objects_over3d method should specify the objects
, just like Component.animation_objects for ordinary 2d animations.
By default, this is a defined as a square (same as in ordinary 2d).

Changed functionality (0)
-------------------------
From now on, there are several ways that resource requests are honoured (specifified in Resource parameters):
honor_only_first: if True, only the first of the requesters queue will be honoured
honor_only_highest_priority: if True, only components with the priority of the first in requesters will be honoured
As both parameters are False by default, existing models will still work as before.

Changed functionality (1)
-------------------------
The way AnimateImage and Animate(image=...) handles the given image spec has been changed,
and is much more robust now.
That means that an image will not be read util really required. So, if animation is not activated,
the image file will not be opened (and could be even absent).
Also, read images from a file will be cached automatically, so it is very easy to cycle through
several images without a performance problems.
It is now possible to say
an = sim.AnimateImage(spec="a.png")
...
an.spec = "b.png"
, so no more need to use sim.spec_to_image(), although that function still exists.

Related to this is that in case no width is given, the width of the image will be
assessed as late as possible.
The method .width() of an image animation object will return None if no width is specified.
If it is required to get the actual (physical) width of a spec, there's now the function
sim.spec_to_image_width()

Changed fuctionality (2)
------------------------
To avoid confusion, it is not allowed anymore to change
fps
video_width
video_height
video_mode
video_repeat
video_pingpong
when a video is being recorded.

Changed functionality (3)
------------------------
When a simulation raised a SimulationStopped exception, a video being recorded will be closed automatically.

Added functionality (0)
-----------------------
An animation can now be stopped with Ctrl-C.

Bugfix (0)
----------
Under Pythonista, changing fonts didn't work properly in version 21.1.7. Fixed.

Bugfix (1)
----------
If Map was used in a specification of a Distribution, an attribute error was raised. Fixed.

Internal change (0)
-------------------
Salabim now uses f-strings extensively (mainly automatically converted by flynt).
This makes reading and maintaining the source easier (and arguably faster).

21.1.7

==========================
Added functionality (1)
-----------------------
During an animation, it is now possible to:
- press <space> to toggle between run and pause (with menu button shown)
,so it is not necessary to press the Menu/Go mouse button
- press - to halve the animation speed
- press + to double the animation speed
- press s to single step
this can very useful, particularly when trace is on
You will love this!

Added functionality (0)
-----------------------
Queues can now have limited capacity, by setting the capacity parameter of Queue(), e.g.
q = sim.Queue('q', capacity=5)
If a queue exceeds that capacity, a QueueFullError exception will be raised.
So, it is possible to do
try:
c.enter(q)
except sim.QueueFullError:
experienced_full += 1

Queue.capacity is a level monitor that can be changed like
q.capacity.value = 10
, so it is also possible to make a normal unrestricted queue into a queue with a
limited capacity.
q = sim.Queue('q')
...
q.capacity.value = 5
Important: if the queue contains more components than the new capacity, all
components will stay in the queue.

The methods union, intersection, difference, symmetric_diffence, and the operator +, -, ^, |, &
will not use the capacity in any way.

The methods copy and move do not copy the capacity by default, but may do so if
copy_capacity=True is given with the call.

Changed functionality (0)
-------------------------
When an animation is stopped, either by the user or an error, now a SimulationStopped exception is raised.
This makes that a simulation will not continue in that case, as it did before.

If you just want to be able to stop a run from the animation menu in a clean way, use something like
try:
env.run()
queue.print_histograms()
except sim.SimulationStopped:
pass

Changed functionality (1)
-------------------------
The s1 parameter in print_trace was always padded to a length of 10.

From now on this length is dynamically defined, although it is highly recommended that the method
always returns the same length string.

In relation to this, the Environment.time_to_str_format() method has been phased out.

The same functionality as env.time_to_str_format("{:10.4f}") can be obtained with:
sim.Enviroment.time_to_str = lambda self, t: f"{t:10.4f}"
or
class MyEnvironment(sim.Component):
def time_to_str(self, t):
return f"{t:10.4f}"
...
env = MyEnvironment()

With this change in functionality, it is possible to show the time even as a proper date/time, like
sim.Enviroment.time_to_str = lambda self, t: datetime.datetime.utcfromtimestamp(t).strftime("%Y-%m-%d %H:%M:%S")

Note that the Environment.time_to_str() method is also used to show the current time in animations.

Related to this change is a new method Environment.duration_to_str, that is used whenever a duration has
to be printed in a trace.
This method defaults to a 0.3f formatted string, but may be overridden.

Removed functionality (2)
-------------------------
The height, linecolor and linewidth parameters of AnimateButton were completely ignored
(apart from in the Pythonista implementation).
Therefore, these have been removed completely.
The documentation/docstring will be updated accordingly.

Pythonista specific improvements / bugfixes (0)
----------------------------------------------
Using one of the standard fonts now do not have to call fonts(), thus avoiding a significant delay.

AnimateSlider() now calls the action function (if any) at start up, as with the tkinter version.

The action function in AnimateSlider gets a string as parameter now instead of a float, as with the tkinter version.

Bugfix (0)
----------
A serious bug prevented animations to run properly under Pythonista. Fixed.

Bugfix (1)
----------
Bug in the interpretation of multiple states in Component.wait() fixed.

Bugfix (2)
----------
When producing an animated gif or png video, pingpong was always applied, regardless of the pingpong parameter. Fixed.

Bug fix (3)
-----------
When video_repeat was 1 (for animated GIF videos), the video was played twice on certain platforms.
Fixed.

Bug fix (4)
-----------
The maximum number of fonts that could be use in one animation was approximately 500.
From this version on, the number of fonts that can be handled is only limited by the available memory.

Speed improvement(0)
--------------------
If a font can't be located directly, the salabim and current directory are not searched recursively anymore.

Documentation update (0)
------------------------
The docstring for Environment.video() now makes clear that the
video_width
video_height
video_mode
video_repeat
video_pingpong
parameters at the time Environment.video is called are used. Any change after will be ignored and only applied to
another Environment.video call.

Documentation update (0)
------------------------
The docstring for Component.request() and Component.wait() now makes clear that the
priority parameter refers to the fail event.

21.1.6

==========================
Changed functionality (0)
-------------------------
Labels in AnimateMonitor() / Monintor.animate() are now suppressed if the
corresponding y-value is outside the 'y range'.

Changed functionality (1)
-------------------------
The default for priority in Environment.run() is now inf (was 0).
This makes that, by default, all components scheduled for the end moment will become active before
the run ends

Changed functionality (2)
-------------------------
When an_menu() was issued from a program, the simulation wasn't paused until the next tkinter tick.
From this version, the simulation will pause exactly at the current time (just prior to the next event).
This functionality is also available under Pythonista.

Added checks (0)
----------------
A call to Component.wait is now more strictly checked for errors.

Bugfix (0)
----------
In version 21.1.4 a bug was introduced that made it impossible to add audio to a video.
Fixed.

Bugfix (1)
-----------
Although State.animate was phased out already in version 2.3.0, the State.__init__ method still contained
an animation_objects parameter, that is not used anymore.
So, both the docstring, documentation and the parameter heading have been updated accordingly.

Bugfix (2)
----------
Bug in Monitor.median caused an error when interpolation was not specified. Fixed.

Bugfix (3)
----------
AnimateSlide did not observe the width and height parameters at all (apart from under Pythonista).
Fixed.

Documentation and docstring enhancement (0)
-------------------------------------------
All animation objects now have the remove() method documented.

Documentation bugfix (0)
------------------------
The default value label_anchor parameter of AnimateMonitor / Monitor.animate was
documented to be 'sw', where it should have been 'e'. Fixed.

Internal change (0)
-------------------
Check for correct interpolation in Monitor.percentile() / Monitor.median() now done at start of the method, thus being more robust.

21.1.5

==========================
Changed functionality / bug fix (0)
-----------------------------------
The Monitor.percentile method has been completely rewritten, to fix bugs and
introduce the interpolation parameter.

For non weighted monitors, the method is now exactly equivalent to the numpy percentile
function. So it is now possible to use the interpolation parameters as follows:
This optional parameter specifies the interpolation method to use when the
desired percentile lies between two data points i < j:
‘linear’: i + (j - i) * fraction, where fraction is the fractional part of the index surrounded by i and j
‘lower’: i.
‘higher’: j.
‘nearest’: i or j, whichever is nearest.
‘midpoint’: (i + j) / 2.
For weighted and level monitors the behaviour is quite different (there's no equivalent in numpy),
as only tallied values will be returned, apart from when the value is undetermined,
i.e. on change of value. In that case, the interpolation parameter will be applied as follows:
‘linear’, 'midpoint': mean of the two tallied values
‘lower’: lower tallied value
‘higher’: highed tallie value

In all cases, interpolation defaults to 'linear'.

The test_monitor.py file has been updated to test the new functionality.

Added functionality (0)
-----------------------
The Monitor.median method now also supports the interpolation parameter
(see above description of percentile)


Added functionality (1)
-----------------------
The classes
AnimateCircle, AnimateImage, AnimateLine, AnimatePolygon, AnimateRectangle, AnimateText,
Animate3dBar, Animate3dBox, Animate3dGrid, Animate3dLine, Animate3dObj, Animate3dRectangle, Animate3dSphere and
AnimateQueue
now have additional method: add_attr .

This is useful to add attribute(s) to an animation object, without having to assign the object a name and
assign the attribute(s) in seperate line(s).
So, instead of
for xx in range(10):
an = sim.AnimateRectangle(spec=lambda arg,t: (arg.xx,0,arg.xx+10,arg.xx+t*10))
an.xx = xx
we can now say
for xx in range(10):
sim.AnimateRectangle(spec=lambda arg,t: (arg.xx, 0, arg.xx + 10, arg.xx + t * 10)).add_attr(xx=xx * 20)

It is possible to assign several attributes at once, like:
sim.AnimateRectangle(spec=lambda arg,t: (arg.xx, arg.yy,arg.xx + 10,arg.xx + t * 10)).add_attr(xx=xx * 20, yy=xx * 5)
, but also like
sim.AnimateRectangle(spec=lambda arg,t: (arg.xx, arg.yy,arg.xx + 10, arg.xx + t * 10)).add_attr(xx=xx * 20).add_attr(yy=xx * 5)

The method add_attr just returns the "calling" object, thus allowing "daisy chanining".

Note that it is not allowed to add any attributes that are already defined. So
sim.AnimateRectangle(spec=(0, 0, 10, 10).add_attr(x=5)
is not allowed as x is already defined by salabim.


Added functionality (2)
-----------------------
The method env.animate() now can use '?', to enable animation, if possible.
If not possible, animation is ignored.

The method env.animate3d() now can use '?', to enable 3D-animation, if possible.
If not possible, 3D-animation is ignored.

Both functionalities are also available via env.animation_parameters().

Bug fix (0)
-----------
The offsetx and offsety parameters of all animation objects were always in screen_coordinates, even
if screen_coordinates == False. Fixed.

Documentation bug fix (0)
-------------------------
Docstring of AnimateMonitor and Monitor.animate() updated.

Bug fix (1)
-----------
Under Pythonista, 3D animation was just ignored, instead of issueing an error message
(as Pythonista does not support OpenGL). Fixed.

Page 10 of 28

© 2025 Safety CLI Cybersecurity Inc. All Rights Reserved.