femagtools 1.8.1__py3-none-any.whl → 1.8.3__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.
Files changed (49) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/dxfsl/area.py +110 -1
  3. femagtools/dxfsl/areabuilder.py +93 -45
  4. femagtools/dxfsl/conv.py +5 -0
  5. femagtools/dxfsl/converter.py +85 -27
  6. femagtools/dxfsl/fslrenderer.py +5 -4
  7. femagtools/dxfsl/functions.py +14 -6
  8. femagtools/dxfsl/geom.py +135 -149
  9. femagtools/dxfsl/journal.py +1 -1
  10. femagtools/dxfsl/machine.py +161 -9
  11. femagtools/dxfsl/shape.py +46 -1
  12. femagtools/dxfsl/svgparser.py +1 -1
  13. femagtools/dxfsl/symmetry.py +143 -38
  14. femagtools/femag.py +64 -61
  15. femagtools/fsl.py +15 -12
  16. femagtools/isa7.py +3 -2
  17. femagtools/machine/__init__.py +5 -4
  18. femagtools/machine/afpm.py +79 -33
  19. femagtools/machine/effloss.py +29 -18
  20. femagtools/machine/sizing.py +192 -13
  21. femagtools/machine/sm.py +34 -36
  22. femagtools/machine/utils.py +2 -2
  23. femagtools/mcv.py +58 -29
  24. femagtools/model.py +4 -3
  25. femagtools/multiproc.py +79 -80
  26. femagtools/parstudy.py +11 -5
  27. femagtools/plot/nc.py +2 -2
  28. femagtools/semi_fea.py +108 -0
  29. femagtools/templates/basic_modpar.mako +0 -3
  30. femagtools/templates/fe-contr.mako +18 -18
  31. femagtools/templates/ld_lq_fast.mako +3 -0
  32. femagtools/templates/mult_cal_fast.mako +3 -0
  33. femagtools/templates/pm_sym_f_cur.mako +4 -1
  34. femagtools/templates/pm_sym_fast.mako +3 -0
  35. femagtools/templates/pm_sym_loss.mako +3 -0
  36. femagtools/templates/psd_psq_fast.mako +3 -0
  37. femagtools/templates/torq_calc.mako +3 -0
  38. femagtools/tks.py +23 -20
  39. femagtools/zmq.py +213 -0
  40. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/METADATA +3 -3
  41. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/RECORD +49 -47
  42. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/WHEEL +1 -1
  43. tests/test_afpm.py +15 -6
  44. tests/test_femag.py +1 -1
  45. tests/test_fsl.py +4 -4
  46. tests/test_mcv.py +21 -15
  47. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/LICENSE +0 -0
  48. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/entry_points.txt +0 -0
  49. {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,20 @@
1
- m.hc_min = ${'%12.3f' % model.get('hc_min', 95.0)} -- Limit demagnetisa > 0:[%]Hc,<0:[kA/m]
2
- m.con_hdcopy = ${'%12.3f' % model.get('con_hdcopy', 0)} -- Hc-copy:Name:auto:0,intact:1, none:-1
3
- m.b_max = ${'%12.3f' % model.get('b_max', 2.4)} -- Max Induction [T] in colorgradation
4
- m.b_min = ${'%12.3f' % model.get('move_inside')} -- Move inside: 0 , Move outside: > 0
5
- m.calc_fe_loss = ${'%12.3f' % model.get('calc_fe_loss', 1)} -- Calc. FE-Loss:0:no, 1:yes, 2:m-output
6
- m.eval_force = ${'%12.3f' % model.get('eval_force', 0)} -- Eval. force density > 0, no <= 0
7
- m.allow_draw = ${'%12.3f' % model.get('allow_draw', 1)} -- Draw Graphics :> 0: yes, 0: no
8
- m.fline_dens = ${'%12.3f' % model.get('fline_dens', 4)} -- F-Lines: 1: small, 2: medium, 3:thick
9
- m.num_flines = ${'%12.3f' % model.get('num_flines', 20)} -- Number of Field-lines: < 100 > 2
10
- m.name_bch_log = ${'%12.3f' % model.get('name_bch_log', 0)} -- Name bch-file in Logfile:> 0:yes,0:no
11
- m.st_size_move = ${'%12.3f' % model.get('st_size_move', 0)} -- Step size move: r/ph:[degr], x/y:[mm]
12
- m.num_nonl_it = ${'%12.3f' % model.get('num_nonl_it', 300)} -- Number of nonlinear Iterations < 99
13
- m.perm_mode = ${'%12.3f' % model.get('perm_mode', 0)} -- Permeability mode:>0:restore,0:actual
14
- m.error_perm = ${'%12.3f' % model.get('error_perm', 0.005)} -- Rel. Permeability error < 0.1 [%]
15
- m.allow_demagn = ${'%12.3f' % model.get('allow_demagn', 0)} -- Allow Demagnetisation:= 1:yes,= 0:no
16
- m.maenergy = ${'%12.3f' % model.get('maenergy', 0)} -- Force from magn energy 1 :yes,= 0:no
17
- m.el_order_ag = ${'%12.3f' % model.get('el_order_ag', 1)} -- El. order in air gap: lin=1: quadr=2
18
- m.export_scrpt = ${'%12.3f' % model.get('export_scrpt', 0)} -- Export parameters in script: yes > 0
1
+ m.hc_min = ${'%12.3f' % model.get('hc_min', 95.0)} -- Limit demagnetisa > 0:[%]Hc,<0:[kA/m]
2
+ m.con_hdcopy = ${'%12.3f' % model.get('con_hdcopy', 0)} -- Hc-copy:Name:auto:0,intact:1, none:-1
3
+ m.b_max = ${'%12.3f' % model.get('b_max', 2.4)} -- Max Induction [T] in colorgradation
4
+ m.b_min = ${'%12.3f' % model.get('move_inside')} -- Move inside: 0 , Move outside: > 0
5
+ m.calc_fe_loss = ${model.get('calc_fe_loss', 1)} -- Calc. FE-Loss:0:no, 1:yes, 2:m-output
6
+ m.eval_force = ${'%12.3f' % model.get('eval_force', 0)} -- Eval. force density > 0, no <= 0
7
+ m.allow_draw = ${'%12.3f' % model.get('allow_draw', 1)} -- Draw Graphics :> 0: yes, 0: no
8
+ m.fline_dens = ${'%12.3f' % model.get('fline_dens', 4)} -- F-Lines: 1: small, 2: medium, 3:thick
9
+ m.num_flines = ${'%12.3f' % model.get('num_flines', 20)} -- Number of Field-lines: < 100 > 2
10
+ m.name_bch_log = ${'%12.3f' % model.get('name_bch_log', 0)} -- Name bch-file in Logfile:> 0:yes,0:no
11
+ m.st_size_move = ${'%12.3f' % model.get('st_size_move', 0)} -- Step size move: r/ph:[degr], x/y:[mm]
12
+ m.num_nonl_it = ${'%12.3f' % model.get('num_nonl_it', 300)} -- Number of nonlinear Iterations < 99
13
+ m.perm_mode = ${'%12.3f' % model.get('perm_mode', 0)} -- Permeability mode:>0:restore,0:actual
14
+ m.error_perm = ${'%12.3f' % model.get('error_perm', 0.005)} -- Rel. Permeability error < 0.1 [%]
15
+ m.allow_demagn = ${'%12.3f' % model.get('allow_demagn', 0)} -- Allow Demagnetisation:= 1:yes,= 0:no
16
+ m.maenergy = ${'%12.3f' % model.get('maenergy', 0)} -- Force from magn energy 1 :yes,= 0:no
17
+ m.el_order_ag = ${'%12.3f' % model.get('el_order_ag', 1)} -- El. order in air gap: lin=1: quadr=2
18
+ m.export_scrpt = ${'%12.3f' % model.get('export_scrpt', 0)} -- Export parameters in script: yes > 0
19
19
 
20
20
  pre_models("FE-contr-data")
@@ -21,6 +21,9 @@ m.num_cur_steps = ${model['num_cur_steps']}
21
21
  m.nu_beta_steps = ${model['num_beta_steps']}
22
22
  m.beta_max = ${model['beta_max']}
23
23
  m.beta_min = ${model['beta_min']}
24
+ % if model.get('calc_fe_loss', 0):
25
+ m.calc_fe_loss = ${model['calc_fe_loss']}
26
+ % endif
24
27
  % if model.get('loss_funct',0):
25
28
  m.loss_funct = ${model.get('loss_funct')}
26
29
  % endif
@@ -22,6 +22,9 @@ m.fc_mult_move_type = 1.0 -- Type of move path in air gap
22
22
  m.fc_force_points = 0.0 -- number move points in air gap
23
23
  m.loss_funct = ${model.get('loss_funct', 0)} -- loss functon 0: own 1: ext
24
24
  m.loss_fact = ${model.get('loss_fact', 1)} -- loss multiplication factor
25
+ % if model.get('calc_fe_loss', 0):
26
+ m.calc_fe_loss = ${model['calc_fe_loss']}
27
+ % endif
25
28
 
26
29
  % if model.get('vtu_movie', 0):
27
30
  m.movie_type = 'vtu'
@@ -23,11 +23,14 @@ m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
23
23
  % if model.get('vtu_movie', 0):
24
24
  m.movie_type = 'vtu'
25
25
  %endif
26
+ % if model.get('calc_fe_loss'):
27
+ m.calc_fe_loss = ${'%d' % model['calc_fe_loss']}
28
+ % endif
26
29
  % if model.get('loss_funct',0):
27
30
  m.loss_funct = ${model.get('loss_funct')}
28
31
  % endif
29
32
  -- Excitation current
30
- m.nloa_ex_cur = ${model.get('nload_ex_cur', 0)} -- No Load Exciting current
33
+ m.nloa_ex_cur = ${model.get('noload_ex_cur', 0)} -- No Load Exciting current
31
34
  m.load_ex_cur = ${model.get('load_ex_cur', 0)} -- Load Exciting current
32
35
  m.wdgkeyex = 0 -- automatic winding selection
33
36
 
@@ -7,6 +7,9 @@ set_sim_data("explicit_mode", ${model.get('explicit_mode',0)})
7
7
  % if model.get('wind_temp',0):
8
8
  set_dev_data("cond_temp", ${model.get('wind_temp')}, ${model.get('wind_temp')})
9
9
  % endif
10
+ % if model.get('calc_fe_loss', 0):
11
+ m.calc_fe_loss = ${model['calc_fe_loss']}
12
+ % endif
10
13
  m.move_action = ${model.get('move_action', 0)}
11
14
  % if model.get('lfe',0):
12
15
  m.arm_length = ${model.get('lfe')*1e3}
@@ -20,6 +20,9 @@ m.winding_temp = ${model.get('wind_temp')}
20
20
  m.current = 1.0
21
21
  m.ntibfilename = model..'.ntib'
22
22
  m.period_frac = ${model.get('period_frac', 1)}
23
+ % if model.get('calc_fe_loss', 0):
24
+ m.calc_fe_loss = ${model['calc_fe_loss']}
25
+ % endif
23
26
  % if model.get('loss_funct',0):
24
27
  m.loss_funct = ${model.get('loss_funct')}
25
28
  % endif
@@ -24,6 +24,9 @@ m.delta_iq = ${model['delta_iq']}/m.num_par_wdgs
24
24
  % if model.get('load_ex_cur',0):
25
25
  m.load_ex_cur = ${model['load_ex_cur']}
26
26
  %endif
27
+ % if model.get('calc_fe_loss', 0):
28
+ m.calc_fe_loss = ${model['calc_fe_loss']}
29
+ % endif
27
30
  % if model.get('loss_funct',0):
28
31
  m.loss_funct = ${model.get('loss_funct')}
29
32
  % endif
@@ -2,6 +2,9 @@
2
2
  -- Torque/Force calculation
3
3
  --
4
4
  m.move_action = ${model.get('move_action', 0)}
5
+ % if model.get('calc_fe_loss', 0):
6
+ m.calc_fe_loss = ${model['calc_fe_loss']}
7
+ % endif
5
8
  % if model.get('loss_funct',0):
6
9
  m.loss_funct = ${model.get('loss_funct')}
7
10
  % endif
femagtools/tks.py CHANGED
@@ -22,15 +22,15 @@ HBpattern = re.compile(r'H.+\s+B')
22
22
  BPpattern = re.compile(r'B.+\s+P')
23
23
 
24
24
  _tranlate = {
25
- "ch": "Hysteresis Loss Factor",
26
- "cw": "Eddy Current Loss Factor",
27
- "ce": "Excess Loss Factor",
28
- "ch_freq": "Hyteresis Exponent",
29
- "cw_freq": "Eddy Current Exponent",
30
- "b_coeff": "Induction Loss Exponent",
25
+ "ch": "Hysteresis Loss Factor",
26
+ "cw": "Eddy Current Loss Factor",
27
+ "ce": "Excess Loss Factor",
28
+ "ch_freq": "Hyteresis Exponent",
29
+ "cw_freq": "Eddy Current Exponent",
30
+ "b_coeff": "Induction Loss Exponent",
31
31
  "alpha": "Induction Loss Exponent (Bertotti)",
32
- "Bo": "Reference Induction",
33
- "fo": "Reference Frequency",
32
+ "Bo": "Reference Induction",
33
+ "fo": "Reference Frequency",
34
34
  }
35
35
 
36
36
  def readlist(section):
@@ -134,15 +134,15 @@ class Reader(object):
134
134
  self.losses['cw_freq'] = z[1]
135
135
  self.losses['b_coeff'] = z[2]
136
136
 
137
- self.steinmetz = {'cw': z[0], 'cw_freq': z[1], 'b_coeff': z[2],
137
+ self.steinmetz = {'cw': z[0], 'cw_freq': z[1], 'b_coeff': z[2],
138
138
  'Bo': self.Bo, 'fo': self.fo}
139
139
 
140
140
  self.losses['Bo'] = self.Bo
141
141
  self.losses['fo'] = self.fo
142
142
  z = lc.fit_bertotti(self.losses['f'],
143
143
  self.losses['B'], pfe)
144
- self.bertotti = {'ch': z[0], 'cw': z[1], 'ce': z[2],
145
- 'alpha': 2.0, 'Bo': 1, 'fo': 1}
144
+ self.bertotti = {'ch': z[0], 'cw': z[1], 'ce': z[2],
145
+ 'b_coeff': 2.0, 'Bo': 1, 'fo': 1}
146
146
  logger.info("Bertotti loss coeffs %s", z)
147
147
 
148
148
  # must normalize pfe matrix:
@@ -171,9 +171,12 @@ class Reader(object):
171
171
  'cw_freq': self.cw_freq,
172
172
  'b_coeff': self.b_coeff,
173
173
  'rho': self.rho,
174
- 'losses': self.losses}
175
-
176
- def tableview(Reader):
174
+ 'losses': self.losses,
175
+ 'bertotti': self.bertotti,
176
+ 'steinmetz': self.steinmetz,
177
+ 'jordan': self.jordan}
178
+
179
+ def tableview(Reader):
177
180
  """pretty print loss coeff table"""
