Exemplo n.º 1
0
    def slabs(self, structure=None):
        layers = super(LipidLeafletTest, self).slabs(structure=structure)

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]


        # tail region
        volfrac = self.vm_tails.value / (self.apm.value *
                                         self.thickness_tails.value)
        layers[0, 4] = 1 - volfrac
        if self.head_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[0] = Structure.overall_sld(layers[0], self.head_solvent)
            layers[0, 4] = 0

        # tail region
        volfrac = self.vm_tails.value / (self.apm.value *
                                         self.thickness_tails.value)

        layers[1, 4] = 1 - volfrac
        if self.tail_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[1] = Structure.overall_sld(layers[1], self.tail_solvent)
            layers[1, 4] = 0

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]
Exemplo n.º 2
0
    def slabs(self, structure=None):
        """
        Slab representation of monolayer, as an array

        Parameters
        ----------
        structure : refnx.reflect.Structure
            The Structure hosting this Component
        """
        layers = np.zeros((2, 5))

        # thicknesses
        layers[0, 0] = float(self.thickness_heads)
        layers[1, 0] = float(self.thickness_tails)

        # real and imag SLD's
        head_sld_real, tail_sld_real = self.sld_(
            self.b_heads_real,  #real
            self.b_tails_real,
            self.b_mscl_real)
        head_sld_imag, tail_sld_imag = self.sld_(
            self.b_heads_imag,  #imaginary
            self.b_tails_imag,
            self.b_mscl_imag)
        layers[0, 1] = head_sld_real
        layers[0, 2] = head_sld_imag

        layers[1, 1] = tail_sld_real
        layers[1, 2] = tail_sld_imag

        # roughnesses
        layers[0, 3] = float(self.rough_preceding_mono)
        layers[1, 3] = float(self.rough_head_tail)

        # volume fractions
        # head region
        volfrac = self.vm_head() / (self.apm.value *
                                    self.thickness_heads.value)
        layers[0, 4] = 1 - volfrac
        if self.head_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[0] = Structure.overall_sld(layers[0], self.head_solvent)
            layers[0, 4] = 0

        # tail region
        volfrac = self.vm_tail() / (self.apm.value *
                                    self.thickness_tails.value)

        layers[1, 4] = 1 - volfrac
        if self.tail_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[1] = Structure.overall_sld(layers[1], self.tail_solvent)
            layers[1, 4] = 0

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]

        return layers
Exemplo n.º 3
0
    def profile(self, extra=False):
        """
        Calculates the volume fraction profile

        Returns
        -------
        z, vfp : np.ndarray
            Distance from the interface, volume fraction profile
        """
        s = Structure()
        s |= SLD(0)

        m = SLD(1.)

        for i, slab in enumerate(self.left_slabs):
            layer = m(slab.thick.value, slab.rough.value)
            if not i:
                layer.rough.value = 0
            layer.vfsolv.value = slab.vfsolv.value
            s |= layer

        polymer_slabs = self.slabs()
        offset = np.sum(s.slabs()[:, 0])

        if polymer_slabs is not None:
            for i in range(np.size(polymer_slabs, 0)):
                layer = m(polymer_slabs[i, 0], polymer_slabs[i, 3])
                layer.vfsolv.value = polymer_slabs[i, -1]
                s |= layer

        for i, slab in enumerate(self.right_slabs):
            layer = m(slab.thick.value, slab.rough.value)
            layer.vfsolv.value = 1 - slab.vfsolv.value
            s |= layer

        s |= SLD(0, 0)

        # now calculate the VFP.
        total_thickness = np.sum(s.slabs()[:, 0])
        zed = np.linspace(0, total_thickness, total_thickness + 1)
        # SLD profile puts a very small roughness on the interfaces with zero
        # roughness.
        zed[0] = 0.01
        z, s = s.sld_profile(z=zed)
        s[0] = s[1]

        # perhaps you'd like to plot the knot locations
        zeds = np.cumsum(self.dz)
        if np.sum(self.dz) > 1:
            zeds /= np.sum(self.dz)
            zeds = np.clip(zeds, 0, 1)

        zed_knots = zeds * float(self.extent) + offset

        if extra:
            return z, s, zed_knots, np.array(self.vf)
        else:
            return z, s
Exemplo n.º 4
0
def phase_problem_plot(flag):
    if flag != "SLD" and flag != "ACF":
        raise Exception("Invalid flag to plot")

    qvals = np.linspace(0,0.2,1025)[1:]
    sld1 = SLD(0, 0)
    sld3 = SLD(2.074, 0)

    layer1 = sld1(0, 0)
    layer3 = sld3(0, 0)

    fig = plt.figure(figsize=(15, 10))
    gs = gridspec.GridSpec(2, 2)
    ax1 = plt.subplot(gs[0,0])
    ax2 = plt.subplot(gs[1,0])
    for i, style in zip([0,1.0], ['k-', 'r:']):
        sld20 = SLD(6.335 - i, 0)
        sld21 = SLD(6.335 + i, 0)
        layer20 = sld20(100, 0)
        layer21 = sld21(100, 0)
        structure = Structure(layer1 | layer20 | layer21 | layer3)
        z, rho = structure.sld_profile()
        drho = (rho[1:] - rho[:-1]) / (z[1:] - z[:-1])
        z_ = 0.5 * (z[:-1] + z[1:])
        acf = autocorr(drho)
        z_acf = z_ - z_.min()
        z_acf = np.hstack((-np.flip(z_acf)[:-1], z_acf))

        if flag == 'SLD':
            ax1.plot(z, rho, style)
            ax2.semilogy(qvals, ReflectModel(structure, dq=0.0).model(qvals), style)

        else:
            ax1.stem(z_,   drho, style, markerfmt=' ', basefmt=style, use_line_collection=True)
            ax2.stem(z_acf, acf, style, markerfmt=' ', basefmt=style, use_line_collection=True)


    if flag == 'SLD':
        ax1.set_xlabel(r'$z$/Å')
        ax1.set_ylabel(r'$\rho(z)$/Å$^{-2}$')

        ax2.set_xlabel(r'$q$/Å')
        ax2.set_ylabel(r'$R(q)$')

    else:
        ax1.set_xlabel(r'$z$/Å')
        ax1.set_ylabel(r'$\rho\'(z)$/Å$^{-3}$')

        ax2.set_xlabel(r'$z$/Å')
        ax2.set_ylabel("$ \\rm{ACF}_{\\rho'}(z)/ \\AA^{-5}$")

    plt.tight_layout()
    figfilename = f"phase_problem_{flag}.pdf"
    plt.savefig(figfilename)
    print(f"Figure saved as {figfilename}")
    plt.close()
Exemplo n.º 5
0
    def test_left_right_influence(self):
        # make sure that if the left and right components change, so does the
        # spline
        a = Spline(100, [2], [0.5], zgrad=False, microslab_max_thickness=1)

        s = self.left | a | self.right | self.solvent

        # change the SLD of the left component, spline should respond
        self.left.sld.real.value = 2.0
        assert_almost_equal(a(0, s), 2)

        # check that the spline responds if it's a vfsolv that changes
        self.left.vfsolv.value = 0.5
        assert_almost_equal(
            Structure.overall_sld(self.left.slabs(), self.solvent)[0, 1], 6.0)
        assert_almost_equal(a(0, s), 6.0)

        # check that the right side responds.
        self.right.sld.real.value = 5.0
        assert_almost_equal(a(100, s), 5.0)

        # the spline should respond if the knot SLD's are changed
        a.vs[0].value = 3.0
        assert_almost_equal(a(50, s), 3.0)

        # spline responds if the interval knot spacing is changed
        a.dz[0].value = 0.9
        assert_almost_equal(a(90, s), 3.0)
Exemplo n.º 6
0
    def slabs(self, structure=None):
        """
        Slab representation of monolayer, as an array

        Parameters
        ----------
        structure : refnx.reflect.Structure
            The Structure hosting this Component
        """
        layers = super(LipidLeafletWithProtien,
                       self).slabs(structure=structure)

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]

        # volume fractions
        # head region
        # volfrac = self.vm_heads.value / (self.apm.value *
        #                                  self.thickness_heads.value)
        layers[0,
               4] = (1 - self.PLRatio.value
                     ) * self.thickness_heads.value / self.total_thickness()
        if self.protein_head_SLD() is not None:
            # we do the solvation here, not in Structure.slabs
            layers[0] = Structure.overall_sld(layers[0],
                                              self.protein_head_SLD())
            layers[0, 4] = 0

        # tail region
        # volfrac = self.vm_tails.value / (self.apm.value *
        #                                  self.thickness_tails.value)

        layers[1,
               4] = (1 - self.PLRatio.value
                     ) * self.thickness_heads.value / self.total_thickness()
        if self.protein_tail_SLD() is not None:
            # we do the solvation here, not in Structure.slabs
            layers[1] = Structure.overall_sld(layers[1],
                                              self.protein_tail_SLD())
            layers[1, 4] = 0

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]

        return layers
