salabim 24.0.13__py3-none-any.whl → 24.0.14.post3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
salabim/salabim.py CHANGED
@@ -1,13 +1,13 @@
1
- # _ _ _ ____ _ _ ___ _ _____
2
- # ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | || | / _ \ / ||___ /
3
- # / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) || || |_ | | | | | | |_ \
4
- # \__ \| (_| || || (_| || |_) || || | | | | | / __/ |__ _| _ | |_| | _ | | ___) |
5
- # |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____| |_| (_) \___/ (_)|_||____/
1
+ # _ _ _ ____ _ _ ___ _ _ _
2
+ # ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | || | / _ \ / || || |
3
+ # / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) || || |_ | | | | | || || |_
4
+ # \__ \| (_| || || (_| || |_) || || | | | | | / __/ |__ _| _ | |_| | _ | ||__ _|
5
+ # |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____| |_| (_) \___/ (_)|_| |_|
6
6
  # discrete event simulation
7
7
  #
8
8
  # see www.salabim.org for more information, the documentation and license information
9
9
 
10
- __version__ = "24.0.13"
10
+ __version__ = "24.0.14"
11
11
 
12
12
  import heapq
13
13
  import random
@@ -9055,7 +9055,6 @@ by adding:
9055
9055
  else:
9056
9056
  return
9057
9057
 
9058
-
9059
9058
  def _trywait(self):
9060
9059
  if self.status.value == interrupted:
9061
9060
  return False
@@ -10207,7 +10206,7 @@ class Event(Component):
10207
10206
  """
10208
10207
  return self._action_taken
10209
10208
 
10210
-
10209
+
10211
10210
  class Environment:
10212
10211
  """
10213
10212
  environment object
@@ -11349,13 +11348,13 @@ class Environment:
11349
11348
 
11350
11349
  if width is not None:
11351
11350
  if self._width != width:
11352
- self._width = width
11351
+ self._width = int(width)
11353
11352
  frame_changed = True
11354
11353
  width_changed = True
11355
11354
 
11356
11355
  if height is not None:
11357
11356
  if self._height != height:
11358
- self._height = height
11357
+ self._height = int(height)
11359
11358
  frame_changed = True
11360
11359
  height_changed = True
11361
11360
 
@@ -11804,7 +11803,8 @@ class Environment:
11804
11803
  for ao in an_objects:
11805
11804
  ao.make_pil_image(self.t())
11806
11805
  if ao._image_visible and (include_topleft or not ao.getattr("in_topleft", False)):
11807
- image.paste(ao._image, (int(ao._image_x), int(self._height - ao._image_y - ao._image.size[1])), ao._image)
11806
+ image.paste(ao._image, (int(ao._image_x), int(self._height - ao._image_y - ao._image.size[1])),ao._image.convert("RGBA"),)
11807
+
11808
11808
 
11809
11809
  return image.convert(mode)
11810
11810
 
@@ -13201,7 +13201,7 @@ class Environment:
13201
13201
  if co is None:
13202
13202
  if len(g.canvas_objects) >= self._maximum_number_of_bitmaps:
13203
13203
  if overflow_image is None:
13204
- overflow_image = Image.new("RGBA", (self._width, self._height), (0, 0, 0, 0))
13204
+ overflow_image = Image.new("RGBA", (int(self._width), int(self._height)), (0, 0, 0, 0))
13205
13205
  overflow_image.paste(ao._image, (int(ao._image_x), int(self._height - ao._image_y - ao._image.size[1])), ao._image)
13206
13206
  ao.canvas_object = None
13207
13207
  else:
@@ -15426,10 +15426,20 @@ class Animate2dBase(DynamicClass):
15426
15426
  spec = self.image(t)
15427
15427
  image_container = ImageContainer(spec)
15428
15428
  width = self.width(t)
15429
+ height = self.height(t)
15430
+
15429
15431
  if width is None:
15430
- width = image_container.images[0].size[0]
15432
+ if height is None:
15433
+ width = image_container.images[0].size[0]
15434
+ height = image_container.images[0].size[1]
15435
+ else:
15436
+ width = height * image_container.images[0].size[0] / image_container.images[0].size[1]
15437
+ else:
15438
+ if height is None:
15439
+ height = width * image_container.images[0].size[1] / image_container.images[0].size[0]
15440
+ else:
15441
+ ...
15431
15442
 
15432
- height = width * image_container.images[0].size[1] / image_container.images[0].size[0]
15433
15443
  if not self.screen_coordinates:
15434
15444
  width *= self.env._scale
15435
15445
  height *= self.env._scale
@@ -15448,7 +15458,6 @@ class Animate2dBase(DynamicClass):
15448
15458
  offsety = offsety * self.env._scale
15449
15459
 
15450
15460
  alpha = int(self.alpha(t))
15451
-
15452
15461
  image, id = image_container.get_image(
15453
15462
  (t - self.animation_start(t)) * self.animation_speed(t),
15454
15463
  repeat=self.animation_repeat(t),
@@ -15456,6 +15465,7 @@ class Animate2dBase(DynamicClass):
15456
15465
  t_from=self.animation_from(t),
15457
15466
  t_to=self.animation_to(t),
15458
15467
  )
15468
+
15459
15469
  self._image_ident = (spec, id, width, height, angle, alpha, flip_horizontal, flip_vertical)
15460
15470
 
15461
15471
  if self._image_ident != self._image_ident_prev:
@@ -15736,6 +15746,9 @@ class AnimateClassic(Animate2dBase):
15736
15746
  def width(self, t):
15737
15747
  return self.master.width(t)
15738
15748
 
15749
+ def height(self, t):
15750
+ return self.master.height(t)
15751
+
15739
15752
  def anchor(self, t):
15740
15753
  return self.master.anchor(t)
15741
15754
 
@@ -15963,6 +15976,11 @@ class Animate:
15963
15976
 
15964
15977
  if omitted or None, no scaling
15965
15978
 
15979
+ height0 : float
15980
+ width of the image to be displayed at time t0
15981
+
15982
+ if omitted or None, no scaling
15983
+
15966
15984
  t1 : float
15967
15985
  time of end of the animation (default inf)
15968
15986
 
@@ -16031,6 +16049,9 @@ class Animate:
16031
16049
  width1 : float
16032
16050
  width of the image to be displayed at time t1 (default: width0)
16033
16051
 
16052
+ height1 : float
16053
+ width of the image to be displayed at time t1 (default: height0)
16054
+
16034
16055
  over3d : bool
16035
16056
  if True, this object will be rendered to the OpenGL window
16036
16057
 
@@ -16099,6 +16120,7 @@ class Animate:
16099
16120
  font -
16100
16121
  fontsize0,fontsize1 -
16101
16122
  width0,width1 -
16123
+ height0,height1 -
16102
16124
  ====================== ========= ========= ========= ========= ========= =========
