예제 #1
0
def tst_nss_spherical_harmonics():
  N=50
  M=20
  lfg =  math.log_factorial_generator(N)
  nsssphe = math.nss_spherical_harmonics(M+5,50000,lfg)

  a = nsssphe.legendre_lm(8,2)
  b = nsssphe.legendre_lm_pc(8,2)
  for aa,bb in zip(a,b):
    assert abs(aa-bb)<1e-7

  a = nsssphe.legendre_lm(14,3)
  b = nsssphe.legendre_lm_pc(14,3)
  for aa,bb in zip(a,b):
    assert abs(aa-bb)<1e-7

  lm=[ (0,0), (3,3), (4,1) ]

  theta = flex.double(range(100))*3.14/100.0
  phi = flex.double(range(100))*6.28/100.0
  for tt in theta:
    for pp in phi:
      r  = nsssphe.spherical_harmonic(20,10,tt,pp)
      rr = nsssphe.spherical_harmonic_pc(20,10,tt,pp)
      #print tt,pp, r.real, r.imag, 100.0*abs(r.real-rr.real)/(max(abs(r.real),1e-12)) , 100.0*abs(rr.imag-r.imag)/(max(abs(r.imag),1e-12))
      assert 100.0*abs(r.real-rr.real)/(max(abs(r.real),1e-12))<2.0
      assert 100.0*abs(rr.imag-r.imag)/(max(abs(r.imag),1e-12))<2.0
예제 #2
0
def tst_nss_spherical_harmonics():
  N=50
  M=20
  lfg =  math.log_factorial_generator(N)
  nsssphe = math.nss_spherical_harmonics(M+5,50000,lfg)

  a = nsssphe.legendre_lm(8,2)
  b = nsssphe.legendre_lm_pc(8,2)
  for aa,bb in zip(a,b):
    assert abs(aa-bb)<1e-7

  a = nsssphe.legendre_lm(14,3)
  b = nsssphe.legendre_lm_pc(14,3)
  for aa,bb in zip(a,b):
    assert abs(aa-bb)<1e-7

  lm=[ (0,0), (3,3), (4,1) ]

  theta = flex.double(range(100))*3.14/100.0
  phi = flex.double(range(100))*6.28/100.0
  for tt in theta:
    for pp in phi:
      r  = nsssphe.spherical_harmonic(20,10,tt,pp)
      rr = nsssphe.spherical_harmonic_pc(20,10,tt,pp)
      #print tt,pp, r.real, r.imag, 100.0*abs(r.real-rr.real)/(max(abs(r.real),1e-12)) , 100.0*abs(rr.imag-r.imag)/(max(abs(r.imag),1e-12))
      assert 100.0*abs(r.real-rr.real)/(max(abs(r.real),1e-12))<2.0
      assert 100.0*abs(rr.imag-r.imag)/(max(abs(r.imag),1e-12))<2.0
예제 #3
0
파일: plots.py 프로젝트: hattne/dials
def plot_absorption_surface(physical_model):
    """Plot an absorption surface for a physical scaling model."""

    d = {
        "absorption_surface": {
            "data": [],
            "layout": {
                "title": "Absorption correction surface",
                "xaxis": {"domain": [0, 1], "anchor": "y", "title": "theta (degrees)"},
                "yaxis": {"domain": [0, 1], "anchor": "x", "title": "phi (degrees)"},
            },
            "help": absorption_help_msg,
        }
    }

    params = physical_model.components["absorption"].parameters

    order = int(-1.0 + ((1.0 + len(params)) ** 0.5))
    lfg = scitbxmath.log_factorial_generator(2 * order + 1)
    STEPS = 50
    phi = np.linspace(0, 2 * np.pi, 2 * STEPS)
    theta = np.linspace(0, np.pi, STEPS)
    THETA, _ = np.meshgrid(theta, phi)
    lmax = int(-1.0 + ((1.0 + len(params)) ** 0.5))
    Intensity = np.ones(THETA.shape)
    counter = 0
    sqrt2 = pymath.sqrt(2)
    nsssphe = scitbxmath.nss_spherical_harmonics(order, 50000, lfg)
    for l in range(1, lmax + 1):
        for m in range(-l, l + 1):
            for it, t in enumerate(theta):
                for ip, p in enumerate(phi):
                    Ylm = nsssphe.spherical_harmonic(l, abs(m), t, p)
                    if m < 0:
                        r = sqrt2 * ((-1) ** m) * Ylm.imag
                    elif m == 0:
                        assert Ylm.imag == 0.0
                        r = Ylm.real
                    else:
                        r = sqrt2 * ((-1) ** m) * Ylm.real
                    Intensity[ip, it] += params[counter] * r
            counter += 1
    d["absorption_surface"]["data"].append(
        {
            "x": list(theta * 180.0 / np.pi),
            "y": list(phi * 180.0 / np.pi),
            "z": list(Intensity.T.tolist()),
            "type": "heatmap",
            "colorscale": "Viridis",
            "colorbar": {"title": "inverse <br>scale factor"},
            "name": "absorption surface",
            "xaxis": "x",
            "yaxis": "y",
        }
    )
    return d