Exemplo n.º 7
0
    def slabs(self):
        """
        Slab representation of monolayer, as an array
        """
        layers = np.zeros((2, 5))

        # thicknesses
        layers[0, 0] = float(self.thickness_heads)
        layers[1, 0] = float(self.thickness_tails)

        # real and imag SLD's
        layers[0, 1] = float(self.b_heads_real) / float(self.vm_heads) * 1.e6
        layers[0, 2] = float(self.b_heads_imag) / float(self.vm_heads) * 1.e6

        layers[1, 1] = float(self.b_tails_real) / float(self.vm_tails) * 1.e6
        layers[1, 2] = float(self.b_tails_imag) / float(self.vm_tails) * 1.e6

        # roughnesses
        layers[0, 3] = float(self.rough_preceding_mono)
        layers[1, 3] = float(self.rough_head_tail)

        # volume fractions
        # head region
        volfrac = self.vm_heads.value / (self.apm.value *
                                         self.thickness_heads.value)
        layers[0, 4] = 1 - volfrac
        if self.head_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[0] = Structure.overall_sld(layers[0], self.head_solvent)
            layers[0, 4] = 0

        # tail region
        volfrac = self.vm_tails.value / (self.apm.value *
                                         self.thickness_tails.value)

        layers[1, 4] = 1 - volfrac
        if self.tail_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[1] = Structure.overall_sld(layers[1], self.tail_solvent)
            layers[1, 4] = 0

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]

        return layers
Exemplo n.º 8
0
    def _interpolator(self):
        dz = np.array(self.dz)
        zeds = np.cumsum(dz)

        # if dz's sum to more than 1, then normalise to unit interval.
        if zeds[-1] > 1:
            zeds /= zeds[-1]
            zeds = np.clip(zeds, 0, 1)

        vs = np.array(self.vs)

        left_sld = Structure.overall_sld(
            np.atleast_2d(self.left_slab.slabs[-1]), self.solvent)[..., 1]

        right_sld = Structure.overall_sld(
            np.atleast_2d(self.right_slab.slabs[0]), self.solvent)[..., 1]

        if self.zgrad:
            zeds = np.concatenate([[-1.1, 0 - EPS], zeds, [1 + EPS, 2.1]])
            vs = np.concatenate([left_sld, left_sld, vs, right_sld, right_sld])
        else:
            zeds = np.concatenate([[0 - EPS], zeds, [1 + EPS]])
            vs = np.concatenate([left_sld, vs, right_sld])

        # cache the interpolator
        cache_zeds = self.__cached_interpolator['zeds']
        cache_vs = self.__cached_interpolator['vs']
        cache_extent = self.__cached_interpolator['extent']

        # you don't need to recreate the interpolator
        if (np.array_equal(zeds, cache_zeds) and np.array_equal(vs, cache_vs)
                and np.equal(self.extent, cache_extent)):
            return self.__cached_interpolator['interp']
        else:
            self.__cached_interpolator['zeds'] = zeds
            self.__cached_interpolator['vs'] = vs
            self.__cached_interpolator['extent'] = float(self.extent)

        # TODO make vfp zero for z > self.extent
        interpolator = self.interpolator(zeds, vs)
        self.__cached_interpolator['interp'] = interpolator
        return interpolator
Exemplo n.º 9
0
def roughness():
    sld1 = SLD(0, 0)
    sld2 = SLD(6.335, 0)
    sld3 = SLD(2.074, 0)

    layer1 = sld1(0, 0)
    layer3 = sld3(10, 0)

    fig = plt.figure(figsize=(10, 7.5 / 2))
    gs = gridspec.GridSpec(1, 3)
    ax1 = plt.subplot(gs[0:2])
    ax2 = plt.subplot(gs[2])
    for i in range(3, 9, 2):
        layer2 = sld2(10, i)
        structure = Structure(layer1 | layer2 | layer3)

        ax1.plot(*structure.sld_profile())
        ax2.plot(*structure.sld_profile())
    ax2.set_ylim(1.6, 2.6)
    ax2.set_xlim(5, 15)
    ax1.axhline(sld3.real, color='k', alpha=0.3)
    ax2.axhline(sld3.real, color='k', alpha=0.3)
    ax1.set_xlabel(r'$z$/Å')
    ax1.set_ylabel(r'$\rho(z)$/Å$^{-2}$')
    ax1.text(0.025,
             0.95,
             '(a)',
             horizontalalignment='left',
             verticalalignment='top',
             transform=ax1.transAxes)
    ax2.set_xlabel(r'$z$/Å')
    ax2.set_ylabel(r'$\rho(z)$/Å$^{-2}$')
    ax2.text(0.025,
             0.95,
             '(b)',
             horizontalalignment='left',
             verticalalignment='top',
             transform=ax2.transAxes)
    plt.tight_layout()
    plt.savefig("roughness.pdf")
    plt.close()