16103
16125
  """
16104
16126
 
@@ -16134,6 +16156,7 @@ class Animate:
16134
16156
  alpha0: float = 255,
16135
16157
  fontsize0: float = 20,
16136
16158
  width0: float = None,
16159
+ height0: float = None,
16137
16160
  t1: float = None,
16138
16161
  x1: float = None,
16139
16162
  y1: float = None,
@@ -16152,6 +16175,7 @@ class Animate:
16152
16175
  alpha1: float = None,
16153
16176
  fontsize1: float = None,
16154
16177
  width1: float = None,
16178
+ height1: float = None,
16155
16179
  xy_anchor: str = "",
16156
16180
  over3d: bool = None,
16157
16181
  flip_horizontal: bool = False,
@@ -16198,10 +16222,12 @@ class Animate:
16198
16222
  self.text0 = text
16199
16223
 
16200
16224
  if image is None:
16201
- self.width0 = 0 # just to be able to interpolate
16225
+ self.width0 = 0 # just to be able to interpolat
16226
+ self.height0 = 0
16202
16227
  else:
16203
16228
  self.image0 = image
16204
16229
  self.width0 = width0 # None means original size
16230
+ self.height0 = height0
16205
16231
 
16206
16232
  self.as_points0 = as_points
16207
16233
  self.font0 = font
@@ -16263,7 +16289,7 @@ class Animate:
16263
16289
  self.alpha1 = self.alpha0 if alpha1 is None else alpha1
16264
16290
  self.fontsize1 = self.fontsize0 if fontsize1 is None else fontsize1
16265
16291
  self.width1 = self.width0 if width1 is None else width1
16266
-
16292
+ self.height1 = self.height0 if height1 is None else height1
16267
16293
  self.t1 = inf if t1 is None else t1
16268
16294
  if self.env._animate_debug:
16269
16295
  self.caller = self.env._frame_to_lineno(_get_caller_frame(), add_filename=True)
@@ -16322,6 +16348,7 @@ class Animate:
16322
16348
  alpha0=None,
16323
16349
  fontsize0=None,
16324
16350
  width0=None,
16351
+ height0=None,
16325
16352
  xy_anchor1=None,
16326
16353
  as_points=None,
16327
16354
  t1=None,
@@ -16342,6 +16369,7 @@ class Animate:
16342
16369
  alpha1=None,
16343
16370
  fontsize1=None,
16344
16371
  width1=None,
16372
+ height1=None,
16345
16373
  flip_horizontal=None,
16346
16374
  flip_vertical=None,
16347
16375
  animation_start=None,
@@ -16494,6 +16522,11 @@ class Animate:
16494
16522
 
16495
16523
  if None, the original width of the image will be used
16496
16524
 
16525
+ height0 : float
16526
+ height of the image to be displayed at time t0 (default see below)
16527
+
16528
+ if None, the original height of the image will be used
16529
+
16497
16530
  t1 : float
16498
16531
  time of end of the animation (default: inf)
16499
16532
 
@@ -16560,6 +16593,8 @@ class Animate:
16560
16593
  width1 : float
16561
16594
  width of the image to be displayed at time t1 (default: width0)
16562
16595
 
16596
+ height1 : float
16597
+ height of the image to be displayed at time t1 (default: height0)
16563
16598
 
16564
16599
  Note
16565
16600
  ----
@@ -16595,6 +16630,8 @@ class Animate:
16595
16630
  self.max_lines0 = max_lines
16596
16631
 
16597
16632
  self.width0 = self.width() if width0 is None else width0
16633
+ self.height0 = self.height() if height0 is None else height0
16634
+
16598
16635
  if image is not None:
16599
16636
  self.image0 = image
16600
16637
 
@@ -16641,6 +16678,7 @@ class Animate:
16641
16678
  self.alpha1 = self.alpha0 if alpha1 is None else alpha1
16642
16679
  self.fontsize1 = self.fontsize0 if fontsize1 is None else fontsize1
16643
16680
  self.width1 = self.width0 if width1 is None else width1
16681
+ self.height1 = self.height0 if height1 is None else height1
16644
16682
  self.xy_anchor1 = self.xy_anchor0 if xy_anchor1 is None else xy_anchor1
16645
16683
 
16646
16684
  self.t1 = inf if t1 is None else t1
@@ -16938,7 +16976,7 @@ class Animate:
16938
16976
 
16939
16977
  def width(self, t=None):
16940
16978
  """
16941
- width position of an animated image object. May be overridden.
16979
+ width of an animated image object. May be overridden.
16942
16980
 
16943
16981
  Parameters
16944
16982
  ----------
@@ -16963,6 +17001,33 @@ class Animate:
16963
17001
 
16964
17002
  return interpolate((self.env._now if t is None else t), self.t0, self.t1, width0, width1)
16965
17003
 
17004
+ def height(self, t=None):
17005
+ """
17006
+ height of an animated image object. May be overridden.
17007
+
17008
+ Parameters
17009
+ ----------
17010
+ t : float
17011
+ current time
17012
+
17013
+ Returns
17014
+ -------
17015
+ height : float
17016
+ default behaviour: linear interpolation between self.height0 and self.height1
17017
+
17018
+ if None, the original height of the image will be used
17019
+ """
17020
+ height0 = self.height0
17021
+ height1 = self.height1
17022
+ if height0 is None and height1 is None:
17023
+ return None
17024
+ if height0 is None:
17025
+ height0 = ImageContainer(self.image0).images[0].size[0]
17026
+ if height1 is None:
17027
+ height1 = ImageContainer(self.image1).images[0].size[0]
17028
+
17029
+ return interpolate((self.env._now if t is None else t), self.t0, self.t1, height0, height1)
17030
+
16966
17031
  def fontsize(self, t=None):
