2 Layer General Guinier Porod - general_guinier_porod.py

    import os
import sys
import numpy as np


#name 
name = "general_guinier_porod" 

#title
title = "Generalized Guinier Porod"

#description
description = """\
        Guinier-Porod model with TWO Guinier regions.
        rg2 and s2 fit the low-q region
        rg1 and s1 fit the mid-q region
        porod_exp fits the high-q region

        ref: B Hammouda, *A new Guinier-Porod model, J. Appl. Cryst.*, (2010), 43, 716-719."""

#parameters 
parameters = [["rg2", "Ang", 100.0, [0, np.inf], "", "Low-Q Radius of gyration"],
              ["s2",  "",    0.0,  [0, np.inf], "", "Low-Q Dimension variable"],
              ["rg1", "Ang", 10.0, [0, np.inf], "", "Mid-Q Radius of gyration"],
              ["s1",  "",    1.0,  [0, np.inf], "", "Mid-Q Dimension variable"],
              ["porod_exp",  "",    3.0,  [0, np.inf], "", "Porod exponent"]]

# def form_volume(*arg): 
#    return 1.0 

# def ER(*arg): 
#    return 1.0 

def Iq(q, rg2, s2, rg1, s1, porod_exp):

    import numpy as np # somehow this is necessary for the code to function properly

    # preallocate return value
    Iq = 0.0*q

    # Take care of the singular points
    if rg2 <= 0.0 or rg1 <= 0.0 or s2 > s1:
        return Iq

    # Calculate cross-over points and scale factors; the parameter "scale" = G1 multiplies all three pieces
    Q1 = np.sqrt((porod_exp-s1)*(3-s1)/2)/rg1
    Q2 = np.sqrt((s1-s2)/(2*np.power(rg2,2)/(3-s2) - 2*np.power(rg1,2)/(3-s1)))
    D = np.power(rg1,-(porod_exp-s1)) * np.exp(-(porod_exp-s1)/2) * np.power((porod_exp-s1)*(3-s1)/2,(porod_exp-s1)/2)
    G2 = np.exp(-np.power(Q2,2) * (np.power(rg1,2)/(3-s1) - np.power(rg2,2)/(3-s2))) * np.power(Q2,(s2-s1))

    # parse data using Q2 and Q1 transition points
    idx_G2 = q <= Q2
    idx_G1 = np.logical_and((q > Q2),(q <= Q1))
    idx_P = q > Q1

    # Do the calculation and return the function value
    with np.errstate(divide='ignore'):
        Iq[idx_G2] = G2 * np.power(q[idx_G2],-s2) * np.exp(-np.power(q[idx_G2]*rg2,2)/(3-s2))
        Iq[idx_G1] = np.power(q[idx_G1],-s1) * np.exp(-np.power(q[idx_G1]*rg1,2)/(3-s1))
        Iq[idx_P] = D * np.power(q[idx_P],-porod_exp)
    return Iq
Iq.vectorized = True # Iq accepts an array of q values

def Iqxy(x, y, rg2, s2, rg1, s1, porod_exp):
    return Iq(np.sqrt(x*x + y*y), rg2, s2, rg1, s1, porod_exp)
Iqxy.vectorized = True


Back to Model Download