Exemplo n.º 10
0
def resolution_test(slabs, data, backend):
    structure = Structure()
    for i, slab in enumerate(slabs):
        m = SLD(complex(slab[1], slab[2]))
        structure |= m(slab[0], slab[-1])

    with use_reflect_backend(backend):
        model = ReflectModel(structure, bkg=0.0)
        model.quad_order = 17
        R = model.model(data[:, 0],
                        x_err=data[:, -1] * 2 * np.sqrt(2 * np.log(2)))
        np.testing.assert_allclose(R, data[:, 1], rtol=0.03)
Exemplo n.º 11
0
    def test_stack(self):
        stk = Stack()
        slabs = stk.slabs(None)
        assert (slabs is None)

        si = SLD(2.07)
        sio2 = SLD(3.47)
        polymer = SLD(1.0)
        d2o = SLD(6.36)

        # check some initial stack properties
        stk.append(sio2(55, 4))
        slabs = stk.slabs(None)
        assert (slabs.shape == (1, 5))
        assert_equal(np.sum(slabs[:, 0]), 55)
        assert_equal(slabs[0, 1], 3.47)
        stk.repeats.value = 3.2
        slabs = stk.slabs(None)
        assert (slabs.shape == (3, 5))
        assert_equal(np.sum(slabs[:, 0]), 165)

        # ior a Stack and a Component
        stk |= polymer(110, 3.5)
        assert_equal(len(stk), 2)
        assert (isinstance(stk, Stack))
        assert_almost_equal(stk.repeats, 3.2)
        slabs = stk.slabs()
        assert (slabs.shape == (6, 5))
        assert_equal(np.sum(slabs[:, 0]), 495)

        # place a stack into a structure
        s = si | d2o(10, 3) | stk | d2o
        assert (isinstance(s, Structure))
        slabs = s.slabs()
        assert_equal(slabs[:, 0], [0, 10, 55, 110, 55, 110, 55, 110, 0])
        assert_equal(slabs[:, 1],
                     [2.07, 6.36, 3.47, 1.0, 3.47, 1.0, 3.47, 1.0, 6.36])
        assert_equal(slabs[:, 3], [0, 3, 4, 3.5, 4, 3.5, 4, 3.5, 0])

        # what are the interfaces of the Stack
        assert_equal(len(stk.interfaces), len(stk.slabs()))
        assert_equal(len(list(flatten(s.interfaces))), len(s.slabs()))

        # ior a Structure and a Stack
        s = Structure(components=[si(), d2o(10, 3)])
        s |= stk
        s |= d2o
        assert (isinstance(s, Structure))

        assert_equal(s.slabs()[:, 0], [0, 10, 55, 110, 55, 110, 55, 110, 0])
        assert_equal(s.slabs()[:, 1],
                     [2.07, 6.36, 3.47, 1.0, 3.47, 1.0, 3.47, 1.0, 6.36])

        q = repr(s)
        r = eval(q)
        assert_equal(r.slabs()[:, 0], [0, 10, 55, 110, 55, 110, 55, 110, 0])
        assert_equal(r.slabs()[:, 1],
                     [2.07, 6.36, 3.47, 1.0, 3.47, 1.0, 3.47, 1.0, 6.36])

        s |= stk
        assert (isinstance(s.components[-1], Stack))
        import pytest
        with pytest.raises(ValueError):
            s.slabs()
    def slabs(self, structure=None):
        """
        Slab representation of monolayer, as an array

        Parameters
        ----------
        structure : refnx.reflect.Structure
            The Structure hosting this Component
        """
        layers = np.zeros((2, 5))

        # thicknesses
        layers[0, 0] = float(self.thickness_heads)
        layers[1, 0] = float(self.thickness_tails)

        # real and imag SLD's
        head_sld_r, tail_sld_r = self.sld_r()
        head_sld_i, tail_sld_i = self.sld_i()
        layers[0, 1] = head_sld_r
        layers[0, 2] = head_sld_i

        layers[1, 1] = tail_sld_r
        layers[1, 2] = tail_sld_i

        # roughnesses
        layers[0, 3] = float(self.rough_preceding_mono)
        layers[1, 3] = float(self.rough_head_tail)

        # volume fractions
        # head region
        
        apm = self.total_vm()/self.total_thickness()
        
        self.apm.value = apm
        
        volfrac = self.vm_head() / (self.apm.value *
                                         self.thickness_heads.value)
        layers[0, 4] = 1 - volfrac
        # print("volfrac h", volfrac)
        # print(layers[0])
        if self.head_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[0] = Structure.overall_sld(layers[0], self.head_solvent_true())
            layers[0, 4] = 0

        # print(layers[0])
        # tail region
        volfrac = self.vm_tail() / (self.apm.value *
                                         self.thickness_tails.value)

        layers[1, 4] = 1 - volfrac
        # print("volfrac t", volfrac)
        if self.tail_solvent is not None:
            # we do the solvation here, not in Structure.slabs
            layers[1] = Structure.overall_sld(layers[1], self.tail_solvent_true())
            layers[1, 4] = 0

        if self.reverse_monolayer:
            layers = np.flipud(layers)
            layers[:, 3] = layers[::-1, 3]
