femagtools 1.8.2__py3-none-any.whl → 1.8.4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/bch.py +10 -6
  3. femagtools/dxfsl/area.py +69 -1
  4. femagtools/dxfsl/conv.py +53 -16
  5. femagtools/dxfsl/converter.py +273 -76
  6. femagtools/dxfsl/fslrenderer.py +18 -22
  7. femagtools/dxfsl/functions.py +38 -8
  8. femagtools/dxfsl/geom.py +112 -35
  9. femagtools/dxfsl/journal.py +1 -1
  10. femagtools/dxfsl/machine.py +44 -7
  11. femagtools/dxfsl/shape.py +4 -0
  12. femagtools/dxfsl/symmetry.py +105 -32
  13. femagtools/femag.py +64 -61
  14. femagtools/fsl.py +4 -2
  15. femagtools/isa7.py +3 -2
  16. femagtools/machine/afpm.py +45 -25
  17. femagtools/machine/effloss.py +31 -20
  18. femagtools/machine/im.py +6 -8
  19. femagtools/machine/sizing.py +4 -3
  20. femagtools/machine/sm.py +35 -37
  21. femagtools/mcv.py +66 -37
  22. femagtools/multiproc.py +79 -80
  23. femagtools/parstudy.py +10 -4
  24. femagtools/semi_fea.py +108 -0
  25. femagtools/templates/basic_modpar.mako +0 -3
  26. femagtools/templates/fe-contr.mako +18 -18
  27. femagtools/templates/ld_lq_fast.mako +3 -0
  28. femagtools/templates/mesh-airgap.mako +6 -0
  29. femagtools/templates/mult_cal_fast.mako +3 -0
  30. femagtools/templates/pm_sym_f_cur.mako +4 -1
  31. femagtools/templates/pm_sym_fast.mako +3 -0
  32. femagtools/templates/pm_sym_loss.mako +3 -0
  33. femagtools/templates/psd_psq_fast.mako +3 -0
  34. femagtools/templates/torq_calc.mako +3 -0
  35. femagtools/tks.py +23 -20
  36. femagtools/utils.py +1 -1
  37. femagtools/windings.py +11 -4
  38. femagtools/zmq.py +213 -0
  39. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/METADATA +3 -3
  40. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/RECORD +49 -47
  41. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/WHEEL +1 -1
  42. tests/test_afpm.py +15 -6
  43. tests/test_femag.py +1 -1
  44. tests/test_fsl.py +4 -4
  45. tests/test_mcv.py +20 -14
  46. tests/test_parident.py +2 -1
  47. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/LICENSE +0 -0
  48. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/entry_points.txt +0 -0
  49. {femagtools-1.8.2.dist-info → femagtools-1.8.4.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py CHANGED
@@ -1986,7 +1986,7 @@ class Geometry(object):
1986
1986
  startangle=0.0,
1987
1987
  endangle=np.pi/2)
1988
1988
 
1989
- elif np.isclose(width, height*2, self.rtol, self.atol):
1989
+ elif np.isclose(width, height*2, rtol=1e-2, atol=1e-2):
1990
1990
  radius = width/2
1991
1991
  self.set_center([mm[1]-height, mm[2]])
1992
1992
  logger.info("check for half machine")
@@ -2005,7 +2005,7 @@ class Geometry(object):
2005
2005
  startangle=np.pi,
2006
2006
  endangle=0.0)
2007
2007
 
2008
- elif np.isclose(width*2, height, self.rtol, self.atol):
2008
+ elif np.isclose(width*2, height, rtol=1e-2, atol=1e-2):
2009
2009
  radius = width
2010
2010
  logger.info("check for half machine")
2011
2011
  self.set_center([mm[1], mm[3]-width])
@@ -2256,45 +2256,120 @@ class Geometry(object):
2256
2256
  return center[0]
2257
2257
  return None
2258
2258
 