예제 #4
0
파일: plot.py 프로젝트: dials/dials_scratch
def sph_harm_surf(l, m):
    from scitbx import math
    from scitbx.array_family import flex
    import math as pymath

    lfg = math.log_factorial_generator(2 * l + 1)
    nsssphe = math.nss_spherical_harmonics(l, 50000, lfg)

    theta = numpy.linspace(0, 2 * numpy.pi, 2 * STEPS)
    phi = numpy.linspace(0, numpy.pi, STEPS)

    THETA, PHI = numpy.meshgrid(theta, phi)
    R = numpy.cos(PHI**2)
    C = numpy.empty(THETA.shape, dtype=str)

    sqrt2 = pymath.sqrt(2)

    for it, t in enumerate(theta):
        for ip, p in enumerate(phi):
            Ylm = nsssphe.spherical_harmonic(l, abs(m), p, t)
            if m < 0:
                r = sqrt2 * ((-1)**m) * Ylm.imag
            elif m == 0:
                assert Ylm.imag == 0.0
                r = Ylm.real
            else:
                r = sqrt2 * ((-1)**m) * Ylm.real
            R[ip, it] = pymath.fabs(r)
            if r < 0:
                C[ip, it] = "y"
            else:
                C[ip, it] = "b"

    X = R * numpy.sin(PHI) * numpy.cos(THETA)
    Y = R * numpy.sin(PHI) * numpy.sin(THETA)
    Z = R * numpy.cos(PHI)

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1, projection="3d")
    plot = ax.plot_surface(
        X,
        Y,
        Z,
        rstride=1,
        cstride=1,
        facecolors=C,
        linewidth=0,
        antialiased=True,
        alpha=0.5,
    )

    print("Saving %s..." % ("ylm%d%d.png" % (l, m)))
    plt.savefig("ylm%d%d.png" % (l, m))
예제 #5
0
파일: AimlessSurface.py 프로젝트: xia2/xia2
def work():
  from scitbx import math
  from scitbx.array_family import flex
  N=15
  lfg =  math.log_factorial_generator(N)
  nsssphe = math.nss_spherical_harmonics(6,50000,lfg)

  l = 2
  m = 1
  t = 1
  p = 1

  print nsssphe.spherical_harmonic(2, 1, 1, 1)
예제 #6
0
def work():
    from scitbx import math
    from scitbx.array_family import flex
    N = 15
    lfg = math.log_factorial_generator(N)
    nsssphe = math.nss_spherical_harmonics(6, 50000, lfg)

    l = 2
    m = 1
    t = 1
    p = 1

    print nsssphe.spherical_harmonic(2, 1, 1, 1)
