porespy/generators/__imgen__.py
changed.
Other files ignored by Codecov
test/unit/test_generators.py
has changed.
porespy/generators/__init__.py
has changed.
914  914  return im 

915  915  
916  916  
917    def cylinders(shape: List[int], radius: int, ncylinders: int, 

918    phi_max: float = 0, theta_max: float = 90, length: float = None, 

919    verbose: bool = True): 

917  +  def _cylinders(shape: List[int], 

918  +  radius: int, 

919  +  ncylinders: int, 

920  +  phi_max: float = 0, 

921  +  theta_max: float = 90, 

922  +  length: float = None, 

923  +  verbose: bool = True): 

920  924  r""" 

921  925  Generates a binary image of overlapping cylinders. 

922  926 
999  1003  return ~dt 

1000  1004  
1001  1005  
1002    def cylinders_porosity(shape: list, 

1003    radius: int, 

1004    porosity: float, 

1005    phi_max: float = 0, 

1006    theta_max: float = 90, 

1007    length: float = None, 

1008    max_iter: int = 3, 

1009    return_fiber_number: bool = False, 

1010    verbose: bool = True): 

1006  +  def cylinders(shape: List[int], 

1007  +  radius: int, 

1008  +  ncylinders: int = None, 

1009  +  porosity: float = None, 

1010  +  phi_max: float = 0, 

1011  +  theta_max: float = 90, 

1012  +  length: float = None, 

1013  +  max_iter: int = 3): 

1011  1014  r""" 

1012    Generates a binary image of overlapping cylinders, with a target 

1013    porosity input. Delegates cylinder creation to generators.cylinders. 

1015  +  Generates a binary image of overlapping cylinders given porosity OR number 

1016  +  of cylinders. 

1014  1017  
1015  1018  This is a good approximation of a fibrous mat. 

1016  1019  
1017    The cylinders_porosity function works by estimating the number of 

1018    cylinders needed to be inserted into the domain by estimating 

1019    cylinder length, and exploiting the fact that, when inserting any 

1020    potentially overlapping objects randomly into a volume v_total (which 

1021    has units of pixels and is equal to dimx x dimy x dimz, for example), 

1022    such that the total volume of objects added to the volume is v_added 

1023    (and includes any volume that was inserted but overlapped with already 

1024    occupied space), the resulting porosity will be equal to 

1025    exp(v_added/v_total). 

1026    
1027    After intially estimating the cylinder number and inserting a small 

1028    fraction of the estimated number, the true cylinder volume is 

1029    calculated, the estimate refined, and a larger fraction of cylinders 

1030    inserted. This is repeated a number of times according to the 

1031    'iterations' argument, yielding an image with a porosity close to 

1032    the goal. 

1033    
1034  1020  Parameters 

1035  1021   

1036  1022  shape : list 
1038  1024  number of voxels. 2D images are not permitted. 

1039  1025  radius : scalar 

1040  1026  The radius of the cylinders in voxels 

1027  +  ncylinders : scalar 

1028  +  The number of cylinders to add to the domain. Adjust this value to 

1029  +  control the final porosity, which is not easily specified since 

1030  +  cylinders overlap and intersect different fractions of the domain. 

1041  1031  porosity : scalar 

1042  1032  The targeted value for the porosity of the generated mat. The 

1043  1033  function uses an algorithm for predicted the number of required 
1073  1063   

1074  1064  image : NDarray 

1075  1065  A boolean array with ``True`` values denoting the pore space 

1076    fiber_number : scalar 

1077    The number of fibers added to the image. This is optional, and whether 

1078    it is returned is determined by 'return_fiber_number' 

1066  +  
1067  +  Notes 

1068  +   

1069  +  The cylinders_porosity function works by estimating the number of 

1070  +  cylinders needed to be inserted into the domain by estimating 

1071  +  cylinder length, and exploiting the fact that, when inserting any 

1072  +  potentially overlapping objects randomly into a volume v_total (which 

1073  +  has units of pixels and is equal to dimx x dimy x dimz, for example), 

1074  +  such that the total volume of objects added to the volume is v_added 

1075  +  (and includes any volume that was inserted but overlapped with already 

1076  +  occupied space), the resulting porosity will be equal to 

1077  +  exp(v_added/v_total). 

1078  +  
1079  +  After intially estimating the cylinder number and inserting a small 

1080  +  fraction of the estimated number, the true cylinder volume is 

1081  +  calculated, the estimate refined, and a larger fraction of cylinders 

1082  +  inserted. This is repeated a number of times according to the 

1083  +  'max_iter' argument, yielding an image with a porosity close to 

1084  +  the goal. 

1085  +  
1079  1086  """ 

1087  +  if ncylinders is not None: 

1088  +  im = _cylinders( 

1089  +  shape=shape, 

1090  +  radius=radius, 

1091  +  ncylinders=ncylinders, 

1092  +  phi_max=phi_max, 

1093  +  theta_max=theta_max, 

1094  +  length=length, 

1095  +  ) 

1096  +  return im 

1097  +  
1098  +  if porosity is None: 

1099  +  raise Exception("'ncylinders' and 'porosity' can't be both None") 

1100  +  
1080  1101  if max_iter < 3: 

1081  1102  raise Exception("Iterations must be greater than or equal to 3") 

1082  1103 
1104  1125  fractions.append(fractions[i  1] + (max_iter  i) ** 2 * subdif) 

1105  1126  
1106  1127  im = np.ones(shape, dtype=bool) 

1107    for frac in tqdm(fractions, disable=not verbose, file=sys.stdout, 

1108    desc="Adding fibers"): 

1128  +  for frac in tqdm(fractions, file=sys.stdout, desc="Adding fibers"): 

1109  1129  n_fibers_total = n_pixels_to_add / vol_fiber 

1110  1130  n_fibers = int(np.ceil(frac * n_fibers_total)  n_fibers_added) 

1111  1131  if n_fibers > 0: 

1112    im = im & ps.generators.cylinders( 

1132  +  im = im & _cylinders( 

1113  1133  shape, radius, n_fibers, phi_max, theta_max, length, verbose=False 

1114  1134  ) 

1115  1135  n_fibers_added += n_fibers 
1118  1138  vol_added = get_num_pixels(porosity) 

1119  1139  vol_fiber = vol_added / n_fibers_added 

1120  1140  
1121    if verbose: 

1122    print(f"{n_fibers_added} fibers were added to reach the target porosity.\n") 

1141  +  print(f"{n_fibers_added} fibers were added to reach the target porosity.\n") 

1123  1142  
1124    if return_fiber_number: 

1125    return im, n_fibers_added 

1126  1143  return im 

1127  1144  
1128  1145 
Files  Coverage 

porespy  88.1% 
Project Totals (16 files)  88.1% 
1 
codecov: 
2 
branch: dev 
3  
4 
coverage: 
5 
precision: 1 
6 
round: down 
7 
range: "50...100" 
8  
9 
status: 
10 
project: 
11 
default: 
12 
target: auto 
13 
threshold: 0.5% 
14 
branches: null 
15  
16 
patch: 
17 
default: 
18 
target: auto 
19 
threshold: 0.5% 
20 
branches: null 
21  
22 
comment: 
23 
layout: "header, diff, changes, sunburst, uncovered" 
24 
branches: null 
25 
behavior: default 