#         print("layers",layers)
        return layers
Exemplo n.º 13
0
from refnx.reflect import Structure, SLD

sld1 = SLD(0, 0)
sld2 = SLD(6.335, 0)
sld3 = SLD(2.074, 0)

layer1 = sld1(0, 0)
layer3 = sld3(10, 0)

fig = plt.figure(figsize=(10, 7.5 / 2))
gs = gridspec.GridSpec(1, 3)
ax1 = plt.subplot(gs[0:2])
ax2 = plt.subplot(gs[2])
for i in range(3, 9, 2):
    layer2 = sld2(10, i)
    structure = Structure(layer1 | layer2 | layer3)

    ax1.plot(*structure.sld_profile())
    ax2.plot(*structure.sld_profile())
ax2.set_ylim(1.6, 2.6)
ax2.set_xlim(5, 15)
ax1.axhline(sld3.real, color='k', alpha=0.3)
ax2.axhline(sld3.real, color='k', alpha=0.3)
ax1.set_xlabel(r'$z$/Å')
ax1.set_ylabel(r'$\rho(z)$/Å$^{-2}$')
ax1.text(0.025,
         0.95,
         '(a)',
         horizontalalignment='left',
         verticalalignment='top',
         transform=ax1.transAxes)
Exemplo n.º 14
0
    def _interpolator(self, structure):
        dz = np.array(self.dz)
        zeds = np.cumsum(dz)

        # if dz's sum to more than 1, then normalise to unit interval.
        if len(zeds) and zeds[-1] > 1:
            # there may be no knots
            zeds /= zeds[-1]
            zeds = np.clip(zeds, 0, 1)

        # note - this means you shouldn't use the same Spline more than once in
        # a Component, because only the first use will be detected.
        try:
            loc = structure.index(self)
            # figure out SLDs for the bracketing Components.
            # note the use of the modulus operator. This means that if the
            # Spline is at the end, then the right most Component will be
            # assumed to be the first Component. This is to aid the use of
            # Spline in a Stack.
            left_component = structure[loc - 1]
            right_component = structure[(loc + 1) % len(structure)]
        except ValueError:
            raise ValueError("Spline didn't appear to be part of a super"
                             " Structure")

        if (isinstance(left_component, Spline)
                or isinstance(right_component, Spline)):
            raise ValueError("Spline must be bracketed by Components that"
                             " aren't Splines.")

        vs = np.array(self.vs)

        left_sld = Structure.overall_sld(
            np.atleast_2d(left_component.slabs(structure)[-1]),
            structure.solvent)[..., 1]

        right_sld = Structure.overall_sld(
            np.atleast_2d(right_component.slabs(structure)[0]),
            structure.solvent)[..., 1]

        if self.zgrad:
            zeds = np.concatenate([[-1.1, 0 - EPS], zeds, [1 + EPS, 2.1]])
            vs = np.concatenate([left_sld, left_sld, vs, right_sld, right_sld])
        else:
            zeds = np.concatenate([[0 - EPS], zeds, [1 + EPS]])
            vs = np.concatenate([left_sld, vs, right_sld])

        # cache the interpolator
        cache_zeds = self.__cached_interpolator['zeds']
        cache_vs = self.__cached_interpolator['vs']
        cache_extent = self.__cached_interpolator['extent']

        # you don't need to recreate the interpolator
        if (np.array_equal(zeds, cache_zeds) and np.array_equal(vs, cache_vs)
                and np.equal(self.extent, cache_extent)):
            return self.__cached_interpolator['interp']
        else:
            self.__cached_interpolator['zeds'] = zeds
            self.__cached_interpolator['vs'] = vs
            self.__cached_interpolator['extent'] = float(self.extent)

        # TODO make vfp zero for z > self.extent
        interpolator = self.interpolator(zeds, vs)
        self.__cached_interpolator['interp'] = interpolator
        return interpolator