2259
- def get_center_arcs(self):
2259
+ def is_same_center(self, center_lst, center, rtol, atol):
2260
+ for c in center_lst:
2261
+ if points_are_close(c['center'], center['center'], rtol, atol):
2262
+ radius = center['radius'][0]
2263
+ if not radius in c['radius']:
2264
+ c['radius'].append(radius)
2265
+ c['count'] = c['count'] + 1
2266
+ return True
2267
+ return False
2268
+
2269
+ def get_center_with_x(self, center_lst, x):
2270
+ c_list = [c for c in center_lst
2271
+ if np.isclose(c['center'][0], x, rtol=self.rtol, atol=self.atol)]
2272
+ if not c_list:
2273
+ return None
2274
+ cy_list = [(c['center'][1], c) for c in c_list]
2275
+ cy_list.sort()
2276
+ y, c = cy_list[0]
2277
+ return c
2278
+
2279
+ def get_center_with_y(self, center_lst, y):
2280
+ c_list = [c for c in center_lst
2281
+ if np.isclose(c['center'][1], y, rtol=self.rtol, atol=self.atol)]
2282
+ if not c_list:
2283
+ return None
2284
+ cy_list = [(c['center'][0], c) for c in c_list]
2285
+ cy_list.sort()
2286
+ [logger.info("y=%s, c=%s", y, c) for y, c in cy_list]
2287
+ y, c = cy_list[0]
2288
+ return c
2289
+
2290
+ def get_center_arcs(self, mm):
2260
2291
  logger.debug("begin of get_center_arcs")
2261
2292
  center_list = []
2293
+ x_min, x_max, y_min, y_max = mm
2294
+
2295
+ def center_is_inside(c):
2296
+ tol = 0.1
2297
+ x, y = c
2298
+ if x-tol > x_min and \
2299
+ x+tol < x_max and \
2300
+ y-tol > y_min and \
2301
+ y+tol < y_max:
2302
+ return True
2303
+ return False
2304
+
2262
2305
  circles = [e for e in self.elements() if is_Circle(e)]
2263
2306
  logger.debug(" -- %s Circles", len(circles))
2264
2307
 
2265
2308
  for e in circles:
2266
2309
  center = (round(e.center[0], 3), round(e.center[1], 3))
2267
- radius = round(e.radius, 1)
2268
- center_list.append(([1], center, [radius]))
2310
+ entry = {'center': center,
2311
+ 'radius': [round(e.radius, 1)],
2312
+ 'phi': e.get_angle_of_arc(),
2313
+ 'dist': e.length(),
2314
+ 'inside': center_is_inside(center),
2315
+ 'count': 1}
2316
+ center_list.append(entry)
2269
2317
 
2270
2318
  arcs = [e for e in self.elements() if is_Arc(e)]
2271
2319
  logger.debug(" -- %s Arcs", len(arcs))
2272
2320
 
2273
2321
  for e in arcs:
2274
2322
  center = (round(e.center[0], 3), round(e.center[1], 3))
2275
- radius = round(e.radius, 1)
2276
- c = self.get_same_center(center_list, center, self.rtol, self.atol)
2277
- if c is None:
2278
- center_list.append(([1], center, [radius]))
2279
- else:
2280
- c[0][0] += 1
2281
- if radius not in c[2]:
2282
- c[2].append(radius)
2323
+ entry = {'center': center,
2324
+ 'radius': [round(e.radius, 1)],
2325
+ 'phi': e.get_angle_of_arc(),
2326
+ 'dist': e.length(),
2327
+ 'inside': center_is_inside(center),
2328
+ 'count': 1}
2329
+ if not self.is_same_center(center_list, entry, self.rtol, self.atol):
2330
+ center_list.append(entry)
2283
2331
 
2284
2332
  center = None
2285
- arc_list = [[len(c[2]), c[0][0], c[1]] for c in center_list]
2333
+ arc_list = [[c['count'], len(c['radius']), c['phi'], n, c]
2334
+ for n, c in enumerate(center_list)]
2286
2335
  arc_list.sort(reverse=True)
2287
2336
 
2288
- if arc_list:
2289
- c1 = arc_list[0]
2290
- center = c1[2]
2291
- if len(arc_list) > 1:
2292
- c2 = arc_list[1]
2293
- if not c1[0] > c2[0]:
2294
- center = None
2337
+ logger.debug("x min/max = %s/%s", x_min, x_max)
2338
+ logger.debug("y min/max = %s/%s", y_min, y_max)
2295
2339
 