16967
17032
  """
16968
17033
  fontsize of an animate object. May be overridden.
@@ -19656,6 +19721,8 @@ class AnimateImage(Animate2dBase):
19656
19721
  width : float
19657
19722
  width of the image (default: None = no scaling)
19658
19723
 
19724
+ heighth : float
19725
+ height of the image (default: None = no scaling)
19659
19726
 
19660
19727
  text : str, tuple or list
19661
19728
  the text to be displayed
@@ -19791,6 +19858,7 @@ class AnimateImage(Animate2dBase):
19791
19858
  x: Union[float, Callable] = None,
19792
19859
  y: Union[float, Callable] = None,
19793
19860
  width: Union[float, Callable] = None,
19861
+ height: Union[float, Callable] = None,
19794
19862
  text: Union[str, Callable] = None,
19795
19863
  fontsize: Union[float, Callable] = None,
19796
19864
  textcolor: Union[ColorType, Callable] = None,
@@ -19833,6 +19901,7 @@ class AnimateImage(Animate2dBase):
19833
19901
  x=0,
19834
19902
  y=0,
19835
19903
  width=None,
19904
+ height=None,
19836
19905
  text="",
19837
19906
  fontsize=15,
19838
19907
  textcolor="bg",
@@ -19915,10 +19984,10 @@ class ComponentGenerator(Component):
19915
19984
 
19916
19985
  Parameters
19917
19986
  ----------
19918
- component_class : callable, usually a subclass of Component or Pdf or Cdf distribution
19987
+ component_class : callable, usually a subclass of Component or Pdf/Pmf or Cdf distribution
19919
19988
  the type of components to be generated
19920
19989
 
19921
- in case of a distribution, the Pdf or Cdf should return a callable
19990
+ in case of a distribution, the Pdf/Pmf or Cdf should return a callable
19922
19991
 
19923
19992
  generator_name : str
19924
19993
  name of the component generator.
@@ -20478,7 +20547,7 @@ class _Distribution:
20478
20547
  If, after number_of_tries retries, the sampled value is still not within the given bounds,
20479
20548
  fail_value will be returned
20480
20549
 
20481
- Samples that cannot be converted (only possible with Pdf and CumPdf) to float
20550
+ Samples that cannot be converted (only possible with /Pmf and CumPdf/CumPmf) to float
20482
20551
  are assumed to be within the bounds.
20483
20552
  """
20484
20553
  return Bounded(self, lowerbound, upperbound, fail_value, number_of_retries, include_lowerbound, include_upperbound).sample()
@@ -20718,7 +20787,7 @@ class Bounded(_Distribution):
20718
20787
  If, after number_of_tries retries, the sampled value is still not within the given bounds,
20719
20788
  fail_value will be returned
20720
20789
 
20721
- Samples that cannot be converted to float (only possible with Pdf and CumPdf)
20790
+ Samples that cannot be converted to float (only possible with Pdf/Pmf and CumPdf)
20722
20791
  are assumed to be within the bounds.
20723
20792
  """
20724
20793
 
@@ -22214,6 +22283,9 @@ class Pdf(_Distribution):
22214
22283
 
22215
22284
  If it is a salabim distribution, not the distribution,
22216
22285
  but a sample will be returned when calling sample.
22286
+
22287
+
22288
+ This method is also available under the name Pmf
22217
22289
  """
22218
22290
 
22219
22291
  def __init__(self, spec: Union[Iterable, Dict], probabilities=None, time_unit: str = None, randomstream: Any = None, env: "Environment" = None):
@@ -22358,9 +22430,151 @@ class Pdf(_Distribution):
22358
22430
  return self._mean
22359
22431
 
22360
22432
 