Exemplo n.º 15
0
def phase_problem_plot(flag):
    if flag != "SLD" and flag != "ACF":
        raise Exception("Invalid flag to plot")

    qvals = np.linspace(0, 0.2, 1025)[1:]
    sld1 = SLD(0, 0)
    sld3 = SLD(2.074, 0)

    layer1 = sld1(0, 0)
    layer3 = sld3(0, 0)

    fig = plt.figure(figsize=(10, 7.5))
    gs = gridspec.GridSpec(2, 1)
    ax1 = plt.subplot(gs[0, 0])
    ax2 = plt.subplot(gs[1, 0])
    colors = [_fig_params.colors[0], _fig_params.colors[1]]
    ls = ['-', ':']
    for i in [0, 1]:
        sld20 = SLD(6.335 - i, 0)
        sld21 = SLD(6.335 + i, 0)
        layer20 = sld20(100, 0)
        layer21 = sld21(100, 0)
        structure = Structure(layer1 | layer20 | layer21 | layer3)
        z, rho = structure.sld_profile()
        drho = (rho[1:] - rho[:-1]) / (z[1:] - z[:-1])
        z_ = 0.5 * (z[:-1] + z[1:])
        acf = autocorr(drho)
        z_acf = z_ - z_.min()
        z_acf = np.hstack((-np.flip(z_acf)[:-1], z_acf))

        if flag == 'SLD':
            ax1.plot(z, rho, color=colors[i], ls=ls[i])
            ax2.semilogy(qvals,
                         ReflectModel(structure, dq=0.0).model(qvals),
                         color=colors[i],
                         ls=ls[i])

        else:
            ax1.stem(z_,
                     drho,
                     linefmt='C{}'.format(i) + ls[i],
                     basefmt='C{}'.format(i) + ls[i],
                     markerfmt=' ',
                     use_line_collection=True)
            ax2.stem(z_acf,
                     acf,
                     linefmt='C{}'.format(i) + ls[i],
                     basefmt='C{}'.format(i) + ls[i],
                     markerfmt=' ',
                     use_line_collection=True)

    if flag == 'SLD':
        ax1.set_xlabel(r'$z$/Å')
        ax1.set_ylabel(r'$\rho(z)$/Å$^{-2}$')

        ax2.set_xlabel(r'$q$/Å')
        ax2.set_ylabel(r'$R(q)$')
        ax1.text(0.025,
                 0.95,
                 '(a)',
                 horizontalalignment='left',
                 verticalalignment='top',
                 transform=ax1.transAxes)

    else:
        ax1.set_xlabel(r'$z$/Å')
        ax1.set_ylabel(r'$\rho\'(z)$/Å$^{-3}$')

        ax2.set_xlabel(r'$z$/Å')
        ax2.set_ylabel("$ \\rm{ACF}_{\\rho'}(z)/ \\AA^{-5}$")
        ax1.text(0.975,
                 0.95,
                 '(a)',
                 horizontalalignment='right',
                 verticalalignment='top',
                 transform=ax1.transAxes)

    ax2.text(0.975,
             0.95,
             '(b)',
             horizontalalignment='right',
             verticalalignment='top',
             transform=ax2.transAxes)

    plt.tight_layout()
    figfilename = f"phase_problem_{flag}.pdf"
    plt.savefig(figfilename)
    print(f"Figure saved as {figfilename}")
    plt.close()