Commit f34f2592 authored by Eiffert, Brett's avatar Eiffert, Brett
Browse files

add dataloader and r curve generator

parent fc726995
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
{
    "parameters": {
        "q_min": 0.008,
        "q_max": 0.2,
        "step_size": 0.015,
        "FINAL_SEI_SLD": 6.13,
        "SIMULATE_ERRORS": true,
        "ERR": 0.15,
        "total_time": 50,
        "transition_time": 3,
        "transition_midpoint": 15 
    },
    "materials": [
        {
            "name": "Si", 
            "rho": 2.07, 
            "irho": 0, 
            "thickness": 0, 
            "roughness": 0
        },
        {
            "name": "THF", 
            "rho": 6.13, 
            "irho": 0, 
            "thickness": 0, 
            "roughness": 43.77
        },
        {
            "name": "Ti", 
            "rho": -1.238, 
            "irho": 0, 
            "thickness": 52.91, 
            "roughness": 12.7
        },
        {
            "name": "Cu", 
            "rho": 6.446, 
            "irho": 0, 
            "thickness": 566.1, 
            "roughness": 9.736
        },
        {
            "name": "material", 
            "rho": -1.648, 
            "irho": 0, 
            "thickness": 21.73, 
            "roughness": 18.22
        },
        {
            "name": "SEI", 
            "rho": 4.581, 
            "irho": 0, 
            "thickness": 177.7, 
            "roughness": 23.04
        }
    ]
    
}
+71 −0
Original line number Diff line number Diff line
from refl1d.names import *

class DataLoader:

    def __init__(self, json_dict: dict):
        """Initialize the class.

        Parameters
        ----------
        json_dict : json dictionary
            json dictionary of all parameters and materials to stack in a sample.
        """
        self.json_dict = json_dict
        self.q_min = json_dict["parameters"]["q_min"]
        self.q_max = json_dict["parameters"]["q_max"]
        self.step_size = json_dict["parameters"]["step"]
        self.final_sei_sld = json_dict["parameters"]["FINAL_SEI_SLD"]
        self.simulate_errors = json_dict["parameters"]["SIMULATE_ERRORS"]
        self.err = json_dict["parameters"]["ERR"]
        self.total_time = json_dict["parameters"]["total_time"]
        self.transition_time = json_dict["parameters"]["transition_time"]
        self.transition_midpoint = json_dict["parameters"]["transition_midpoint"]
        self.sample = self.create_sample_from_json(json_dict["materials"])

    def create_slab_chunk(self, material : dict) -> "Slab":
        
        """Return a slab chunk built from given configuration.

        Parameters
        ----------
        material : dictionary
            Single material dictionary to turn into slab chunk.

        Returns
        -------
        Slab
            The slab chunk instance.
        """

        slab = Slab(
            material=SLD(
                name=material["name"],
                rho=material["rho"],
                irho=material["irho"],
            ),
            thickness=material["thickness"],
            interface=material["roughness"],
        )

        return slab

    def create_sample_from_json(self, json_object : list) -> "Slab | Stack":

        """Return a slab instance built from given configuration.

        Parameters
        ----------
        json_object : list
            The sample configuration dictionary list.

        Returns
        -------
        Slab
            The slab instance.
        """

        sample = self.create_slab_chunk(json_object[0])
        for i in range(1, len(json_object)):
            sample = sample | self.create_slab_chunk(json_object[i])  

        return sample
 No newline at end of file
+210 −0
Original line number Diff line number Diff line
import json

import numpy as np
import math

from refl1d.names import *

from dataloader import DataLoader