178
181
  losscoeff = [Reader.jordan, Reader.steinmetz, Reader.bertotti]
179
182
  # Title
@@ -181,18 +184,18 @@ def tableview(Reader):
181
184
  print('='*strlen)
182
185
  print('| {:^34} '.format(' ') + '| {:^18} | {:^18} | {:^18} |'.format(*["Jordan", "Steinmetz", 'Bertotti']))
183
186
  print('='*strlen)
184
- # data
185
- for key, item in _tranlate.items():
187
+ # data
188
+ for key, item in _tranlate.items():
186
189
  fout = ''
187
- for i in losscoeff:
188
- if key in i:
190
+ for i in losscoeff:
191
+ if key in i:
189
192
  fout += '| ' + f'{i[key]:^18.8e} '
190
- else:
193
+ else:
191
194
  tmp = '-'
192
195
  fout += '| ' + f'{tmp:^18} '
193
196
  print(f'| {item:^34}' + ' ' + fout + '|')
194
197
  print('='*strlen)
195
- return
198
+ return
196
199
 
197
200
  def read(filename, filecontent=None):
198
201
  """read Thyssen File TKS and return mc dict"""
femagtools/zmq.py ADDED
@@ -0,0 +1,213 @@
1
+ """zmq functions for FEMAG
2
+
3
+ """
4
+ import re
5
+ import pathlib
6
+ import threading
7
+ import json
8
+ import time
9
+ import logging
10
+ try:
11
+ import zmq
12
+ except ImportError:
13
+ pass
14
+
15
+ numpat = re.compile(r'([+-]?\d+(?:\.\d+)?(?:[eE][+-]\d+)?)\s*')
16
+ logger = logging.getLogger(__name__)
17
+
18
+ class ProtFile:
19
+ def __init__(self, dirname, num_cur_steps):
20
+ self.size = 0
21
+ self.looplen = 0
22
+ self.cur_steps = [1, num_cur_steps]
23
+ self.n = 0
24
+ self.num_loops = 0
25
+ import platform
26
+ self.dirname = dirname
27
+ self.name = 'samples'
28
+
29
+ def percent(self):
30
+ if self.looplen > 0:
31
+ return min(100 * self.n / self.looplen, 100)
32
+ return 0
33
+
34
+ def update(self):
35
+ if not self.dirname:
36
+ return ''
37
+ p = list(pathlib.Path(self.dirname).glob('*.PROT'))
38
+ if p:
39
+ buf = ''
40
+ if self.size < p[0].stat().st_size:
41
+ with p[0].open() as fp:
42
+ fp.seek(self.size)
43
+ buf = fp.read()
44
+ return self.append(buf)
45
+ return ''
46
+
47
+ def append(self, buf):
48
+ self.size += len(buf)
49
+ for line in [l.strip() for l in buf.split('\n') if l]:
50
+ if line.startswith('Loop'):
51
+ self.n = 0
52
+ try:
53
+ cur_steps = self.cur_steps[self.num_loops]
54
+ except IndexError:
55
+ cur_steps = 1
56
+ x0, x1, dx, nbeta = [float(f)
57
+ for f in re.findall(numpat, line)][:4]
58
+ move_steps = round((x1-x0)/dx+1)
59
+ beta_steps = int(nbeta)
60
+ self.looplen = cur_steps*beta_steps*move_steps
61
+ self.num_loops += 1
62
+ elif (line.startswith('Cur') or
63
+ line.startswith('Id')):
64
+ self.n += 1
65
+ elif line.startswith('Number movesteps Fe-Losses'):
66
+ return f'{self.percent():3.1f}%' # 100%
67
+ elif line.startswith('begin'):
68
+ self.name = line.split()[1].strip()
69
+
70
+ return f'{self.percent():3.1f}%' # {self.n}/{self.looplen}'
71
+
72
+
73
+ class SubscriberTask(threading.Thread):
74
+ ylabel_index = 1
75
+ curve_label = '{}.'
76
+ # used by static notify func
77
+ percent_list = []
78
+ notify_timerfunc = None
79
+ notify_send_loop = True
80
+ notify = None
81
+ notify_send_header = set()
82
+ notify_send_data = dict()
83
+
84
+ def __init__(self, **kwargs):
85
+ threading.Thread.__init__(self)
86
+ context = zmq.Context.instance()
87
+ self.subscriber = context.socket(zmq.SUB)
88
+ self.port = kwargs.get('port', None)
89
+ self.host = kwargs.get('host')
90
+ self.notify = kwargs.get('notify', None)
91
+ SubscriberTask.notify = kwargs.get('notify', None)
92
+ self.header = kwargs.get('header')
93
+ self.num_cur_steps = kwargs.get('num_cur_steps', None)
94
+ SubscriberTask.curve_label = kwargs.get('curve_label', '')
95
+ SubscriberTask.timestep = kwargs.get('timestep', 1)
96
+ if not self.host:
97
+ self.host = 'localhost'
98
+ if not self.header:
99
+ self.header = [b'']
100
+ self.running = True
101
+
102
+ # timer function
103
+ if not SubscriberTask.notify_timerfunc:
104
+ SubscriberTask.notify_timerfunc = threading.Timer(0.1, SubscriberTask.send_notify)
105
+ SubscriberTask.notify_send_loop = True
106
+ SubscriberTask.notify_timerfunc.start()
107
+
108
+ if b'xyplot' in self.header:
109
+ self.ylabel = self.curve_label.format(SubscriberTask.ylabel_index)
110
+ SubscriberTask.ylabel_index += 1
111
+ if b'progress' in self.header:
112
+ self.protfile = ProtFile(None, self.num_cur_steps)
113
+ self.protId = len(SubscriberTask.percent_list)
114
+ SubscriberTask.percent_list.append(0) # 0%
115
+
116
+ self.subscriber.connect(f'tcp://{self.host}:{self.port}')
117
+ self.subscriber.setsockopt(zmq.SUBSCRIBE, self.header[0] if len(self.header) == 1 else b'')
118
+ self.controller = zmq.Context.instance().socket(zmq.PULL)
119
+ self.controller_url = f'inproc://publisher{self.port}'
120
+ try:
121
+ self.controller.bind(self.controller_url)
122
+ except zmq.error.ZMQError:
123
+ pass # ignore
124
+
125
+ self.poller = zmq.Poller()
126
+ self.poller.register(self.subscriber, zmq.POLLIN)
127
+ self.poller.register(self.controller, zmq.POLLIN)
128
+ self.logger = logger
129
+
130
+ def stop(self):
131
+ socket = zmq.Context.instance().socket(zmq.PUSH)
132
+ socket.connect(self.controller_url)
133
+ socket.send(b"quit")
134
+ socket.close()
135
+ self.running = False
136
+
137
+ def clear():
138
+ SubscriberTask.ylabel_index = 1
139
+ SubscriberTask.curve_label = '{}.'
140
+ SubscriberTask.notify_timerfunc = None
141
+ SubscriberTask.notify_send_loop = False
142
+ SubscriberTask.notify = None
143
+ SubscriberTask.notify_send_header = set()
144
+ SubscriberTask.notify_send_data = dict()
145
+ SubscriberTask.percent_list = []
146
+
147
+ def send_notify():
148
+ logger.debug(f"Send loop: {SubscriberTask.notify_send_loop}")
149
+ while SubscriberTask.notify_send_loop:
150
+ logger.debug(f"Send data: {SubscriberTask.notify_send_header}")
151
+ if 'progress_logger' in SubscriberTask.notify_send_header:
152
+ # collect data from different threads
153
+ SubscriberTask.notify_send_header.remove('progress_logger')
154
+ numTot = len(SubscriberTask.percent_list)
155
+ d = json.loads(SubscriberTask.notify_send_data.get('progress_logger')[1])
156
+ d['percent'] = sum(SubscriberTask.percent_list) / numTot
157
+ d['subtitle'] = f"{SubscriberTask.percent_list.count(100)} of {numTot}"
158
+ SubscriberTask.notify(['progress_logger', json.dumps(d)])
159
+ if 'xyplot' in SubscriberTask.notify_send_header:
160
+ SubscriberTask.notify([s.decode('latin1')
161
+ for s in SubscriberTask.notify_send_data.get('xyplot')])
162
+ SubscriberTask.notify_send_header.remove('xyplot')
163
+
164
+ time.sleep(abs(SubscriberTask.timestep))
165
+ logger.debug(f"Send Finished loop: {SubscriberTask.notify_send_loop}")
166
+
167
+ def run(self):
168
+ self.logger.debug("subscriber is ready, port: %s", {self.port})
169
+ while self.running:
170
+ socks = dict(self.poller.poll())
171
+ if socks.get(self.subscriber) == zmq.POLLIN:
172
+ try:
173
+ response = self.subscriber.recv_multipart()
174
+ # Sometimes femag send messages with only len = 1. These messages must be ignored
175
+ if len(response) < 2:
176
+ continue
177
+ # header progress
178
+ if response[0] == b'progress' and b'progress' in self.header:
179
+ SubscriberTask.notify_send_header.add('progress_logger')
180
+ response[0] = b'progress_logger'
181
+ SubscriberTask.notify_send_data['progress_logger'] = response
182
+ SubscriberTask.percent_list[self.protId] = json.loads(response[1].decode()).get('percent')
183
+ continue
184
+
185
+ # header xyplot (add ylabel)
186
+ if response[0] == b'xyplot' and b'xyplot' in self.header :
187
+ d = json.loads(response[1].decode(), strict=False)
188
+ d['ylabel'] = f"{d.get('ylabel')}_{self.ylabel}" \
189
+ if d.get('ylabel') else self.ylabel
190
+ response[1] = json.dumps(d).encode()
191
+
192
+ # timestep negative, immediately update
193
+ if SubscriberTask.timestep < 0:
194
+ self.notify([s.decode('latin1') for s in response])
195
+ else:
196
+ SubscriberTask.notify_send_data['xyplot'] = response
197
+ SubscriberTask.notify_send_header.add('xyplot')
198
+ continue
199
+
200
+ if response[0] in self.header or b'' in self.header:
201
+ self.notify([s.decode('latin1') for s in response])
202
+
203
+ except Exception:
204
+ self.logger.error(
205
+ "error in subscription message processing", exc_info=True)
206
+
207
+ if socks.get(self.controller) == zmq.POLLIN:
208
+ req = self.controller.recv()
209
+ self.logger.info("subscriber %s", req)
210
+ break
211
+ self.subscriber.close()
212
+ self.controller.close()
213
+ self.logger.debug("subscriber stopped")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: femagtools
3
- Version: 1.8.1
3
+ Version: 1.8.3
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
@@ -37,7 +37,7 @@ Classifier: Topic :: Scientific/Engineering
37
37
  Requires-Python: >=3.7
38
38
  Description-Content-Type: text/markdown
39
39
  License-File: LICENSE
40
- Requires-Dist: numpy<=1.26.4
40
+ Requires-Dist: numpy
41
41
  Requires-Dist: scipy
42
42
  Requires-Dist: mako
43
43
  Requires-Dist: six