2296
- logger.debug("end of get_center_arcs: -> %s", center)
2297
- return center
2340
+ [logger.debug("Arc %s", arc) for arc in arc_list]
2341
+ if not arc_list:
2342
+ logger.debug("end of get_center_arcs: no arcs")
2343
+ return None
2344
+
2345
+ cnt, cr1, p, n, c1 = arc_list[0]
2346
+ logger.debug("First Entry: %s", c1)
2347
+ center = c1['center']
2348
+ if len(arc_list) > 1:
2349
+ cnt, cr2, p, n, c2 = arc_list[1]
2350
+ logger.debug("Second Entry: %s", c2)
2351
+ if not cr1 > cr2:
2352
+ center = None
2353
+
2354
+ if center:
2355
+ logger.debug("end of get_center_arcs: -> %s", center)
2356
+ return center
2357
+
2358
+ c_entry = self.get_center_with_x(center_list, x_min)
2359
+ if c_entry:
2360
+ center = c_entry['center']
2361
+ if center[1] < y_min:
2362
+ logger.debug("end of get_center_arcs: x -> %s", center)
2363
+ return center
2364
+ c_entry = self.get_center_with_y(center_list, y_min)
2365
+ if c_entry:
2366
+ center = c_entry['center']
2367
+ if center[0] < x_min:
2368
+ logger.debug("end of get_center_arcs: y -> %s", center)
2369
+ return center
2370
+
2371
+ logger.debug("end of get_center_arcs: no center found")
2372
+ return None
2298
2373
 
2299
2374
  def get_center_dim(self, mm):
2300
2375
  return (round(mm[0], 4), round(mm[2], 4))
@@ -2305,7 +2380,9 @@ class Geometry(object):
2305
2380
  return None
2306
2381
 
2307
2382
  center = None
2308
- center_arcs = self.get_center_arcs()
2383
+ # Zuerst suchen wir anhand der Circle- und Arc-Segmente nach einem
2384
+ # möglichen Center-Punkt.
2385
+ center_arcs = self.get_center_arcs(mm)
2309
2386
 
2310
2387
  if center_arcs:
2311
2388
  center = center_arcs
@@ -2409,31 +2486,31 @@ class Geometry(object):
2409
2486
  logger.debug("end check_airgap: return %s", len(area_id_list) > 1)
2410
2487
  return len(area_id_list) > 1 # bad
2411
2488
 
2412
- def is_border_line(self, center, startangle, endangle, e, atol):
2489
+ def is_border_line(self, center, startangle, endangle, e, rtol=1e-3, atol=1e-3):
2413
2490
  if isinstance(e, Line):
2414
2491
  if np.isclose(startangle, endangle):
2415
2492
  return False # full
2416
2493
 
2417
2494
  if points_are_close(center, e.p1):
2418
2495
  angle_p2 = alpha_line(center, e.p2)
2419
- if np.isclose(startangle, angle_p2, 1e-3, atol):
2496
+ if np.isclose(startangle, angle_p2, rtol=rtol, atol=atol):
2420
2497
  return True
2421
- return np.isclose(endangle, angle_p2, 1e-3, atol)
2498
+ return np.isclose(endangle, angle_p2, rtol=rtol, atol=atol)
2422
2499
 
2423
2500
  if points_are_close(center, e.p2):
2424
2501
  angle_p1 = alpha_line(center, e.p1)
2425
- if np.isclose(startangle, angle_p1, 1e-3, atol):
2502
+ if np.isclose(startangle, angle_p1, rtol=rtol, atol=atol):
2426
2503
  return True
2427
- return np.isclose(endangle, angle_p1, 1e-3, atol)
2504
+ return np.isclose(endangle, angle_p1, rtol=rtol, atol=atol)
2428
2505
 
2429
2506
  angle_p1 = alpha_line(center, e.p1)
2430
- if np.isclose(startangle, angle_p1, 1e-3, atol):
2507
+ if np.isclose(startangle, angle_p1, rtol=rtol, atol=atol):
2431
2508
  angle_p2 = alpha_line(center, e.p2)
2432
- return np.isclose(startangle, angle_p2, 1e-3, atol)
2509
+ return np.isclose(startangle, angle_p2, rtol=rtol, atol=atol)
2433
2510
 
2434
- if np.isclose(endangle, angle_p1, 1e-3, atol):
2511
+ if np.isclose(endangle, angle_p1, rtol=rtol, atol=atol):
2435
2512
  angle_p2 = alpha_line(center, e.p2)
2436
- return np.isclose(endangle, angle_p2, 1e-3, atol)
2513
+ return np.isclose(endangle, angle_p2, rtol=rtol, atol=atol)
2437
2514
  return False
2438
2515
 
2439
2516
  def get_gaplist(self, center):
@@ -2457,7 +2534,7 @@ class Geometry(object):
2457
2534
  """
2458
2535
  gaplist = []
2459
2536
  for e in self.elements(Shape):
2460
- if not self.is_border_line(center, startangle, endangle, e, atol):
2537
+ if not self.is_border_line(center, startangle, endangle, e, atol=atol):
2461
2538
  gaplist += [e.minmax_from_center(center)]
2462
2539
  else:
2463
2540
  min_r, max_r = e.minmax_from_center(center)
@@ -3259,7 +3336,7 @@ class Geometry(object):
3259
3336
  max_size, max_w = windings_surface[0]
3260
3337
  for sz, w in windings_surface[1:]:
3261
3338
  logger.debug("winding size = %s", sz)
3262
- if sz / max_size < 0.80:
3339
+ if sz / max_size < 0.70:
3263
3340
  w.set_type(AREA.TYPE_AIR)
3264
3341
  if sz / max_size < 0.2:
3265
3342
  windings_found -= 1
@@ -18,7 +18,7 @@ logger = logging.getLogger('femagtools.journal')
18
18
  journal = None
19
19
 
20
20
  #############################
21
- # concat #
21
+ # journal #
22
22
  #############################
23
23
 
24
24
 
@@ -135,6 +135,16 @@ class Machine(object):
135
135
  self.geom.is_outer = True
136
136
  self.geom.is_inner = False
137
137
 
138
+ def set_attributes(self,
139
+ kind="",
140
+ inner=False,
141
+ outer=False):
142
+ self.set_kind(kind)
143
+ if inner:
144
+ self.set_inner()
145
+ if outer:
146
+ self.set_outer()
147
+
138
148
  def clear_cut_lines(self):
139
149
  self.geom.clear_cut_lines()
140
150
  if self.mirror_geom is not None:
@@ -635,9 +645,13 @@ class Machine(object):
635
645
  parts = symmetry.find_symmetry() # temp solution
636
646
  logger.debug(">>> Symmetry parts = %s <<<", parts)
637
647
 
638
- if parts > 1:
639
- found = True
640
- else:
648
+ if parts == 1:
649
+ # no slices, but ok
650
+ return False
651
+
652
+ found = (parts > 1)
653
+
654
+ if not found:
641
655
  found = self.geom.find_symmetry(self.radius,
642
656
  self.startangle,
643
657
  self.endangle,
@@ -833,11 +847,11 @@ class Machine(object):
833
847
  if dist_start > dist_end:
834
848
  machine.mirror_all_areas(self.startangle)
835
849
  machine.rotate_to(angle)
836
- machine.geom.create_list_of_areas(delete=True)
837
850
  machine.startangle -= angle
838
851
  else:
839
852
  machine.mirror_all_areas(self.endangle)
840
853
  machine.endangle += angle
854
+ machine.geom.create_list_of_areas(delete=True)
841
855
  machine.set_alfa_and_corners()
842
856
  machine.part = machine.part_of_circle()
843
857
  machine.geom.set_subregion_parameters(self.startangle,
@@ -907,23 +921,25 @@ class Machine(object):
907
921
  first_thirdangle,
908
922
  second_thirdangle)
909
923
  machine_mirror_1.clear_cut_lines()
910
-
911
924
  machine_mirror_1.repair_hull()
912
925
  machine_mirror_1.set_alfa_and_corners()
926
+ if machine_mirror_1.geom.number_of_edges() < 2: # very bad
927
+ logger.debug("end get_third_symmetry_mirror: no remaining elements")
928
+ return None
913
929
  if not machine_mirror_1.check_symmetry_graph(0.001, 0.05):
914
930
  logger.debug("end get_third_symmetry_mirror: no mirror first third")
915
931
  return None
916
932
 
917
933
  if plt:
918
934
  plt.render_elements(machine_mirror_1.geom, Shape,
919
- title="Part",
935
+ title="Part 1",
920
936
  show=True,
921
937
  with_corners=False,
922
938
  with_nodes=False,
923
939
  neighbors=True)
924
940
 
925
941
  plt.render_elements(machine_mirror_1.mirror_geom, Shape,
926
- title="Counterpart",
942
+ title="Counterpart 1",
927
943
  show=True,
928
944
  with_corners=False,
929
945
  with_nodes=False,
@@ -935,10 +951,28 @@ class Machine(object):
935
951
  machine_mirror_2.clear_cut_lines()
936
952
  machine_mirror_2.repair_hull()
937
953
  machine_mirror_2.set_alfa_and_corners()
954
+ if machine_mirror_2.geom.number_of_edges() < 2: # very bad
955
+ logger.debug("end get_third_symmetry_mirror: no remaining elements")
956
+ return None
938
957
  if not machine_mirror_2.check_symmetry_graph(0.001, 0.05):
939
958
  logger.debug("end get_third_symmetry_mirror: no mirror second third")
940
959
  return None
941
960
 
961
+ if plt:
962
+ plt.render_elements(machine_mirror_2.geom, Shape,
963
+ title="Part 2",
964
+ show=True,
965
+ with_corners=False,
966
+ with_nodes=False,
967
+ neighbors=True)
968
+
969
+ plt.render_elements(machine_mirror_2.mirror_geom, Shape,
970
+ title="Counterpart 2",
971
+ show=True,
972
+ with_corners=False,
973
+ with_nodes=False,
974
+ neighbors=True)
975
+
942
976
  machine_mirror_1.previous_machine = self
943
977
  logger.debug("end get_third_symmetry_mirror: ok")
944
978
  return machine_mirror_1
@@ -992,6 +1026,9 @@ class Machine(object):
992
1026
  with_nodes=False,
993
1027
  neighbors=True)
994
1028
 
1029
+ if machine_mirror.geom.number_of_edges() < 2: # very bad
1030
+ logger.debug("end get_symmetry_mirror: no remaining elements")
1031
+ return None
995
1032
  if machine_mirror.check_symmetry_graph(0.001, 0.05):
996
1033
  machine_mirror.previous_machine = self
997
1034
  machine_mirror.rotate_to(0.0)
femagtools/dxfsl/shape.py CHANGED
@@ -467,6 +467,10 @@ class Circle(Shape):
467
467
  r0 = np.linalg.norm(self.center)
468
468
  return max(abs(r-r0-self.radius), abs(r-r0+self.radius))
469
469
 
470
+ def length(self):
471
+ """returns length of this circle"""
472
+ return self.radius*2*np.pi
473
+
470
474
  def overlapping_shape(self, e, rtol=1e-03, atol=1e-03):
471
475
  if not (isinstance(e, Arc) or isinstance(e, Circle)):
472
476
  # end overlapping_shape: Circle (not Arc or Circle)
@@ -102,6 +102,7 @@ class Symmetry(object):
102
102
  a.get_mid_angle(self.geom.center)))
103
103
 
104
104
  def area_list_entry(self, a):
105
+ a.set_symmetry_parameter(self.geom.center)
105
106
  return (round(a.get_alpha(self.geom.center), 3),
106
107
  round(a.min_dist, 1),
107
108
  round(a.height, 1),
@@ -119,24 +120,47 @@ class Symmetry(object):
119
120
  areas.sort(reverse=True)
120
121
  return areas
121
122
 
123
+ def get_equal_areas(self, areas):
124
+ return
125
+
122
126
  def build_results(self, areas):
127
+ logger.debug("begin of build_results with %s areas", len(areas))
128
+ [logger.debug("#%s: alpha=%s, min=%s, max=%s",
129
+ a.get_id(), alpha, a.min_angle, a.max_angle) for
130
+ alpha, dist, h, mid, a in areas]
131
+
123
132
  a0_alpha, a0_min_dist, a0_height, a0_mid_angle, a0 = areas[0]
124
133
  equal_areas = [(a0_mid_angle, a0)]
125
134
  check_rslt = []
126
135
  for a1_alpha, a1_min_dist, a1_height, a1_mid_angle, a1 in areas[1:]:
127
- if self.equal_area(a0_min_dist, a0_height, a0_alpha,
128
- a1_min_dist, a1_height, a1_alpha,
129
- rtol=0.001, atol=0.05):
136
+ if (self.equal_area(a0_min_dist, a0_height, a0_alpha,
137
+ a1_min_dist, a1_height, a1_alpha,
138
+ rtol=0.001, atol=0.05)):
130
139
  a0_min_dist = (a0_min_dist + a1_min_dist) / 2
131
140
  a0_height = (a0_height + a1_height) / 2
132
141
  a0_alpha = (a0_alpha + a1_alpha) / 2
133
142
  equal_areas.append((a1_mid_angle, a1))
134
143
  else:
135
- rslt = self.check_delta(equal_areas)
136
- areasize = a0.area_size()
137
- rslt['area'] = a0
138
- rslt['areasize'] = areasize
139
- check_rslt.append((areasize, rslt))
144
+ # alpha Wechsel
145
+ id_list = []
146
+ for i in range(len(equal_areas)):
147
+ mid_angle0, area0 = equal_areas[i]
148
+ if area0.get_id() in id_list:
149
+ continue
150
+ equal_areas_check = [(mid_angle0, area0)]
151
+ for mid_angle1, area1 in equal_areas[i+1:]:
152
+ if area1.get_id() in id_list:
153
+ continue
154
+ if area0.is_symmetry_equal(area1):
155
+ equal_areas_check.append((mid_angle1, area1))
156
+ id_list.append(area1.get_id())
157
+
158
+ rslt = self.check_delta(equal_areas_check)
159
+ areasize = a0.area_size()
160
+ rslt['area'] = a0
161
+ rslt['areasize'] = areasize
162
+ check_rslt.append((areasize, rslt))
163
+
140
164
  equal_areas = [(a1_mid_angle, a1)]
141
165
  a0_min_dist = a1_min_dist
142
166
  a0_height = a1_height
@@ -148,12 +172,14 @@ class Symmetry(object):
148
172
  rslt['area'] = a0
149
173
  rslt['areasize'] = areasize
150
174
  check_rslt.append((areasize, rslt))
175
+ logger.debug("end of build_results")
151
176
  return check_rslt
152
177
 
153
178
  def get_winding_symmetry(self, inside=False):
154
179
  if inside:
155
180
  areas = [self.area_list_entry(a) for a in self.geom.list_of_areas()
156
181
  if not a.close_to_ag]
182
+ areas.sort(reverse=True)
157
183
  else:
158
184
  areas = self.build_area_list((AREA.TYPE_WINDINGS,))
159
185
 
@@ -228,6 +254,7 @@ class Symmetry(object):
228
254
  return 0
229
255
 
230
256
  check_rslt = self.build_results(areas)
257
+ logger.debug("%s results available", len(check_rslt))
231
258
 
232
259
  parts, start_delta = self.get_symmetry_parts(check_rslt)
233
260
  if parts < 2:
@@ -248,6 +275,7 @@ class Symmetry(object):
248
275
  result = {'areas': len(area_list),
249
276
  'startdelta': 0.0,
250
277
  'slices': None}
278
+ result['area_id_list'] = [a.get_id() for m, a in area_list]
251
279
  if not area_list:
252
280
  logger.debug("end of check_delta: no areas")
253
281
  return result
@@ -645,6 +673,9 @@ class Symmetry(object):
645
673
  m1 = m2
646
674
  d1 = d2
647
675
 
676
+ if not mid_list:
677
+ return None
678
+
648
679
  logger.debug("New Mids: %s", mid_list)
649
680
  delta = positive_angle(mid_list[0] * 2)
650
681
  delta_list = [delta]
@@ -692,6 +723,41 @@ class Symmetry(object):
692
723
  logger.debug("end check_first_last_difference => %s", n1 + 1)
693
724
  return n1 + 1
694
725
 
726
+ def concatenate_results(self, check_rslt):
727
+ if len(check_rslt) < 2:
728
+ return check_rslt
729
+ # ----------
730
+ def get_slices(rslt):
731
+ if rslt['slices'] is None:
732
+ return 0
733
+ if rslt.get('startdelta', 0.0) != 0.0:
734
+ return 0
735
+ if rslt.get('halfslice', None) is not None:
736
+ return 0
737
+ return rslt['slices']
738
+ # ------
739
+ new_rslt = []
740
+ size1, n1, rslt1 = check_rslt[0]
741
+ slices1 = get_slices(rslt1)
742
+ for size2, n2, rslt2 in check_rslt[1:]:
743
+ slices2 = get_slices(rslt2)
744
+ if slices1 > 0 and \
745
+ slices1 == slices2 and \
746
+ np.isclose(size1, size2, rtol=1e-01, atol=1e-01) and \
747
+ (rslt1.get('delta_corr', 0.0) == 0.0 or \
748
+ rslt2.get('delta_corr', 0.0) == 0.0):
749
+ # concatenate
750
+ rslt1['slices'] = None
751
+ rslt2['delta_corr'] = 0.0
752
+ rslt2['areas'] = rslt2['areas'] + rslt1['areas']
753
+ logger.debug("concatenate results(size %s)", size1)
754
+ else:
755
+ new_rslt.append((size1, n1, rslt1))
756
+ slices1, size1, n1, rslt1 = (slices2, size2, n2, rslt2)
757
+
758
+ new_rslt.append((size1, n1, rslt1))
759
+ return new_rslt
760
+
695
761
  def get_symmetry_parts(self, check_rslt):
696
762
  max_size = 0
697
763
  max_areas = 0
@@ -700,10 +766,11 @@ class Symmetry(object):
700
766
  self.delta_angle_corr = None
701
767
  unsure_sym = False
702
768
 
703
- check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt)]
769
+ check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt)
770
+ if rslt['slices'] is not None]
704
771
  check_rslt.sort(reverse=True)
705
- for size, n, rslt in check_rslt:
706
- logger.debug("Result: %s, %s", size, rslt)
772
+ check_rslt = self.concatenate_results(check_rslt)
773
+ [logger.debug("Result #%s: %s, %s", n, size, rslt) for size, n, rslt in check_rslt]
707
774
 
708
775
  rtol = 1e-3
709
776
  atol = 1e-2
@@ -720,40 +787,46 @@ class Symmetry(object):
720
787
  for size, n, rslt in check_rslt:
721
788
  areas = rslt['areas']
722
789
  slices = rslt['slices']
790
+ if slices is None:
791
+ continue
792
+
723
793
  size = rslt['areasize']
724
794
  angle_corr = rslt.get('delta_corr', 0.0)
725
795
 
726
796
  if rslt.get('halfslice', 0) == 1:
727
797
  halfslice.append(rslt)
728
798
 
729
- if slices is not None:
730
- if slices > 0:
731
- max_size = max(max_size, size)
732
- max_areas = max(max_areas, areas)
733
- max_slices = max(max_slices, slices)
734
- missing_middles += rslt.get('missing_middles', [])
735
- area = rslt['area']
736
- if not (np.isclose(area.min_dist,
737
- self.geom.min_radius,
738
- rtol=1e-4, atol=1e-3) and \
739
- np.isclose(area.max_dist,
740
- self.geom.max_radius,
741
- rtol=1e-4, atol=1e-3)):
742
- if rslt.get('delta_corr', 0.0) == 0.0:
743
- without_angle_corr += areas * size
744
- else:
745
- with_angle_corr += areas * size
799
+ if slices > 0:
800
+ max_size = max(max_size, size)
801
+ max_areas = max(max_areas, areas)
802
+ max_slices = max(max_slices, slices)
803
+ missing_middles += rslt.get('missing_middles', [])
804
+ area = rslt['area']
805
+ if not (np.isclose(area.min_dist,
806
+ self.geom.min_radius,
807
+ rtol=1e-4, atol=1e-3) and \
808
+ np.isclose(area.max_dist,
809
+ self.geom.max_radius,
810
+ rtol=1e-4, atol=1e-3)):
811
+ if rslt.get('delta_corr', 0.0) == 0.0:
812
+ without_angle_corr += areas * size
746
813
  else:
747
- maybe_angle_korr += areas * size
814
+ with_angle_corr += areas * size
815
+ else:
816
+ maybe_angle_korr += areas * size
817
+
748
818
  logger.debug("max size: %s, max areas: %s", max_size, max_areas)
819
+ logger.debug("Angle-Corrections: %s Yes, %s No, %s Maybe",
820
+ with_angle_corr,
821
+ without_angle_corr,
822
+ maybe_angle_korr)
749
823
 
750
- logger.debug("Angle-Corrections: %s Yes, %s No",
751
- with_angle_corr, without_angle_corr)
752
824
  if np.isclose(with_angle_corr, without_angle_corr):
753
825
  with_angle_corr = (maybe_angle_korr > 0)
754
826
  else:
755
827
  with_angle_corr = (with_angle_corr > without_angle_corr)
756
828
 
829
+ # -------------------------
757
830
  def get_halfslice_counterpart(rslt):
758
831
  if rslt.get('halfslice', 0) != 2:
759
832
  return None
@@ -768,7 +841,7 @@ class Symmetry(object):
768
841
  np.isclose(alpha1, alpha2, rtol=rtol, atol=atol):
769
842
  return half
770
843
  return None
771
-
844
+ # -----------
772
845
  if halfslice:
773
846
  logger.debug("%s halfslice [1] found", len(halfslice))
774
847