예제 #7
0
파일: plot.py 프로젝트: dials/dials_scratch
def sph_harm_surf(l, m):
  from scitbx import math
  from scitbx.array_family import flex
  import math as pymath
  lfg = math.log_factorial_generator(2 * l + 1)
  nsssphe = math.nss_spherical_harmonics(l, 50000, lfg)

  theta = numpy.linspace(0, 2 * numpy.pi, 2*STEPS)
  phi = numpy.linspace(0, numpy.pi, STEPS)

  THETA, PHI = numpy.meshgrid(theta, phi)
  R = numpy.cos(PHI**2)
  C = numpy.empty(THETA.shape, dtype=str)

  sqrt2 = pymath.sqrt(2)

  for it, t in enumerate(theta):
    for ip, p in enumerate(phi):
      Ylm = nsssphe.spherical_harmonic(l, abs(m), p, t)
      if m < 0:
        r = sqrt2 * ((-1) ** m) * Ylm.imag
      elif m == 0:
        assert(Ylm.imag == 0.0)
        r = Ylm.real
      else:
        r = sqrt2 * ((-1) ** m) * Ylm.real
      R[ip, it] = pymath.fabs(r)
      if r < 0:
        C[ip, it] = 'y'
      else:
        C[ip, it] = 'b'

  X = R * numpy.sin(PHI) * numpy.cos(THETA)
  Y = R * numpy.sin(PHI) * numpy.sin(THETA)
  Z = R * numpy.cos(PHI)

  fig = plt.figure()
  ax = fig.add_subplot(1,1,1, projection='3d')
  plot = ax.plot_surface(
      X, Y, Z, rstride=1, cstride=1, facecolors=C,
      linewidth=0, antialiased=True, alpha=0.5)

  print 'Saving %s...' % ('ylm%d%d.png' % (l, m))
  plt.savefig('ylm%d%d.png' % (l, m))