class RCurveGenerator:

    def __init__(self, data : DataLoader):

        """Initialize the class.

        Parameters
        ----------
        data : DataLoader object
            Object of parsed data to use with RCurveGenerator and related functions
        """

        self.data = data
        self.probe, self.tr_probe = self.create_probes(data.q_min, data.q_max, res=data.step)
        self.expt = Experiment(probe=self.probe, sample=self.data.sample)
        self.r_final, self.r_init = self.get_states(self.expt, self.data.final_sei_sld, self.data.simulate_errors, self.data.err)
        self.tr_expt = Experiment(probe=self.tr_probe, sample=self.data.sample)
        self.tr_data, self.rho_data = self.generate_tNR(self.tr_expt, self.data.total_time, self.data.transition_time, self.data.transition_midpoint, self.data.final_sei_sld, self.data.simulate_errors, self.data.err)

    def create_probes(self, q_min : float, q_max : float, step_size : float, resolution : float = 0.028) -> tuple:
        
        """Returns two probes, one using the full data and one with a slice, in the form of a tuple.

        Parameters
        ----------
        q_min : float
            minimum of the q range

        q_max : float
            maximum of the q range

        res : float
            step size between min and max

        Returns
        -------
        tuple
            tuple containing both relevant probes
        """

        q = np.arange(np.log(q_min), np.log(q_max), step_size)
        q = np.exp(q)

        dq = resolution*q

        # Time-resolved Q range
        q_tr = q[50:130]
        dq_tr = dq[50:130]

        probe = QProbe(q, dq, data=None)

        # If using data for fits, replace data by the data to fit:
        # probe = QProbe(q, dq, data=(data, errors))

        tr_probe = QProbe(q_tr, dq_tr, data=None)

        return probe, tr_probe
    
    def get_states(self, expt, final_sei_sld, simulate_errors, err) -> tuple:

        """Returns a tuple containing both the initial and final r states.

        Parameters
        ----------
        expt : Experiment
            Experiment object - full range
        final_sei_sld : float
            final sei sld contant
        simulate_errors : boolean
            boolean indicating whether you want to include error or not in simulation
        err : float
            error constant

        Returns
        -------
        tuple
            Tuple of both r_final and r_init lists
        """

        # Final state ##################################################################
        _, r_final = expt.reflectivity()
        if simulate_errors:
            r_final = np.random.normal(r_final, err*r_final)


        # Initial state ################################################################
        expt.sample['SEI'].material.rho.value = final_sei_sld
        expt.update()
        _, r_init = expt.reflectivity()
        if simulate_errors:
            r_init = np.random.normal(r_init, err*r_init)

        return r_final, r_init
    
    def generate_tNR(self, tr_expt, total_time, transition_time, transition_midpoint, final_sei_sld, simulate_errors, err) -> tuple:
        """Return a tuple built containing tr_data and rho_data.

        Parameters
        ----------
        tr_expt : Experiment
            Subset of experiment
        total_time : int
            
        transition_time : int

        transition_midpoint : int

        final_sei_sld : float

        simulate_errors : bool

        err : float

        Returns
        -------
        tuple
            tuple of both tr_data and rho_data lists
        """

        tr_data = []
        rho_data = []
        for i in range(total_time):
            # This is a simple ERF transition, but it could be any function!
            rho_sei = final_sei_sld - (final_sei_sld-4.581) * (1 + math.erf((i-transition_midpoint)/transition_time)) / 2
        
            tr_expt.sample['SEI'].material.rho.value = rho_sei
            tr_expt.update()
            _, _r = tr_expt.reflectivity()
            if simulate_errors:
                _r = np.random.normal(_r, err*_r)

            rho_data.append(rho_sei)
            tr_data.append(_r)    
        
        tr_data = np.asarray(tr_data)
        return tr_data, rho_data
    
    def get_r_final(self) -> list:

        """Returns a list from the RCurveGenerator object instance.

        Returns
        -------
        list
            r_final list
        """

        return self.r_final

    def get_r_init(self) -> list:

        """Returns a list from the object instance.

        Returns
        -------
        list
            r_init list
        """

        return self.r_init

    def get_tr_data(self) -> list:
        
        """Returns a list from the object instance.

        Returns
        -------
        list
            tr_data list
        """

        return self.tr_data

    def get_rho_data(self) -> list:

        """Returns a list from the object instance.

        Returns
        -------
        list
            rho_data list
        """

        return self.rho_data
    
""" USE EXAMPLE
if __name__ == "__main__":
    f = open("data.json","r")
    data = json.load(f)
    dataloader = DataLoader(data)
    rc = RCurveGenerator(dataloader)
    print(rc.get_r_init())
    
    #gen = RCurveGenerator(0.008, 0.2)
    #print(gen.q)
"""