22433
+ class Pmf(Pdf):
22434
+ """
22435
+ Probability mass function
22436
+
22437
+ Parameters
22438
+ ----------
22439
+ spec : list, tuple or dict
22440
+ either
22441
+
22442
+ - if no probabilities specified:
22443
+
22444
+ list/tuple with x-values and corresponding probability
22445
+ dict where the keys are re x-values and the values are probabilities
22446
+ (x0, p0, x1, p1, ...xn,pn)
22447
+
22448
+ - if probabilities is specified:
22449
+
22450
+ list with x-values
22451
+
22452
+ probabilities : iterable or float
22453
+ if omitted, spec contains the probabilities
22454
+
22455
+ the iterable (p0, p1, ...pn) contains the probabilities of the corresponding
22456
+ x-values from spec.
22457
+
22458
+ alternatively, if a float is given (e.g. 1), all x-values
22459
+ have equal probability. The value is not important.
22460
+
22461
+ time_unit : str
22462
+ specifies the time unit
22463
+
22464
+ must be one of "years", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds"
22465
+
22466
+ default : no conversion
22467
+
22468
+
22469
+ randomstream : randomstream
22470
+ if omitted, random will be used
22471
+
22472
+ if used as random.Random(12299)
22473
+ it assigns a new stream with the specified seed
22474
+
22475
+ env : Environment
22476
+ environment where the distribution is defined
22477
+
22478
+ if omitted, default_env will be used
22479
+
22480
+ Note
22481
+ ----
22482
+ p0+p1=...+pn>0
22483
+
22484
+ all densities are auto scaled according to the sum of p0 to pn,
22485
+ so no need to have p0 to pn add up to 1 or 100.
22486
+
22487
+ The x-values can be any type.
22488
+
22489
+ If it is a salabim distribution, not the distribution,
22490
+ but a sample will be returned when calling sample.
22491
+
22492
+ This method is also available under the name Pdf
22493
+
22494
+ """
22495
+
22496
+ def __repr__(self):
22497
+ return "Pmf"
22498
+
22499
+ def print_info(self, as_str: bool = False, file: TextIO = None) -> str:
22500
+ """
22501
+ prints information about the distribution
22502
+
22503
+ Parameters
22504
+ ----------
22505
+ as_str: bool
22506
+ if False (default), print the info
22507
+ if True, return a string containing the info
22508
+
22509
+ file: file
22510
+ if None(default), all output is directed to stdout
22511
+
22512
+ otherwise, the output is directed to the file
22513
+
22514
+ Returns
22515
+ -------
22516
+ info (if as_str is True) : str
22517
+ """
22518
+ result = []
22519
+ result.append("Pmf distribution " + hex(id(self)))
22520
+ result.append(" randomstream=" + hex(id(self.randomstream)))
22521
+ return return_or_print(result, as_str, file)
22522
+
22523
+ def sample(self, n: int = None) -> Any:
22524
+ """
22525
+ Parameters
22526
+ ----------
22527
+ n : number of samples : int
22528
+ if not specified, specifies just return one sample, as usual
22529
+
22530
+ if specified, return a list of n sampled values from the distribution without replacement.
22531
+ This requires that all probabilities are equal.
22532
+
22533
+ If n > number of values in the Pmf distribution, n is assumed to be the number of values
22534
+ in the distribution.
22535
+
22536
+ If a sampled value is a distribution, a sample from that distribution will be returned.
22537
+
22538
+ Returns
22539
+ -------
22540
+ Sample of the distribution : any (usually float) or list
22541
+ In case n is specified, returns a list of n values
22542
+
22543
+ """
22544
+ if self.supports_n:
22545
+ if n is None:
22546
+ return self.randomstream.sample(self._x, 1)[0]
22547
+ else:
22548
+ if n < 0:
22549
+ raise ValueError("n < 0")
22550
+ n = min(n, len(self._x))
22551
+ xs = self.randomstream.sample(self._x, n)
22552
+ return [x.sample() if isinstance(x, _Distribution) else x for x in xs]
22553
+ else:
22554
+ if n is None:
22555
+ r = self.randomstream.random()
22556
+ for cum, x in zip([0] + self._cum, [0] + self._x):
22557
+ if r <= cum:
22558
+ if isinstance(x, _Distribution):
22559
+ return x.sample()
22560
+ return x
22561
+ else:
22562
+ raise ValueError("not all probabilities are the same")
22563
+
22564
+ def mean(self) -> float:
22565
+ """
22566
+ Returns
22567
+ -------
22568
+ mean of the distribution : float
22569
+ if the mean can't be calculated (if not all x-values are scalars or distributions),
22570
+ nan will be returned.
22571
+ """
22572
+ return self._mean
22573
+
22574
+
22361
22575
  class CumPdf(_Distribution):