예제 #8
0
def evaluate_1degree(ClmList, png_filename):
  from scitbx import math
  from scitbx.array_family import flex
  import math as pymath
  import numpy
  d2r = pymath.pi / 180.0
  order = order_from_nterm(len(ClmList))
  lfg =  math.log_factorial_generator(2 * order + 1)
  nsssphe = math.nss_spherical_harmonics(order,50000,lfg)
  Clm = { }
  idx = 0
  for l in range(1, order+1):
    for m in range(-l, l+1):
      Clm[(l,m)] = ClmList[idx]
      idx += 1

  abscor = numpy.empty((1+180//1, 1+360//1), float, 'C')
  sqrt2 = pymath.sqrt(2)
  for t in range(0, 181, 1):
    for p in range(0, 361, 1):
      a = 1.0
      for l in range(1, order+1):
        for m in range(-l, l+1):
          # Ylm = nsssphe.spherical_harmonic(l, m, t*d2r, p*d2r)
          # Convert from complex to real according to
          # http://en.wikipedia.org/wiki/Spherical_harmonics#Real_form
          Ylm = nsssphe.spherical_harmonic(l, abs(m), t*d2r, p*d2r)
          if m < 0:
            a += Clm[(l,m)] * sqrt2 * ((-1) ** m) * Ylm.imag
          elif m == 0:
            assert(Ylm.imag == 0.0)
            a += Clm[(l,m)] * Ylm.real
          else:
            a += Clm[(l,m)] * sqrt2 * ((-1) ** m) * Ylm.real
      abscor[(t//1, p//1)] = a

  import matplotlib
  matplotlib.use('Agg')
  from matplotlib import pyplot
  plot = pyplot.imshow(abscor)
  pyplot.colorbar()
  pyplot.savefig(png_filename)
  return
예제 #9
0
def evaluate_1degree(ClmList):
    from scitbx import math
    from scitbx.array_family import flex
    import math as pymath
    import numpy
    d2r = pymath.pi / 180.0
    order = order_from_nterm(len(ClmList))
    lfg = math.log_factorial_generator(2 * order + 1)
    nsssphe = math.nss_spherical_harmonics(order, 50000, lfg)
    Clm = {}
    idx = 0
    for l in range(1, order + 1):
        for m in range(-l, l + 1):
            Clm[(l, m)] = ClmList[idx]
            idx += 1

    abscor = numpy.empty((1 + 180 // 1, 1 + 360 // 1), float, 'C')
    sqrt2 = pymath.sqrt(2)
    for t in range(0, 181, 1):
        for p in range(0, 361, 1):
            a = 1.0
            for l in range(1, order + 1):
                for m in range(-l, l + 1):
                    # Ylm = nsssphe.spherical_harmonic(l, m, t*d2r, p*d2r)
                    # Convert from complex to real according to
                    # http://en.wikipedia.org/wiki/Spherical_harmonics#Real_form
                    Ylm = nsssphe.spherical_harmonic(l, abs(m), t * d2r,
                                                     p * d2r)
                    if m < 0:
                        a += Clm[(l, m)] * sqrt2 * ((-1)**m) * Ylm.imag
                    elif m == 0:
                        assert (Ylm.imag == 0.0)
                        a += Clm[(l, m)] * Ylm.real
                    else:
                        a += Clm[(l, m)] * sqrt2 * ((-1)**m) * Ylm.real
            abscor[(t // 1, p // 1)] = a
    return abscor
예제 #10
0
파일: plots.py 프로젝트: rjgildea/dials
def plot_absorption_plots(physical_model, reflection_table=None):
    """Make a number of plots to help with the interpretation of the
    absorption correction."""
    # First plot the absorption surface

    d = {
        "absorption_surface": {
            "data": [],
            "layout": {
                "title": "Absorption correction surface",
                "xaxis": {
                    "domain": [0, 1],
                    "anchor": "y",
                    "title": "azimuthal angle (degrees)",
                },
                "yaxis": {
                    "domain": [0, 1],
                    "anchor": "x",
                    "title": "polar angle (degrees)",
                },
            },
            "help": absorption_help_msg,
        }
    }

    params = physical_model.components["absorption"].parameters

    order = int(-1.0 + ((1.0 + len(params)) ** 0.5))
    lfg = scitbxmath.log_factorial_generator(2 * order + 1)
    STEPS = 50
    azimuth_ = np.linspace(0, 2 * np.pi, 2 * STEPS)
    polar_ = np.linspace(0, np.pi, STEPS)
    THETA, _ = np.meshgrid(azimuth_, polar_, indexing="ij")
    lmax = int(-1.0 + ((1.0 + len(params)) ** 0.5))
    Intensity = np.ones(THETA.shape)
    undiffracted_intensity = np.ones(THETA.shape)
    counter = 0
    sqrt2 = math.sqrt(2)
    nsssphe = scitbxmath.nss_spherical_harmonics(order, 50000, lfg)
    for l in range(1, lmax + 1):
        for m in range(-l, l + 1):
            for it, t in enumerate(polar_):
                for ip, p in enumerate(azimuth_):
                    Ylm = nsssphe.spherical_harmonic(l, abs(m), t, p)
                    if m < 0:
                        r = sqrt2 * ((-1) ** m) * Ylm.imag
                    elif m == 0:
                        assert Ylm.imag == 0.0
                        r = Ylm.real
                    else:
                        r = sqrt2 * ((-1) ** m) * Ylm.real
                    Intensity[ip, it] += params[counter] * r
                    # for the undiffracted intensity, we want to add the correction
                    # at each point to the parity conjugate. We can use the fact
                    # that the odd l terms are parity odd, and even are even, to
                    # just calculate the even terms as follows
                    if l % 2 == 0:
                        undiffracted_intensity[ip, it] += params[counter] * r
            counter += 1
    d["absorption_surface"]["data"].append(
        {
            "x": list(azimuth_ * 180.0 / np.pi),
            "y": list(polar_ * 180.0 / np.pi),
            "z": list(Intensity.T.tolist()),
            "type": "heatmap",
            "colorscale": "Viridis",
            "colorbar": {"title": "inverse <br>scale factor"},
            "name": "absorption surface",
            "xaxis": "x",
            "yaxis": "y",
        }
    )

    d["undiffracted_absorption_surface"] = {
        "data": [],
        "layout": {
            "title": "Undiffracted absorption correction",
            "xaxis": {
                "domain": [0, 1],
                "anchor": "y",
                "title": "azimuthal angle (degrees)",
            },
            "yaxis": {
                "domain": [0, 1],
                "anchor": "x",
                "title": "polar angle (degrees)",
            },
        },
        "help": """
This plot shows the calculated relative absorption for a paths travelling
straight through the crystal at a given direction in a crystal-fixed frame of
reference (in spherical coordinates). This gives an indication of the effective
shape of the crystal for absorbing x-rays. In this plot, the pole (polar angle 0)
corresponds to the laboratory x-axis.
""",
    }

    d["undiffracted_absorption_surface"]["data"].append(
        {
            "x": list(azimuth_ * 180.0 / np.pi),
            "y": list(polar_ * 180.0 / np.pi),
            "z": list(undiffracted_intensity.T.tolist()),
            "type": "heatmap",
            "colorscale": "Viridis",
            "colorbar": {"title": "inverse <br>scale factor"},
            "name": "Undiffracted absorption correction",
            "xaxis": "x",
            "yaxis": "y",
        }
    )

    if not reflection_table:
        return d

    # now plot the directions of the scattering vectors

    d["vector_directions"] = {
        "data": [],
        "layout": {
            "title": "Scattering vectors in crystal frame",
            "xaxis": {
                "domain": [0, 1],
                "anchor": "y",
                "title": "azimuthal angle (degrees)",
                "range": [0, 360],
            },
            "yaxis": {
                "domain": [0, 1],
                "anchor": "x",
                "title": "polar angle (degrees)",
                "range": [0, 180],
            },
            "coloraxis": {
                "showscale": False,
            },
        },
        "help": """
This plot shows the scattering vector directions in the crystal reference frame
used to determine the absorption correction. The s0 vectors are plotted in yellow,
the s1 vectors are plotted in teal. This gives an indication of which parts of
the absorption correction surface are sampled when determining the absorption
correction. In this plot, the pole (polar angle 0) corresponds to the laboratory
x-axis.""",
    }

    STEPS = 180  # do one point per degree
    azimuth_ = np.linspace(0, 2 * np.pi, 2 * STEPS)
    polar_ = np.linspace(0, np.pi, STEPS)
    THETA, _ = np.meshgrid(azimuth_, polar_, indexing="ij")
    Intensity = np.full(THETA.shape, np.NAN)

    # note, the s1_lookup, s0_lookup is only calculated for large datasets, so
    # for small datasets we need to calculate again.
    if "s1_lookup" not in physical_model.components["absorption"].data:
        s1_lookup = calc_lookup_index(
            calc_theta_phi(reflection_table["s1c"]), points_per_degree=1
        )
        idx_polar, idx_azimuth = np.divmod(np.unique(s1_lookup), 360)
        Intensity[idx_azimuth, idx_polar] = 1
    else:
        s1_lookup = np.unique(physical_model.components["absorption"].data["s1_lookup"])
        # x is phi, y is theta
        idx_polar, idx_azimuth = np.divmod(s1_lookup, 720)
        idx_polar = idx_polar // 2  # convert from two points per degree to one
        idx_azimuth = idx_azimuth // 2
        Intensity[idx_azimuth, idx_polar] = 1

    d["vector_directions"]["data"].append(
        {
            "x": list(azimuth_ * 180.0 / np.pi),
            "y": list(polar_ * 180.0 / np.pi),
            "z": list(Intensity.T.tolist()),
            "type": "heatmap",
            "colorscale": "Viridis",
            "showscale": False,
            "xaxis": "x",
            "yaxis": "y",
            "zmin": 0,
            "zmax": 2,
        }
    )

    Intensity = np.full(THETA.shape, np.NAN)

    if "s0_lookup" not in physical_model.components["absorption"].data:
        s0_lookup = calc_lookup_index(
            calc_theta_phi(reflection_table["s0c"]), points_per_degree=1
        )
        idx_polar, idx_azimuth = np.divmod(np.unique(s0_lookup), 360)
        Intensity[idx_azimuth, idx_polar] = 2
    else:
        s0_lookup = np.unique(physical_model.components["absorption"].data["s0_lookup"])
        # x is phi, y is theta
        idx_polar, idx_azimuth = np.divmod(s0_lookup, 720)
        idx_polar = idx_polar // 2  # convert from two points per degree to one
        idx_azimuth = idx_azimuth // 2
        Intensity[idx_azimuth, idx_polar] = 2

    d["vector_directions"]["data"].append(
        {
            "x": list(azimuth_ * 180.0 / np.pi),
            "y": list(polar_ * 180.0 / np.pi),
            "z": list(Intensity.T.tolist()),
            "type": "heatmap",
            "colorscale": "Viridis",
            "showscale": False,
            "xaxis": "x",
            "yaxis": "y",
            "zmin": 0,
            "zmax": 2,
        }
    )

    scales = physical_model.components["absorption"].calculate_scales()
    hist = flex.histogram(scales, n_slots=min(100, int(scales.size() * 10)))

    d["absorption_corrections"] = {
        "data": [
            {
                "x": list(hist.slot_centers()),
                "y": list(hist.slots()),
                "type": "bar",
                "name": "Applied absorption corrections",
            },
        ],
        "layout": {
            "title": "Applied absorption corrections",
            "xaxis": {"anchor": "y", "title": "Inverse scale factor"},
            "yaxis": {"anchor": "x", "title": "Number of reflections"},
        },
    }

    return d