예제 #1
0
 def test_invalid_size(self):
     with self.assertRaises(ValueError):
         lb.Simulator(0, 0)
     with self.assertRaises(ValueError):
         lb.Simulator(0, 1)
     with self.assertRaises(ValueError):
         lb.Simulator(1, 0)
예제 #2
0
def main():
    width = 300
    height = 300

    lb.set_random_seed(randint(0, 32768))
    
    def end_condition(ix, iy):
        return ix == 0 or ix == width - 1 or iy == 0 or iy == height - 1

    def loop(current_loop, max_loop, cells):
        if current_loop % 100 == 0:
            print(f'loop:{current_loop}/{max_loop}')
        return False

    # Initialize a break model
    min_guarantee = 0.0
    eta = 6.0
    model = lb.FastDBM(width, height, min_guarantee=min_guarantee, eta=eta)

    # Simulate
    sim = lb.Simulator(width, height, model)
    sim.breakdown(width // 2, height // 2)
    sim.simulate(max_loop=10000, callback_on_break=end_condition, callback_on_loop=loop)

    # Output
    save(sim.cells, Path(__file__).stem,
         output_binary=True, output_mono=True, output_gray=True)
예제 #3
0
def main():
    # ValueNoiseBreakModel has randomness more than default model, but slower...
    save_probability_mask = True
    width = 300
    height = 300
    seed = randint(0, 65535)  # ValueNoiseBreakModel uses own randomize code
    scale = 50.0  # zoom factor
    persistence = 1.0  # contrast
    octaves = 6  # details
    model = lb.ValueNoiseBreakModel(width,
                                    height,
                                    seed=seed,
                                    scale=scale,
                                    persistence=persistence,
                                    octaves=octaves)

    # Save probability
    if save_probability_mask:
        prob = Image.new("L", (width, height))
        for y in range(height):
            for x in range(width):
                p = model.get(x, y)
                lum = int(p * 255)
                prob.putpixel((x, y), (lum, ))
        prob.save(Path(__file__).stem + '_prob.png')

    sim = lb.Simulator(width, height, model)
    sim.breakdown(150, 150)
    sim.simulate(max_loop=3000)

    # Save to PNG
    save(sim.cells, Path(__file__).stem, output_gray=True)
예제 #4
0
def main():
    width = 200
    height = 200
    sim = lichtenberg.Simulator(width, height)
    sim.breakdown(0, 0)
    sim.insulate_square(0, 50, 40, 51)
    sim.insulate_square(50, 0, 51, 45)
    sim.simulate(max_loop=1000)

    # 1. Draw entire tree
    image = Image.new('RGB', (width, height), (0x00, 0x00, 0x00))
    c_max = sim.cells.get_max_count()
    for y in range(height):
        for x in range(width):
            c = sim.cells.get_count(x, y)
            lm = int(255 * c / c_max)  # normalize
            image.putpixel((x, y), (lm, lm, lm))
    image.save(Path(__file__).stem + '_1.png')

    # 2. Select several paths
    targets = [(5, 116), (3, 176), (46, 180), (94, 184), (184, 187), (175, 85),
               (156, 9)]
    image = Image.new('RGB', (width, height), (0x00, 0x00, 0x00))
    tree = lichtenberg.Tree(sim.cells)
    for target in targets:
        path = tree.get_path(0, 0,
                             *target)  # get the path between (0, 0) and target
        for point in path:
            x, y = point
            image.putpixel((x, y), (255, 255, 255))
    image.save(Path(__file__).stem + '_2.png')
예제 #5
0
def main():
    width = 300
    height = 300

    lb.set_random_seed(randint(0, 32768))

    def loop(current_loop, max_loop, cells):
        if current_loop % 100 == 0:
            print(f'loop:{current_loop}/{max_loop}')
        return False

    # Initialize a break model
    num_particle = 15000
    model = lb.DLABreakModel(width, height, num_particle=num_particle)

    # Simulate
    sim = lb.Simulator(width, height, model)
    sim.breakdown(width // 2, height // 2)
    sim.simulate(max_loop=10000, callback_on_loop=loop)

    # Output
    save(sim.cells,
         Path(__file__).stem,
         output_binary=True,
         output_mono=True,
         output_gray=True)
예제 #6
0
def main():
    width = 100
    height = 100
    radius = width // 2

    def end_condition(ix, iy):
        dx = ix - width // 2
        dy = iy - height // 2
        d = (dx*dx+dy*dy) ** 0.5
        end = (d >= radius - 3)
        if end:
            print("Reached the outer circle. Break.")
        return end

    def loop(current_loop, max_loop, cells):
        print(f'loop:{current_loop}/{max_loop}')
        return False

    # Initialize the field of simulation (width+2) x (height+2)
    grid = []
    for y in range(height+2):
        row = []
        for x in range(width+2):
            c = lb.DBMCell()
            c.potential = 0.0
            c.lock = False
            row.append(c)
        grid.append(row)
    n = width * height // 2
    cx, cy = width // 2, height // 2
    R = radius - 2
    for i in range(n):
        # Put potential-1.0 on the circle (x-xc)^2+(y-yc)^2=R^2
        t = 2 * math.pi * (i / n)
        x = int(R * math.cos(t)) + cx
        y = int(R * math.sin(t)) + cy
        grid[y][x].lock = True
        grid[y][x].potential = 1.0

    # Initialize a break model
    eta = 2.0  # Detail level of branching
    min_guarantee = 0.001
    model = lb.DielectricBreakModel(width, height, grid,
                                    min_guarantee=min_guarantee, eta=eta)

    # Simulate
    sim = lb.Simulator(width, height, model)
    sim.breakdown(width // 2, height // 2)
    sim.simulate(max_loop=10000, callback_on_break=end_condition, callback_on_loop=loop)

    # Output
    gamma = 1.0 / 1.8  # to remove short branches
    scale = 1.0
    save(sim.cells, Path(__file__).stem,
         output_binary=True, output_mono=True, output_gray=True,
         gamma=gamma, scale=scale)
예제 #7
0
 def test_insulate_invalid(self):
     sim = lb.Simulator(1, 1)
     with self.assertRaises(ValueError):
         sim.insulate(-1, 0)
     with self.assertRaises(ValueError):
         sim.insulate(0, -1)
     with self.assertRaises(ValueError):
         sim.insulate(1, 0)
     with self.assertRaises(ValueError):
         sim.insulate(0, 1)
예제 #8
0
 def test_breakdown_invalid(self):
     # Invalid coordinate
     sim = lb.Simulator(1, 1)
     with self.assertRaises(ValueError):
         sim.breakdown(-1, 0)
     with self.assertRaises(ValueError):
         sim.breakdown(0, -1)
     with self.assertRaises(ValueError):
         sim.breakdown(1, 0)
     with self.assertRaises(ValueError):
         sim.breakdown(0, 1)
예제 #9
0
def main():
    width = 200
    height = 200
    lb.set_random_seed(randint(0, 65535))
    sim = lb.Simulator(width, height)
    sim.breakdown(100, 50)
    sim.breakdown(50, 100)
    sim.breakdown(100, 150)
    sim.breakdown(150, 100)
    sim.simulate(max_loop=1000)
    save(sim.cells, Path(__file__).stem, output_gray=True)
예제 #10
0
def main():
    # Basic Simulation
    width = 300
    height = 300
    lb.set_random_seed(randint(0, 65535))  # Set the random seed of C/C++ standard library
    sim = lb.Simulator(width, height)
    sim.breakdown(150, 150)  # First broken cell is (x,y)=(150, 150)
    sim.simulate(max_loop=2000)

    # Save to PNG
    save(sim.cells, Path(__file__).stem, output_gray=True)  # See lichtenberg/archive.py
예제 #11
0
def main():
    width, height = 300, 300
    img = Image.new("RGB", (width, height))

    # Using FastDBM(see also 10_fastdbm_top.py)
    def end_condition(ix, iy):
        return iy == height - 1

    def loop(current_loop, max_loop, cells):
        if current_loop % 100 == 0:
            print(f'loop:{current_loop}/{max_loop}')
        return False

    min_guarantee = 0.0
    eta = 2.0
    bias = make_bias(BiasDirection.Down, width, height)
    model = lb.FastDBM(width,
                       height,
                       min_guarantee=min_guarantee,
                       eta=eta,
                       bias=bias)
    sim = lb.Simulator(width, height, model)
    sim.breakdown(width // 2, 0)
    sim.simulate(max_loop=40000,
                 callback_on_break=end_condition,
                 callback_on_loop=loop)

    # Trimming short tree branches
    min_count = 50
    min_luminance, max_luminance = 0.0, 1.00
    points, luminance = [], []
    max_count = sim.cells.get_max_count()
    for y in range(height):
        for x in range(width):
            if sim.cells.get_broken(x, y):
                c = sim.cells.get_count(x, y)  # length from the end of branch
                if c >= min_count:
                    if max_count == min_count:
                        f = 1.0
                    else:
                        f = (c - min_count) / (max_count - min_count)
                    lum = min_luminance + f * (max_luminance - min_luminance)
                    luminance.append(lum)
                    points.append((x, y))

    # Imaging
    blur_params = [(0, 1.0), (1, 4.0), (2, 8.0)]
    color = (1.2, 1.0, 1.3)
    draw_blur_with_points(img, points, blur_params, 1.0, color, luminance)

    img.save(Path(__file__).stem + ".png")
예제 #12
0
def simulation_2():
    mask_path = './resources/mask.png'
    image = Image.open(mask_path)
    width, height = image.size
    pixels = image_to_array(image)
    model = lichtenberg.ManualBreakModel(width,
                                         height,
                                         pixels,
                                         min_guarantee=0.01)
    sim = lichtenberg.Simulator(width, height, model)
    sim.breakdown(0, 0)
    sim.simulate(max_loop=1000)
    figure = gray(sim.cells)
    figure.save(Path(__file__).stem + "_2_gray.png")
    img_sum = ImageMath.eval("convert((a+b), 'L')", a=image, b=figure)
    img_sum.save(Path(__file__).stem + "_2_gray_overlay.png")
예제 #13
0
def main():
    sim = lb.Simulator(100, 100)
    sim.breakdown(0, 0)
    sim.simulate()

    prefix = Path(__file__).stem
    binary_name = prefix + ".bin"

    # Dump
    sim.cells.save(binary_name)

    # Load
    cells2 = lb.CellList2D()
    cells2.load(binary_name)

    # Imaging & Output
    save(cells2, prefix, output_gray=True)  # see lichtenberg/archive.py
예제 #14
0
파일: util.py 프로젝트: chromia/lichtenberg
def get_path(start: Tuple[int, int], end: Tuple[int, int], margin: int = 50,
             randomness: float = 50.0, seed: int = None) \
        -> List[Tuple[int, int]]:
    """
    Generate single zig-zag line
    :param start: Starting Point
    :param end: Ending Point
    :param margin: The margin of the working area[pixel]
    :param randomness: Roughness of the line
    :param seed: The seed value of the internal random number generator
    :return: The list of points
    """
    if seed is not None and not isinstance(seed, int):
        raise ValueError("seed must be int or None")

    x1, y1 = start
    x2, y2 = end
    width = abs(x2 - x1 + 1)
    height = abs(y2 - y1 + 1)
    work_width = width + margin * 2
    work_height = height + margin * 2
    x_start, x_end = 0, width - 1
    y_start, y_end = 0, height - 1
    if x1 > x2:
        x_start, x_end = x_end, x_start
    if y1 > y2:
        y_start, y_end = y_end, y_start

    # Simulation
    if seed is None:
        seed = randint(0, 2**24)
    model = lb.ValueNoiseBreakModel(work_width,
                                    work_height,
                                    seed=seed,
                                    scale=randomness)
    sim = lb.Simulator(work_width, work_height, model)
    sim.breakdown(x_start + margin, y_start + margin)
    sim.simulate(max_loop=10**5)
    # Get Path
    tree = lb.Tree(sim.cells)
    points = tree.get_path(x_start + margin, y_start + margin, x_end + margin,
                           y_end + margin)
    x_offset = x1 - x_start - margin
    y_offset = y1 - y_start - margin
    return [(x + x_offset, y + y_offset) for x, y in points]
예제 #15
0
def main():
    width = 200
    height = 200
    sim = lichtenberg.Simulator(width, height)
    sim.breakdown(60, 60)
    sim.insulate_circle(100, 100, 50)
    sim.simulate(max_loop=1000)

    image = Image.new('RGB', (width, height), (0x00, 0x00, 0x00))
    c_max = sim.cells.get_max_count()
    for y in range(height):
        for x in range(width):
            if sim.cells.get_insulated(x, y):
                # visualize insulated cells
                image.putpixel((x, y), (255, 0, 0))
            else:
                c = sim.cells.get_count(x, y)
                lm = int(255 * c / c_max)  # normalize
                image.putpixel((x, y), (lm, lm, lm))
    image.save(Path(__file__).stem + '.png')
예제 #16
0
def main():
    width = 200
    height = 200
    sim = lichtenberg.Simulator(width, height)
    sim.breakdown(width // 2, height // 2)
    sim.insulate_circle(100, 100, 100)
    sim.simulate(max_loop=1000)

    tree = lichtenberg.Tree(sim.cells)
    leaves = tree.get_leaves()

    # Select and Draw 2048 longest branch
    image = Image.new('RGB', (width, height), (0x00, 0x00, 0x00))
    # Leaf.count is the length from root(the point specified by Simulator.breakdown)
    longest_leaves = sorted(leaves, key=lambda lf: lf.count)[-2048:]
    for leaf in longest_leaves:
        node = leaf.node
        while node is not None:
            x, y, _ = node.point
            image.putpixel((x, y), (255, 255, 255))
            node = node.parent
    image.save(Path(__file__).stem + '_1.png')

    # Cut down 20-unit from outside
    image = Image.new('RGB', (width, height), (0x00, 0x00, 0x00))
    threshold = 20
    for leaf in longest_leaves:
        node = leaf.node
        while node is not None:
            x, y, count = node.point
            # count is the length from leaf
            # So omit the end of branch
            if count >= threshold:
                image.putpixel((x, y), (255, 255, 255))
            node = node.parent
    image.save(Path(__file__).stem + '_2.png')
예제 #17
0
 def test_run_without_breakdown(self):
     # At least one break point is needed
     sim = lb.Simulator(1, 1)
     with self.assertRaises(RuntimeError):
         sim.simulate()
예제 #18
0
 def test_insulated_breakpoint(self):
     sim = lb.Simulator(2, 2)
     sim.insulate(1, 1)
     sim.breakdown(1, 1)  # invalid
     with self.assertRaises(RuntimeError):
         sim.simulate()
예제 #19
0
def main():
    width = 100
    height = 100
    lb.set_random_seed(156)
    save_GIF = True
    GIF_frames: List[Image] = []

    # Initialize the field of simulation (width+2) x (height+2)
    grid = []
    for y in range(height+2):
        row = []
        for x in range(width+2):
            c = lb.DBMCell()
            c.potential = 0.0
            c.lock = False
            row.append(c)
        grid.append(row)
    # Initial Conditions:
    # - Top row has a minus potentials(attracted)
    # - Bottom row has a plus potentials(attractor)
    top, bottom = 0, height+1
    for x in range(width+2):
        grid[top][x].lock = True
        grid[bottom][x].lock = True
        grid[bottom][x].potential = 1.0
    left, right = 0, width+1
    for y in range(height+2):
        grid[y][left].lock = True
        grid[y][right].lock = True

    def end_condition(ix, iy):
        """
        If you return True, the simulation will be interrupted.
        """
        end = (iy == height-1)
        if end:
            print("Reached the end line. Break.")
        return end

    # Initialize a break model
    eta = 1.0  # Detail level of branching
    min_guarantee = 0.005
    model = lb.DielectricBreakModel(width, height, grid,
                                    min_guarantee=min_guarantee, eta=eta)

    def loop(current_loop, max_loop, cells):
        """
        If you return True, the simulation will be interrupted.
        """
        # Progress Indicator
        print(f"loop:{current_loop}/{max_loop}")

        # True to generate animation frames
        if save_GIF:
            if current_loop % 10 == 0:
                frame = visualize_field(width, height, cells, model)
                GIF_frames.append(frame)
        return False

    # Simulate
    sim = lb.Simulator(width, height, model, up=False)
    sim.breakdown(width // 2, 0)
    sim.simulate(max_loop=10000, callback_on_break=end_condition, callback_on_loop=loop)

    # Output
    gamma = 1.0/1.8
    scale = 1.0
    save(sim.cells, Path(__file__).stem,
         output_binary=True, output_mono=True, output_gray=True,
         gamma=gamma, scale=scale)

    if save_GIF:
        GIF_frames[0].save(Path(__file__).stem + ".gif",
                           save_all=True,
                           append_images=GIF_frames[1:],
                           optimize=False, duration=100, loop=0)
예제 #20
0
def main():
    width = 300
    height = 300
    seed = 49057  # randint(0, 65535)
    print(f"seed={seed}")
    lb.set_random_seed(seed)

    # Simulate
    sim = lb.Simulator(width, height)
    sim.insulate_circle(75, 225, 150)
    sim.breakdown(10, 10)
    sim.simulate(max_loop=2000)

    # Get Longest Path
    tree = lb.Tree(sim.cells)
    leaves = tree.get_leaves()
    leaves = sorted(leaves, key=lambda lf: lf.count, reverse=True)
    longest_leaf = leaves[0]
    longest_points = []
    node = longest_leaf.node
    while node is not None:
        x, y, _ = node.point
        longest_points.append((x, y))
        node = node.parent

    # Generate Potential-Points on the path
    n = len(longest_points)
    step = 1
    potentials = []
    potential_curve = func_potential()
    for i in range(0, n, step):
        t = i / n
        x, y = longest_points[i]
        p = potential_curve(t)
        potentials.append((x, y, p))

    # Output
    margin = 50
    field_width = width + margin * 2
    field_height = height + margin * 2
    time_factors = [1.0, 0.5, 0.1]
    for i, t in enumerate(time_factors):
        print(f"{i + 1}/{len(time_factors)}")

        # Simulate potential field
        flares: List[FlarePoint] = []
        for x, y, p in potentials:
            flares.append((margin + x, margin + y, p * t))
        field = lb.make_electric_field(field_width, field_height, flares)

        # Make Images
        gamma = 1.0
        img = Image.new("L", (width, height))
        for y in range(height):
            for x in range(width):
                p = field[margin + y][margin + x]
                p = p**gamma
                c = int(p * 255)
                img.putpixel((x, y), (c, ))
        img.save(Path(__file__).stem + f"_{i:02}.png")

    img = Image.new("L", (width, height))
    draw = ImageDraw.Draw(img)
    n = len(potentials)
    for i in range(n - 1):
        x1, y1, _ = potentials[i]
        x2, y2, _ = potentials[i + 1]
        draw.line((x1, y1, x2, y2), fill=(255, ), width=10)
    img.save(Path(__file__).stem + "_line.png")
예제 #21
0
 def test_manual_model_normal(self):
     values = [[0.5]]
     model = lb.ManualBreakModel(1, 1, values)
     sim = lb.Simulator(1, 1, model)
     sim.breakdown(0, 0)
     sim.simulate()
예제 #22
0
 def test_breakdown(self):
     sim = lb.Simulator(1, 1)
     sim.breakdown(0, 0)
     self.assertTrue(sim.cells.get_broken(0, 0))
예제 #23
0
 def test_run_with_breakdown(self):
     sim = lb.Simulator(1, 1)
     sim.breakdown(0, 0)
     sim.simulate()
예제 #24
0
 def test_value_noise_model_normal(self):
     model = lb.ValueNoiseBreakModel(1, 1)
     sim = lb.Simulator(1, 1, model)
     sim.breakdown(0, 0)
     sim.simulate()
예제 #25
0
 def test_valid_size(self):
     self.assertIsNotNone(lb.Simulator(1, 1))
     self.assertIsNotNone(lb.Simulator(1000, 1000))
예제 #26
0
 def test_default_model(self):
     model = lb.DefaultBreakModel()
     sim = lb.Simulator(1, 1, model)
     sim.breakdown(0, 0)
     sim.simulate()
예제 #27
0
 def test_insulate(self):
     sim = lb.Simulator(1, 1)
     sim.insulate(0, 0)
     self.assertTrue(sim.cells.get_insulated(0, 0))