Salabim

Latest version: v24.0.9

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

Scan your dependencies

Page 7 of 25

22.0.3

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

Added functionality (0)
-----------------------

AnimateMonitor is completely rebuilt to allow dynamic attributes.
From now on, *ALL* attributes can be specified as a constant, a function of t or a method witn t as
argument.
This is particularly useful for dynamic ranges, both horizontally and vertically.

Now AnimateMonitor also supports visible and over3d (both dynamic) and screen_coordinates.

it is possible to get the monitor associated with AnimateMonitor via the monitor() method.
This can be handy in writing dynamic lambda function, e.g. to get the maximum of a monitor.
(see example below)

Exam


ple:

import salabim as sim


class X(sim.Component):
def process(self):
v0 = v1 = 10
while True:
v0 = max(0, min(500, v0 + sim.Uniform(-1, 1)() * 10))
level_monitor.tally(v0)
v1 = max(0, min(500, v1 + sim.Uniform(-1, 1)() * 10))
non_level_monitor.tally(v1)
yield self.hold(1)


env = sim.Environment()
env.speed(10)

sim.AnimateText("Demonstration dynamic AnimateMonitor", fontsize=20, y=700, x=100)

level_monitor = sim.Monitor("level_monitor", level=True)
non_level_monitor = sim.Monitor("non_level_monitor")
X()
sim.AnimateMonitor(
level_monitor,
linewidth=3,
x=100,
y=100,
width=900,
height=250,
vertical_scale=lambda arg, t: min(50, 250 / arg.monitor().maximum()),
labels=lambda arg, t: [i for i in range(0, int(arg.monitor().maximum()), 10)],
horizontal_scale=lambda t: min(10, 900 / t),
)
sim.AnimateMonitor(
non_level_monitor,
linewidth=5,
x=100,
y=400,
width=900,
height=250,
vertical_scale=lambda arg, t: min(50, 250 / arg.monitor().maximum()),
labels=lambda arg, t: [i for i in range(0, int(arg.monitor().maximum()), 10)],
horizontal_scale=lambda t: min((10, 900 / t)),
)

env.animate(True)
env.run(120)

Enjoy this new feature!

Changed functionality (0)
-------------------------
The behaviour of setting/getting attributes in AnimateCombined is changed.

If you query an attribute of a combined animation object, it will now return the
value of the attribute, only if all combining animation objects (that have this attribute)
are the equal.
If they are not equal or no attribute is found at all, a ValueError will be raised.

If you set an attribute, it will set that attribute only for combining animation
objects that have indeed that attribute present. It is not an error if no
attribute is found at all.

Examples:
an0 = sim.AnimateRectangle(spec=(-10,-10,10,10))
an1 = sim.AnimateCircle(radius=5, fillcolor="white")
an2 = sim.AnimateCircle(radius=10, fillcolor="red")

an = sim.AnimateCombined([an0, an1, an2])

an.x = 5 will set x=0 for an0, an1 and an2
an.radius = 7 will set radius=7 for an1 and an2, but not an0

print(an.x) will print 5 as x==5 for an0, an1 and an2
print(an.radius)
will print 7 as radius==7 for an1 and an2 (an0 does not have a radius and is ignored)

print(an.fillcolor)
will raise a ValueError because an0, an1 and an2 do not have the same fillcolor

print(an.image)
will raise a ValueError because neither an0, an1 nor an2 have an image attribute

Changed functionality (1)
-------------------------
sim.Resource now has an initial_claimed_quantity parameter, that can be used only
for anonymous resources. If not zero, the resource starts with a quantity in it.

Example:
r = sim.Resource("r", capacity=100, initial_claimed_quantity=50, anonymous=True)

Changed functionality (2)
-------------------------
The over3d parameter of
sim.AnimateText, sim.AnimateLine, sim.AnimatePoints, sim.AnimatePolygon,
sim.AnimateImage, sim.AnimateRectangle
is now dynamic.

Bugfix (0)
-----------
There was a bug in AnimateLine, AnimateRectangle and AnimatePolygon that prevented from using as_points properly.
Fixed.

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.

Page 7 of 25

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.