LLNL / LEAP

comprehensive library of 3D transmission Computed Tomography (CT) algorithms with Python API and fully integrated with PyTorch
https://leapct.readthedocs.io
MIT License
74 stars 8 forks source link

issue: d12_geometric_calibration.py #50

Closed ProjX0 closed 2 weeks ago

ProjX0 commented 4 weeks ago

The new geometric_calibration.py in leap v1.13 is very useful. However, it would be even more helpful if it could also work with offset scans.

Additionally, I have two issues: First issue: Is leapct.convert_to_modular() correct at line 214 of d12_geometric_calibration.py? I suspect it should be convert_to_modularbeam().

Second issue: In the example of d12_geometric_calibration.py, it seems to find up to three variables correctly. However, it doesn't seem to find four geometric variables (centerRow, centerCol, tau, and detector tilt). I tested it by modifying the code as follows. Is the code I changed incorrect, or is it that optimization doesn't work well with four variables?


    # First we perturb the true geometry specification
    Delta_centerRow = 10.0
    Delta_centerCol = 20.0
    Delta_tau = 3.0

    leapct.set_centerRow(leapct.get_centerRow() + Delta_centerRow)
    leapct.set_centerCol(leapct.get_centerCol() + Delta_centerCol)
    leapct.set_tau(Delta_tau)

    # Specify the number of times the minimize function is called
    # This may help estimate a more accurate estimate
    numIter = 2

    from scipy.optimize import minimize

    # Start by trying to find the center column
    leapct.find_centerCol(g)

    numIter = 10
    costFcn_rct = lambda x: leapct.consistency_cost(g, x[0], x[1], x[2], x[3])
    x0 = (0.0, 0.0, 0.0, 0.0)
    bounds = ((-50, 50), (-50, 50), (-5, 5), (-2, 2))
    for n in range(numIter):
        res = minimize(costFcn_rct, x0, method='Powell', bounds=bounds)
        x0 = res.x

    # Print out estimated parameters and various cost values
    print(res.message)
    print('estimated perturbations: ' + str(res.x))
    print('optimized cost = ' + str(costFcn_rct(res.x)))

    # A significant detector rotation was detected, so let's assume this is correct
    # In this case, we have to switch to modular-beam geometry
    leapct.set_centerRow(leapct.get_centerRow() + res.x[0])
    leapct.set_centerCol(leapct.get_centerCol() + res.x[1])
    leapct.set_tau(leapct.get_tau() + res.x[2])
    leapct.convert_to_modularbeam()
    leapct.rotate_detector(res.x[3])

    print('Current estimate of detector center: ' + str(leapct.get_centerRow()) + ', ' + str(leapct.get_centerCol()))

    print('Elapsed time: ' + str(time.time() - startTime) + ' seconds')
kylechampley commented 3 weeks ago

This auto calibration method is based on the zeroth order consistency conditions, so it is an absolute necessity that the projections not be truncated. If you know of a calibration method that works with truncated data, please send me a reference.

Yes, you are correct, that is a typo and should be convert_to_modularbeam(). I just fixed this on the development branch.

Your updated code looks fine to me. The authors state that the cost function is only locally convex, so if your initial guess isn't close to the true solution, it may just converge to a local minimum.