femagtools 1.8.3__py3-none-any.whl → 1.8.5__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.
@@ -11,9 +11,10 @@ from .. import model
11
11
  from .. import utils
12
12
  from .. import windings
13
13
  from .. import femag
14
- from scipy.interpolate import RegularGridInterpolator, interp1d, RectBivariateSpline
14
+ from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectBivariateSpline
15
15
  from scipy.integrate import quad
16
16
  import copy
17
+ from matplotlib.colors import to_rgb
17
18
 
18
19
  logger = logging.getLogger(__name__)
19
20
 
@@ -58,7 +59,7 @@ def _integrate(radius, pos, val):
58
59
 
59
60
 
60
61
  def _integrate1d(radius, val):
61
- interp = interp1d(radius, val)
62
+ interp = make_interp_spline(radius, val, k=1)
62
63
  def func(x):
63
64
  return interp((x))
64
65
  return quad(func, radius[0], radius[-1])[0]
@@ -598,6 +599,280 @@ def _get_copper_losses(scale_factor, bch):
598
599
  return 0 # noload calc has no winding losses
599
600
 
600
601
 
602
+ def _set_plot_attributes(ax):
603
+ ax.set_aspect('equal')
604
+ for loc, spine in ax.spines.items():
605
+ spine.set_color('none') # don't draw spine
606
+ ax.yaxis.set_ticks([])
607
+ ax.xaxis.set_ticks([])
608
+
609
+
610
+ def _get_colors(colors, delta):
611
+ if delta == 0.0:
612
+ return colors
613
+ new_colors = []
614
+ for col in colors:
615
+ rgb = to_rgb(col)
616
+ r, g, b = rgb
617
+ col = (max(0.0, min(r+delta, 1.0)),
618
+ max(0.0, min(g+delta, 1.0)),
619
+ max(0.0, min(b+delta, 1.0)))
620
+ new_colors.append(col)
621
+ return new_colors
622
+
623
+
624
+ def _draw_vertical_magnets(ax,
625
+ poles,
626
+ xr, yr,
627
+ Rr,
628
+ xoff, yoff,
629
+ delta=0.0):
630
+ color = ['green', 'red']
631
+ color = _get_colors(color, delta)
632
+ for i in range(poles):
633
+ ax.fill(xr+xoff, yr+yoff,
634
+ facecolor=color[i%2], edgecolor=color[i%2])
635
+ xr, yr = np.dot(Rr, [xr, yr])
636
+ return
637
+
638
+
639
+ def _draw_vertical_slots(ax,
640
+ Q,
641
+ r,
642
+ alpha,
643
+ xoff, yoff,
644
+ delta=0.0):
645
+ color = ['skyblue', 'blue']
646
+ color = _get_colors(color, delta)
647
+ taus = 2*np.pi/Q
648
+ for n in range(Q):
649
+ beta = np.array([[n*taus+alpha[0], (n+1)*taus-alpha[0]],
650
+ [(n+1)*taus-alpha[1], n*taus+alpha[1]]])
651
+ ax.fill(np.hstack((r * np.cos(beta[0, 0]),
652
+ (r[::-1] * np.cos(beta[0, 1]))))+xoff,
653
+ np.hstack((r * np.sin(beta[0, 0]),
654
+ (r[::-1] * np.sin(beta[0, 1]))))+yoff,
655
+ facecolor=color[0], edgecolor=color[0])
656
+
657
+
658
+ def vertical_plot(machine, ax):
659
+ """plots afpm stator and rotor (vertical section)
660
+ Args:
661
+ dy1, dy1: float outer, inner diameter
662
+ rel_magn_width: float rel magnet width 0..1
663
+ Q: number of stator slots
664
+ poles: number of poles
665
+ slot_width: width of stator slot
666
+ """
667
+ logger.debug("begin of vertical_plot()")
668
+
669
+ model_type = machine['afmtype'][0:4]
670
+ dy1 = machine['outer_diam']*1e3
671
+ dy2 = machine['inner_diam']*1e3
672
+ rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
673
+ Q = machine['stator']['num_slots']
674
+ slot_width = machine['stator']['afm_stator']['slot_width']*1e3
675
+ poles = machine['poles']
676
+
677
+ # prepare Magnets
678
+ theta = np.linspace(np.pi/poles*(1-rel_magn_width),
679
+ np.pi/poles*(1+rel_magn_width),
680
+ 10)
681
+ xr = np.concatenate((dy1/2 * np.cos(theta), dy2/2 * np.cos(theta[::-1])))
682
+ yr = np.concatenate((dy1/2 * np.sin(theta), dy2/2 * np.sin(theta[::-1])))
683
+ rtheta = 2*np.pi/poles
684
+ Rr = np.array([
685
+ [np.cos(rtheta), -np.sin(rtheta)],
686
+ [np.sin(rtheta), np.cos(rtheta)]
687
+ ])
688
+
689
+ # prepare Slots
690
+ taus = 2*np.pi/Q
691
+ r = np.array([dy2/2, dy1/2])
692
+ alpha = np.arctan2(slot_width/2, r)
693
+
694
+ yoff = 0.0
695
+ xoff = 0.0
696
+ y_shift = -2
697
+ x_shift = dy1-dy2
698
+ ma_delta = 0.0 # color
699
+ sl_delta = 0.0 # color
700
+
701
+ # Draw
702
+ if model_type in ("S1R2"): # 2 rotor
703
+ _draw_vertical_magnets(ax, poles, xr, yr, Rr, xoff, yoff, delta=-0.1)
704
+ yoff += y_shift
705
+ xoff += x_shift
706
+
707
+ if model_type in ("S2R1"): # 2 stator
708
+ sl_delta = -0.1
709
+
710
+ _draw_vertical_slots(ax, Q, r, alpha, xoff, yoff, delta=sl_delta)
711
+ yoff += y_shift
712
+ xoff += x_shift
713
+
714
+ if model_type in ("S1R2"): # 2 rotor
715
+ ma_delta = 0.1
716
+
717
+ _draw_vertical_magnets(ax, poles, xr, yr, Rr, xoff, yoff, delta=ma_delta)
718
+ yoff += y_shift
719
+ xoff += x_shift
720
+
721
+ if model_type in ("S2R1"): # 2 stator
722
+ sl_delta = 0.0
723
+ _draw_vertical_slots(ax, Q, r, alpha, xoff, yoff, delta=sl_delta)
724
+
725
+ _set_plot_attributes(ax)
726
+ logger.debug("end of vertical_plot()")
727
+
728
+
729
+ IRON_NO = 0
730
+ IRON_UP = 1
731
+ IRON_DOWN = 2
732
+
733
+ def _draw_horizontal_magnets(ax,
734
+ poles,
735
+ magn_height,
736
+ magn_width,
737
+ yoke_height,
738
+ Q,
739
+ g,
740
+ taus,
741
+ dy2,
742
+ yoff=0.0,
743
+ iron=IRON_NO
744
+ ):
745
+ color = ['green', 'red']
746
+ xy = (0, Q//g*taus, Q//g*taus, 0)
747
+
748
+ if iron == IRON_UP:
749
+ yy = (yoff-yoke_height,
750
+ yoff-yoke_height,
751
+ yoff,
752
+ yoff)
753
+ yoff -= yoke_height
754
+ ax.fill(xy, yy, color='skyblue')
755
+
756
+ taum = dy2*np.pi/poles
757
+ ym = np.array([yoff-magn_height,
758
+ yoff-magn_height,
759
+ yoff,
760
+ yoff])
761
+ yoff -= magn_height
762
+
763
+ for n in range(poles//g):
764
+ xl = taum*n + taum*(1 - magn_width)
765
+ xr = taum*(n + 1) - taum*(1 - magn_width)
766
+ xm = (xl, xr, xr, xl)
767
+ ax.fill(xm, ym, color=color[n%2])
768
+
769
+ if iron == IRON_DOWN:
770
+ yy = (yoff-yoke_height,
771
+ yoff-yoke_height,
772
+ yoff,
773
+ yoff)
774
+ yoff -= yoke_height
775
+ ax.fill(xy, yy, color='skyblue')
776
+ return yoff
777
+
778
+
779
+ TOOTH_UP = 0
780
+ TOOTH_DOWN = 1
781
+ TOOTH_ONLY = 2
782
+
783
+
784
+ def _draw_horizontal_slots(ax,
785
+ slot_height, slot_width, yoke_height,
786
+ Q, g, taus,
787
+ yoff=0.0,
788
+ tooth=TOOTH_DOWN):
789
+ if not tooth == TOOTH_ONLY:
790
+ xx = (0, Q//g*taus, Q//g*taus, 0)
791
+ if tooth == TOOTH_DOWN:
792
+ yy = (yoff-yoke_height,
793
+ yoff-yoke_height,
794
+ yoff,
795
+ yoff)
796
+ else:
797
+ yy = (yoff-slot_height,
798
+ yoff-slot_height,
799
+ yoff-slot_height-yoke_height,
800
+ yoff-slot_height-yoke_height)
801
+ ax.fill(xx, yy, color='skyblue')
802
+
803
+ yt = (yoff-slot_height-yoke_height,
804
+ yoff-slot_height-yoke_height,
805
+ yoff, yoff)
806
+ for n in range(Q//g):
807
+ xt = np.array((n*taus, n*taus+(taus-slot_width)/2,
808
+ n*taus+(taus-slot_width)/2, n*taus))
809
+ ax.fill(xt, yt, color='skyblue')
810
+ xt += slot_width + (taus-slot_width)/2
811
+ ax.fill(xt, yt, color='skyblue')
812
+ return yoff - slot_height - yoke_height
813
+
814
+
815
+ def horizontal_plot(machine, ax):
816
+ logger.debug("begin of horizontal_plot()")
817
+
818
+ model_type = machine['afmtype'][0:4]
819
+ dy1 = machine['outer_diam']*1e3
820
+ dy2 = machine['inner_diam']*1e3
821
+ rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
822
+ magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
823
+ magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
824
+
825
+ Q = machine['stator']['num_slots']
826
+ slot_width = machine['stator']['afm_stator']['slot_width']*1e3
827
+ poles = machine['poles']
828
+ m = 3
829
+ slot_height = machine['stator']['afm_stator']['slot_height']*1e3
830
+ if model_type in ('S2R1', 'S2R1_all'):
831
+ slot_height /= 2
832
+ yoke_height = machine['stator']['afm_stator']['yoke_height']*1e3
833
+ ag = machine['airgap']*1e3
834
+
835
+ g = np.gcd(Q, m*poles)//m
836
+ taus = dy2*np.pi/Q
837
+
838
+ yoff = 0.0
839
+ if model_type in ('S1R2', 'S1R2_all'): # 2 rotor
840
+ yoff = _draw_horizontal_magnets(ax, poles,
841
+ magn_height, rel_magn_width,
842
+ magn_yoke_height,
843
+ Q, g, taus, dy2,
844
+ yoff=yoff,
845
+ iron=IRON_UP)
846
+ yoff -= ag
847
+
848
+ tooth = TOOTH_ONLY if model_type in ('S1R2', 'S1R2_all') else TOOTH_DOWN
849
+ yoff = _draw_horizontal_slots(ax,
850
+ slot_height, slot_width, yoke_height,
851
+ Q, g, taus,
852
+ yoff=yoff,
853
+ tooth=tooth)
854
+ yoff -= ag
855
+
856
+ iron = IRON_DOWN if model_type in ('S1R1', 'S1R2', 'S1R2_all') else IRON_NO
857
+ yoff = _draw_horizontal_magnets(ax, poles,
858
+ magn_height, rel_magn_width,
859
+ magn_yoke_height,
860
+ Q, g, taus, dy2,
861
+ yoff=yoff,
862
+ iron=iron)
863
+ yoff -= ag
864
+
865
+ if model_type in ('S2R1', 'S2R1_all'): # 2 rotor
866
+ yoff = _draw_horizontal_slots(ax,
867
+ slot_height, slot_width, yoke_height,
868
+ Q, g, taus,
869
+ yoff=yoff,
870
+ tooth=TOOTH_UP)
871
+
872
+ _set_plot_attributes(ax)
873
+ logger.debug("end of horizontal_plot()")
874
+
875
+
601
876
  class AFPM:
602
877
  """Axial Flux PM
603
878
  Arguments:
@@ -166,9 +166,9 @@ def _generate_mesh(n, T, nb, Tb, npoints):
166
166
  nmax = max(n)
167
167
  tmin, tmax = 0, max(T)
168
168
  tnum = npoints[1]
169
- tip = ip.interp1d(n, T)
169
+ tip = ip.make_interp_spline(n, T, k=1)
170
170
  if nb and Tb:
171
- tbip = ip.interp1d(nb, Tb)
171
+ tbip = ip.make_interp_spline(nb, Tb, k=1)
172
172
  else:
173
173
  def tbip(x): return 0
174
174
 
femagtools/machine/im.py CHANGED
@@ -35,6 +35,9 @@ def log_interp1d(x, y, kind='cubic'):
35
35
  logy = np.log10(yy)
36
36
  lin_interp = ip.interp1d(logx, logy, kind=kind, fill_value="extrapolate")
37
37
  def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz)))
38
+ # TODO check replace interp1d
39
+ #lin_interp = ip.make_interp_spline(logx, logy, bc_type='not-a-knot')
40
+ #def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz), nu=1))
38
41
  return log_interp
39
42
 
40
43
 
@@ -792,15 +795,10 @@ def parident(workdir, engine, f1, u1, wdgcon,
792
795
  tend = time.time()
793
796
  logger.info("Elapsed time %d s Status %s",
794
797
  (tend-tstart), status)
798
+ if any([x != 'C' for x in status]):
799
+ raise ValueError("AC simulation failed")
795
800
  # collect results
796
- results = []
797
- errors = []
798
- for t in job.tasks:
799
- if t.status == 'C':
800
- results.append(t.get_results())
801
- else:
802
- logger.warning("Status %s", t.status)
803
- results.append({})
801
+ results = [t.get_results() for t in job.tasks]
804
802
 
805
803
  i1_0 = results[0]['i1_0'].tolist()
806
804
  psi1_0 = results[0]['psi1_0'].tolist()
femagtools/machine/sm.py CHANGED
@@ -187,7 +187,7 @@ def parident(workdir, engine, machine,
187
187
 
188
188
  if simulation['calculationMode'] == 'ld_lq_fast':
189
189
  dqpars = dict(m=3, p=b['machine']['p'],
190
- r1=r1,
190
+ r1=float(r1),
191
191
  r2=machine['rotor'].get('resistance', 1),
192
192
  rotor_mass=rotor_mass, kfric_b=1,
193
193
  ldq=[dict(
@@ -434,7 +434,7 @@ class SynchronousMachine(object):
434
434
  def iqd_tmech(self, torque, n, disp=False, maxiter=500):
435
435
  """return currents for shaft torque with minimal losses"""
436
436
  if torque > 0:
437
- startvals = self.bounds[0][1], 0, self.bounds[-1][1]
437
+ startvals = self.bounds[0][1]/2, 0, self.bounds[-1][1]
438
438
  else:
439
439
  startvals = -self.bounds[0][1]/2, 0, self.bounds[-1][1]
440
440
 
@@ -366,7 +366,8 @@ def dqparident(workdir, engine, temp, machine,
366
366
  num_beta_steps: number of current steps (default 7 per quadrant)
367
367
  speed: rotor speed in 1/s (default 160/p)
368
368
  i1_max: maximum current in A rms (default approx 3*i1nom)
369
- period_frac: fraction of rotating angle (default 6)
369
+ period_frac: (int) fraction of rotating angle (default 6)
370
+ dqtype: (str) type of identification: 'ldq' (default), 'psidq'
370
371
  cmd: femag executable
371
372
  """
372
373
  import pathlib
femagtools/mcv.py CHANGED
@@ -12,7 +12,7 @@ import pathlib
12
12
  import struct
13
13
  import math
14
14
  import numpy as np
15
- import scipy.interpolate as ip
15
+ from scipy.interpolate import make_interp_spline
16
16
  from six import string_types
17
17
  import femagtools.losscoeffs as lc
18
18
 
@@ -99,7 +99,7 @@ def norm_pfe(B, pfe):
99
99
  b = list(b)
100
100
  b[-1] = Bv[n]
101
101
  n += 1
102
- pfunc = ip.interp1d(b, pfe[i], kind='cubic')
102
+ pfunc = make_interp_spline(b, pfe[i])
103
103
  m.append([float(pfunc(x))
104
104
  for x in Bv[:n]] + [None]*(len(Bv)-n))
105
105
  return Bv.tolist(), m
@@ -168,8 +168,7 @@ def recalc_bsin(curve):
168
168
  if bi[0] > 0:
169
169
  bi.insert(0, 0)
170
170
  hi.insert(0, 0)
171
- bh = ip.interp1d(bi, hi,
172
- kind='cubic', assume_sorted=True)
171
+ bh = make_interp_spline(bi, hi)
173
172
  for bx in c['bi'][2:]:
174
173
  bt = bx*np.sin(2*np.pi/4/ndel*x)
175
174
  nue = np.sum(bh(bt)/bt)/ndel
@@ -196,8 +195,7 @@ def recalc_hsin(curve):
196
195
  if hi[0] > 0:
197
196
  hi.insert(0, 0)
198
197
  bi.insert(0, 0)
199
- hb = ip.interp1d(hi, bi,
200
- kind='cubic', assume_sorted=True)
198
+ hb = make_interp_spline(hi, bi)
201
199
  for hx in c['hi'][2:]:
202
200
  ht = hx*np.sin(2*np.pi/4/ndel*x)
203
201
  bt = hb(ht)*np.sin(2*np.pi/4/ndel*x)
@@ -243,11 +241,12 @@ def approx(db2, curve, ctype):
243
241
  if ctype in (DEMCRV, MAG_AC_CRV):
244
242
  dhdbn = 0
245
243
  k = len(bi2)-1
246
- if curve['bi'][k] - curve['bi'][k-1] > 0:
247
- dhdbn = ((curve['hi'][k] - curve['h'][k-1],KK)
248
- /(curve['bi'][k] - curve['bi'][k-1]))
249
- a.append(MUE0*dhdbn)
250
- b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
244
+ if k < len(curve['bi']):
245
+ if curve['bi'][k] - curve['bi'][k-1] > 0:
246
+ dhdbn = ((curve['hi'][k] - curve['h'][k-1])
247
+ /(curve['bi'][k] - curve['bi'][k-1]))
248
+ a.append(MUE0*dhdbn)
249
+ b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
251
250
  else:
252
251
  a.append(1.0)
253
252
  b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
femagtools/plot/char.py CHANGED
@@ -333,10 +333,14 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
333
333
  clippath = Path(_get_nT_boundary(x, y))
334
334
  patch = PathPatch(clippath, facecolor='none')
335
335
  ax.add_patch(patch)
336
- for c in cont.collections:
337
- c.set_clip_path(patch)
338
- for c in contf.collections:
339
- c.set_clip_path(patch)
336
+ try:
337
+ for c in cont.collections:
338
+ c.set_clip_path(patch)
339
+ for c in contf.collections:
340
+ c.set_clip_path(patch)
341
+ except AttributeError: # matplotlib >= 3.10
342
+ cont.set_clip_path(patch)
343
+ contf.set_clip_path(patch)
340
344
 
341
345
  if xscale > 1:
342
346
  def format_fn(tick_val, tick_pos):
@@ -367,9 +371,16 @@ def efficiency_map(rmap, ax=0, title='', clabel=True,
367
371
 
368
372
 
369
373
  def losses_map(rmap, ax=0, title='Losses Map / kW', clabel=True,
370
- cmap='YlOrRd', cbar=False):
374
+ cmap='YlOrRd', cbar=False, key='losses'):
375
+ """
376
+ plot losses map
377
+ Args:
378
+ rmap: (dict) result of efficiency_losses_map
379
+ key: (str) type of losses: 'plfe1', 'plfe2', 'plmag', 'plcu1', 'plcu2', 'plfric', 'losses';
380
+ """
381
+
371
382
  if ax == 0:
372
383
  fig, ax = plt.subplots(figsize=(12, 12))
373
- return _plot_contour(rmap['n'], rmap['T'], np.asarray(rmap['losses'])/1e3, ax,
374
- title=title, levels=14, clabel=clabel,
375
- cmap=cmap, cbar=cbar)
384
+ return _plot_contour(rmap['n'], rmap['T'], np.asarray(rmap[key])/1e3, ax,
385
+ title=title, levels=14, clabel=clabel,
386
+ cmap=cmap, cbar=cbar)
@@ -44,10 +44,16 @@ if not airgap_created then
44
44
  nc_line(r2, 0.0, x2, y2, 0.0)
45
45
 
46
46
  if m.tot_num_slot > m.num_sl_gen then
47
+ if inner_da_end == nil then
48
+ inner_da_end = inner_da_start
49
+ end
47
50
  x3, y3 = pr2c(inner_da_end, alfa)
48
51
  x4, y4 = pr2c(r1, alfa)
49
52
  nc_line(x3, y3, x4, y4, 0, 0)
50
53
 
54
+ if outer_da_end == nil then
55
+ outer_da_end = outer_da_start
56
+ end
51
57
  x3, y3 = pr2c(outer_da_end, alfa)
52
58
  x4, y4 = pr2c(r2, alfa)
53
59
  nc_line(x3, y3, x4, y4, 0, 0)
femagtools/utils.py CHANGED
@@ -17,7 +17,7 @@ def fft(pos, y, pmod=0):
17
17
  else:
18
18
  #negative_periodic = np.abs(y[0] - y[-1])/np.max(y) > 1
19
19
  # count zero crossings
20
- ypos = np.asarray(y[:-1]) > 0
20
+ ypos = np.asarray(y)-np.mean(y) > 0
21
21
  nypos = ~ypos
22
22
  nzc = len(((ypos[:-1] & nypos[1:])
23
23
  | (nypos[:-1] & ypos[1:])).nonzero()[0])
femagtools/windings.py CHANGED
@@ -179,10 +179,10 @@ class Winding(object):
179
179
  nue = n
180
180
  else:
181
181
  nue = self.kw_order(n)
182
- #if q1 == q2: # integral slot winding
183
- # q = self.Q/2/self.m/self.p
184
- # nuep = nue/self.p
185
- # return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
182
+ if q1 == q2: # integral slot winding
183
+ q = self.Q/2/self.m/self.p
184
+ nuep = nue/self.p
185
+ return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
186
186
  k = 2 if self.l == 1 else 1
187
187
  a = nue*k*np.pi/self.Q*Yk
188
188
  t = self.Q//Qb
@@ -416,6 +416,13 @@ class Winding(object):
416
416
  [[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)])
417
417
  # complete if not basic winding:
418
418
  Qb = self.Q//num_basic_windings(self.Q, self.p, self.l)
419
+
420
+ if not np.asarray(upper).size or not np.asarray(lower).size:
421
+ layers = 1
422
+ if layers == 1 and z[1]:
423
+ z = ([[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)],
424
+ [[d*s for s, d in zip(u, ud)] for u, ud in zip(upper, udirs)])
425
+
419
426
  if max([abs(n) for m in z[0] for n in m]) < Qb:
420
427
  return [[k + [-n+Qb//2 if n < 0 else -(n+Qb//2) for n in k]
421
428
  for k in m] for m in z]
femagtools/zmq.py CHANGED
@@ -147,7 +147,6 @@ class SubscriberTask(threading.Thread):
147
147
  def send_notify():
148
148
  logger.debug(f"Send loop: {SubscriberTask.notify_send_loop}")
149
149
  while SubscriberTask.notify_send_loop:
150
- logger.debug(f"Send data: {SubscriberTask.notify_send_header}")
151
150
  if 'progress_logger' in SubscriberTask.notify_send_header:
152
151
  # collect data from different threads
153
152
  SubscriberTask.notify_send_header.remove('progress_logger')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: femagtools
3
- Version: 1.8.3
3
+ Version: 1.8.5
4
4
  Summary: Python API for FEMAG
5
5
  Author-email: Ronald Tanner <tar@semafor.ch>, Dapu Zhang <dzhang@gtisoft.com>, Beat Holm <hob@semafor.ch>, Günther Amsler <amg@semafor.ch>, Nicolas Mauchle <mau@semafor.ch>
6
6
  License: Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel