femagtools 1.8.2__py3-none-any.whl → 1.8.4__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/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