22362
22576
  """
22363
- Cumulative Probability distribution function
22577
+ Cumulative Probability mass function
22364
22578
 
22365
22579
  Parameters
22366
22580
  ----------
@@ -22413,6 +22627,8 @@ class CumPdf(_Distribution):
22413
22627
 
22414
22628
  If it is a salabim distribution, not the distribution,
22415
22629
  but a sample will be returned when calling sample.
22630
+
22631
+ This method is also available under the name CumPmf
22416
22632
  """
22417
22633
 
22418
22634
  def __init__(
@@ -22528,6 +22744,116 @@ class CumPdf(_Distribution):
22528
22744
  return self._mean
22529
22745
 
22530
22746
 
22747
+ class CumPmf(CumPdf):
22748
+ """
22749
+ Cumulative Probability mass function
22750
+
22751
+ Parameters
22752
+ ----------
22753
+ spec : list or tuple
22754
+ either
22755
+
22756
+ - if no cumprobabilities specified:
22757
+
22758
+ list with x-values and corresponding cumulative probability
22759
+ (x0, p0, x1, p1, ...xn,pn)
22760
+
22761
+ - if cumprobabilities is specified:
22762
+
22763
+ list with x-values
22764
+
22765
+ cumprobabilities : list, tuple or float
22766
+ if omitted, spec contains the probabilities
22767
+
22768
+ the list (p0, p1, ...pn) contains the cumulative probabilities of the corresponding
22769
+ x-values from spec.
22770
+
22771
+
22772
+ time_unit : str
22773
+ specifies the time unit
22774
+
22775
+ must be one of "years", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds"
22776
+
22777
+ default : no conversion
22778
+
22779
+
22780
+ randomstream : randomstream
22781
+ if omitted, random will be used
22782
+
22783
+ if used as random.Random(12299)
22784
+ it assigns a new stream with the specified seed
22785
+
22786
+ env : Environment
22787
+ environment where the distribution is defined
22788
+
22789
+ if omitted, default_env will be used
22790
+
22791
+ Note
22792
+ ----
22793
+ p0<=p1<=..pn>0
22794
+
22795
+ all densities are auto scaled according to pn,
22796
+ so no need to have pn be 1 or 100.
22797
+
22798
+ The x-values can be any type.
22799
+
22800
+ If it is a salabim distribution, not the distribution,
22801
+ but a sample will be returned when calling sample.
22802
+
22803
+ This method is also available under the name CumPdf
22804
+ """
22805
+
22806
+ def __repr__(self):
22807
+ return "CumPmf"
22808
+
22809
+ def print_info(self, as_str: bool = False, file: TextIO = None) -> str:
22810
+ """
22811
+ prints information about the distribution
22812
+
22813
+ Parameters
22814
+ ----------
22815
+ as_str: bool
22816
+ if False (default), print the info
22817
+ if True, return a string containing the info
22818
+
22819
+ file: file
22820
+ if None(default), all output is directed to stdout
22821
+
22822
+ otherwise, the output is directed to the file
22823
+
22824
+ Returns
22825
+ -------
22826
+ info (if as_str is True) : str
22827
+ """
22828
+ result = []
22829
+ result.append("CumPmf distribution " + hex(id(self)))
22830
+ result.append(" randomstream=" + hex(id(self.randomstream)))
22831
+ return return_or_print(result, as_str, file)
22832
+
22833
+ def sample(self) -> Any:
22834
+ """
22835
+ Returns
22836
+ -------
22837
+ Sample of the distribution : any (usually float)
22838
+ """
22839
+ r = self.randomstream.random()
22840
+ for cum, x in zip([0] + self._cum, [0] + self._x):
22841
+ if r <= cum:
22842
+ if isinstance(x, _Distribution):
22843
+ return x.sample()
22844
+ return x
22845
+
22846
+ def mean(self) -> float:
22847
+ """
22848
+ Returns
22849
+ -------
22850
+ mean of the distribution : float
22851
+ if the mean can't be calculated (if not all x-values are scalars or distributions),
22852
+ nan will be returned.
22853
+ """
22854
+ return self._mean
22855
+
22856
+
22531
22857
  class External(_Distribution):
22532
22858
  """
22533
22859
  External distribution function
@@ -24127,7 +24453,7 @@ class _APNG:
24127
24453
 
24128
24454
  def to_bytes(self):
24129
24455
  CHUNK_BEFORE_IDAT = {"cHRM", "gAMA", "iCCP", "sBIT", "sRGB", "bKGD", "hIST", "tRNS", "pHYs", "sPLT", "tIME", "PLTE"}
24130
- PNG_SIGN = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
24456
+ PNG_SIGN = b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"
24131
24457
  out = [PNG_SIGN]
24132
24458
  other_chunks = []
24133
24459
  seq = 0
@@ -26601,8 +26927,8 @@ def getfont(fontname, fontsize):
26601
26927
  return getfont.lookup[(fontname, fontsize)]
26602
26928
  else:
26603
26929
  getfont.lookup = {}
26604
- if fontname=="":
26605
- a=1
26930
+ if fontname == "":
26931
+ a = 1
26606
26932
  if isinstance(fontname, str):
26607
26933
  fontlist1 = [fontname]
26608
26934
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: salabim
3
- Version: 24.0.13
3
+ Version: 24.0.14.post3
4
4
  Summary: salabim - discrete event simulation in Python
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://salabim.org
@@ -0,0 +1,10 @@
1
+ salabim/DejaVuSansMono.ttf,sha256=Z_oIXp5yp1Zaw2y2p3vaxwHhjHpG0MFbmwhxSh4aIEI,335068
2
+ salabim/LICENSE.txt,sha256=qHlBa-POyexatCxDTjSKMlYtkBFQDn9lu-YV_1L6V0U,1106
3
+ salabim/__init__.py,sha256=r7qPLvlmX0dkZDyjuTo8Jo3ex3sD1L4pmK6K5ib9vyw,56
4
+ salabim/calibri.ttf,sha256=RWpf8Uo31RfvGGNaSt9-2sXSuN87AVE_NFMRsV3LhBk,1330156
5
+ salabim/mplus-1m-regular.ttf,sha256=EuFHr90BJjuAn_r5MleJFN-WfkeWJ4tf7DweI5zr8tU,289812
6
+ salabim/salabim.py,sha256=LkXx4KGzg9FaYfe4NUBb2Zm2Iy4v1B2kyHks7cwsWoI,1113664
7
+ salabim-24.0.14.post3.dist-info/METADATA,sha256=4yHEwkcBMUAj2CtFsi3y4s7zkJTzSvLkkm0h3g6vgiI,3456
8
+ salabim-24.0.14.post3.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
9
+ salabim-24.0.14.post3.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
10
+ salabim-24.0.14.post3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,10 +0,0 @@
1
- salabim/DejaVuSansMono.ttf,sha256=Z_oIXp5yp1Zaw2y2p3vaxwHhjHpG0MFbmwhxSh4aIEI,335068
2
- salabim/LICENSE.txt,sha256=qHlBa-POyexatCxDTjSKMlYtkBFQDn9lu-YV_1L6V0U,1106
3
- salabim/__init__.py,sha256=r7qPLvlmX0dkZDyjuTo8Jo3ex3sD1L4pmK6K5ib9vyw,56
4
- salabim/calibri.ttf,sha256=RWpf8Uo31RfvGGNaSt9-2sXSuN87AVE_NFMRsV3LhBk,1330156
5
- salabim/mplus-1m-regular.ttf,sha256=EuFHr90BJjuAn_r5MleJFN-WfkeWJ4tf7DweI5zr8tU,289812
6
- salabim/salabim.py,sha256=NzhLkqRi8niqF9eQQPZRxJueQBROP0084q6qHrY6Qzc,1103953
7
- salabim-24.0.13.dist-info/METADATA,sha256=-xWemNdEOZ-EbstXw49IqGKhr97mg85QxyuDLa2LtGA,3450
8
- salabim-24.0.13.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
9
- salabim-24.0.13.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
10
- salabim-24.0.13.dist-info/RECORD,,