import numpy as np
from PIL import Image

def analyze():
    img = Image.open("output2g.png").convert('L')
    data = np.array(img)
    rows, cols = data.shape
    matrix = (data < 128).astype(np.int8)
    
    print(f"Matrix shape: {rows}x{cols}")
    
    # Check row weights
    row_weights = np.sum(matrix, axis=1)
    print(f"Row weight distribution: Min={np.min(row_weights)}, Max={np.max(row_weights)}, Mean={np.mean(row_weights)}")
    
    # Check column weights
    col_weights = np.sum(matrix, axis=0)
    print(f"Col weight distribution: Min={np.min(col_weights)}, Max={np.max(col_weights)}, Mean={np.mean(col_weights)}")

    # Check for Block-Quasi-Cyclic structure
    # Try different Block sizes B (lifting factors)
    potential_Bs = [32, 64, 128, 256, 512, 1024]
    for b in potential_Bs:
        if rows % b == 0 and cols % b == 0:
            # Check if block (0,0) is related to block (1,0) by a simple shift?
            # No, QC means within a block, (i+1, j+1) is circulant.
            is_block_circulant = True
            # Check block at (0,0)
            block = matrix[0:b, 0:b]
            for i in range(b-1):
                if not np.array_equal(np.roll(matrix[i, 0:b], 1), matrix[i+1, 0:b]):
                    is_block_circulant = False
                    break
            if is_block_circulant:
                print(f"CONFIRMED: Block size B={b} is circulant.")
                return b
    
    # If not strictly circulant, check if row i+1 is a shift of row i
    for b in range(1, 1024):
        if np.array_equal(np.roll(matrix[0], b), matrix[1]):
            print(f"Rows are globally shifted by {b}")
            return b

    print("No standard QC or global shift found.")
    return None

analyze()
