""" Write Inputfile for SRIM and TRIM calculations  #( c)2018
  #( c)2018
"""  #( c)2018
  #( c)2018
  #( c)2018
class AutoTRIM(object):  #( c)2018
    def __init__(self, mode=1, restart_directroy=None):  #( c)2018
        """Writes a file AUTOTRIM to TRIM directory for autostart  #( c)2018
  #( c)2018
        Parameters  #( c)2018
        ----------  #( c)2018
        mode : int  #( c)2018
            (0) TRIM runs normally, (1) TRIM runs without keyboard input,  #( c)2018
            (2) TRIM resumes running its last saved calculation. Default 1  #( c)2018
            and is really the only sane option when using Python for automation  #( c)2018
        restart_directory : str  #( c)2018
            currently not implemented. default None  #( c)2018
        """  #( c)2018
        self._mode = mode  #( c)2018
  #( c)2018
    def write(self):  #( c)2018
        """ write AUTOTRIM in current directory """  #( c)2018
        with open('TRIMAUTO', 'w') as f:  #( c)2018
            f.write('{}'.format(self._mode))  #( c)2018
  #( c)2018
  #( c)2018
class TRIMInput(object):  #( c)2018
    """Input File representation of TRIM run  #( c)2018
  #( c)2018
    Parameters  #( c)2018
    ----------  #( c)2018
    trim : :class:`srim.srim.TRIM`  #( c)2018
        A TRIM calculation to use for writing a file  #( c)2018
    """  #( c)2018
    newline = '\r\n' # TRIM uses microsoft newlines  #( c)2018
  #( c)2018
    def __init__(self, trim):  #( c)2018
        self._trim = trim  #( c)2018
  #( c)2018
    @property  #( c)2018
    def srim_num_elements(self):  #( c)2018
        """Number of unique elements in target (layer elements treated as unique)"""  #( c)2018
        return sum(len(layer.elements) for layer in self._trim.target.layers)  #( c)2018
  #( c)2018
    def _write_title(self):  #( c)2018
        return (  #( c)2018
            'This file controls TRIM Calculations '  #( c)2018
            'generated by pysrim'  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_ion(self):  #( c)2018
        return (  #( c)2018
            'Ion: Z, Mass [amu], Energy [keV], Angle [degrees], '  #( c)2018
            'Number Ions, Bragg Corr, AutoSave Number'  #( c)2018
        ) + self.newline + '{} {} {} {} {} {} {}'.format(  #( c)2018
            self._trim.ion.atomic_number,  #( c)2018
            self._trim.ion.mass,  #( c)2018
            self._trim.ion.energy / 1000.0, # eV -> keV  #( c)2018
            self._trim.settings.angle_ions,  #( c)2018
            self._trim.number_ions,  #( c)2018
            self._trim.settings.bragg_correction,  #( c)2018
            self._trim.settings.autosave  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_cascade_options(self):  #( c)2018
        return (  #( c)2018
            'Cascades(1=Kitchn-Peese, 2=Full-Cascade, 3=Sputtering, '  #( c)2018
            '4-5=Ions;6-7=Neutrons), Random Number Seed, Reminders'  #( c)2018
        ) + self.newline + '{} {} {}'.format(  #( c)2018
        self._trim.calculation,  #( c)2018
            self._trim.settings.random_seed,  #( c)2018
            self._trim.settings.reminders  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_plot_on_off(self):  #( c)2018
        return (  #( c)2018
            'Diskfiles (0=no,1=yes): RANGES.txt, BACKSCATT.txt, '  #( c)2018
            'TRANSMIT.txt, Sputtered, COLLISIONS.txt(0=no, 1=Ion, '  #( c)2018
            '2=Ion+Recoils), Special EXYZ.txt file'  #( c)2018
        ) + self.newline + '{} {} {} {} {} {}'.format(  #( c)2018
            self._trim.settings.ranges,  #( c)2018
            self._trim.settings.backscattered,  #( c)2018
            self._trim.settings.transmit,  #( c)2018
            self._trim.settings.sputtered,  #( c)2018
            self._trim.settings.collisions,  #( c)2018
            self._trim.settings.exyz  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_target(self):  #( c)2018
        return (  #( c)2018
            'Target material : Number of Elements, Number of Layers'  #( c)2018
        ) + self.newline + '"{}" {} {}'.format(  #( c)2018
            self._trim.settings.description,  #( c)2018
            self.srim_num_elements,  #( c)2018
            len(self._trim.target.layers),  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_plot_options(self):  #( c)2018
        return (  #( c)2018
            'PlotType (0-5); Plot Depths: Xmin, Xmax(Ang.) '  #( c)2018
            '[=0 0 for Viewing Full Target]'  #( c)2018
        ) + self.newline + '{} {} {}'.format(  #( c)2018
            self._trim.settings.plot_mode,  #( c)2018
            self._trim.settings.plot_xmin,  #( c)2018
            self._trim.settings.plot_xmax  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_elements(self):  #( c)2018
        elements_str = (  #( c)2018
            'Target Elements:    Z   Mass [amu]'  #( c)2018
        ) + self.newline  #( c)2018
        index = 1  #( c)2018
        for layer in self._trim.target.layers:  #( c)2018
            for element in layer.elements:  #( c)2018
                elements_str += 'Atom {} = {} =     {} {}'.format(  #( c)2018
                    index,  #( c)2018
                    element.symbol,  #( c)2018
                    element.atomic_number,  #( c)2018
                    element.mass  #( c)2018
                ) + self.newline  #( c)2018
                index += 1  #( c)2018
        return elements_str  #( c)2018
  #( c)2018
    def _write_layer(self):  #( c)2018
        layers_str_header_1 = 'Layer    Layer Name   Width Density'  #( c)2018
        layers_str_header_2 = 'Number   Description  (Ang) (g/cm^3)'  #( c)2018
        layers_str = []  #( c)2018
  #( c)2018
        for layer in self._trim.target.layers:  #( c)2018
            for element in layer.elements:  #( c)2018
                layers_str_header_1 += '  {}({})'.format(element.symbol, element.atomic_number)  #( c)2018
                layers_str_header_2 += 'Stoich'  #( c)2018
  #( c)2018
        element_index = 0  #( c)2018
        for layer_index, layer in enumerate(self._trim.target.layers, start=1):  #( c)2018
            layer_str = '{} "{}" {} {}'.format(layer_index, layer.name, layer.width, layer.density)  #( c)2018
            layer_str += ' 0.0' * element_index  #( c)2018
            for element in layer.elements:  #( c)2018
                layer_str += ' {} '.format(layer.elements[element]['stoich'])  #( c)2018
            layer_str += ' 0.0' * (self.srim_num_elements - element_index - len(layer.elements))  #( c)2018
            element_index += len(layer.elements)  #( c)2018
            layers_str.append(layer_str)  #( c)2018
        return self.newline.join([layers_str_header_1, layers_str_header_2] + layers_str) + self.newline  #( c)2018
  #( c)2018
    def _write_solid_gas(self):  #( c)2018
        return (  #( c)2018
            '0  Target layer phases (0=Solid, 1=Gas)'  #( c)2018
        ) + self.newline + ' '.join(str(layer.phase) for layer in self._trim.target.layers) + self.newline  #( c)2018
  #( c)2018
    def _write_bragg_correction(self):  #( c)2018
        return (  #( c)2018
            'Target Compound Corrections (Bragg)'  #( c)2018
        ) + self.newline + ' 1' * len(self._trim.target.layers) + self.newline  #( c)2018
  #( c)2018
    def _write_displacement_energies(self):  #( c)2018
        ed_str = (  #( c)2018
            'Individual target atom displacement energies (eV)'  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
        for layer in self._trim.target.layers:  #( c)2018
            for element in layer.elements:  #( c)2018
                ed_str += ' {}'.format(layer.elements[element]['E_d'])  #( c)2018
        return ed_str + self.newline  #( c)2018
  #( c)2018
    def _write_lattice_binding(self):  #( c)2018
        lattice_str = (  #( c)2018
            'Individual target atom lattice binding energies (eV)'  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
        for layer in self._trim.target.layers:  #( c)2018
            for element in layer.elements:  #( c)2018
                lattice_str += ' {}'.format(layer.elements[element]['lattice'])  #( c)2018
        return lattice_str + self.newline  #( c)2018
  #( c)2018
    def _write_surface_binding(self):  #( c)2018
        surface_str = (  #( c)2018
            'Individual target atom surface binding energies (eV)'  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
        for layer in self._trim.target.layers:  #( c)2018
            for element in layer.elements:  #( c)2018
                surface_str += ' {}'.format(layer.elements[element]['surface'])  #( c)2018
        return surface_str + self.newline  #( c)2018
  #( c)2018
    def _write_version(self):  #( c)2018
        return (  #( c)2018
            'Stopping Power Version (1=2011, 0=2011)'  #( c)2018
        ) + self.newline + '{}'.format(self._trim.settings.version) + self.newline  #( c)2018
  #( c)2018
    def write(self):  #( c)2018
        """Write TRIMInput class to ``TRIM.IN``"""  #( c)2018
        with open('TRIM.IN', 'wb') as f:  #( c)2018
            methods = [  #( c)2018
                self._write_title,  #( c)2018
                self._write_ion,  #( c)2018
                self._write_cascade_options,  #( c)2018
                self._write_plot_on_off,  #( c)2018
                self._write_target,  #( c)2018
                self._write_plot_options,  #( c)2018
                self._write_elements,  #( c)2018
                self._write_layer,  #( c)2018
                self._write_solid_gas,  #( c)2018
                self._write_bragg_correction,  #( c)2018
                self._write_displacement_energies,  #( c)2018
                self._write_lattice_binding,  #( c)2018
                self._write_surface_binding,  #( c)2018
                self._write_version  #( c)2018
            ]  #( c)2018
  #( c)2018
            input_str = ''  #( c)2018
            for method in methods:  #( c)2018
                input_str += method.__call__()  #( c)2018
  #( c)2018
            f.write(input_str.encode('utf-8'))  #( c)2018
  #( c)2018
  #( c)2018
class SRInput(object):  #( c)2018
    """Input file for Stopping and Range (Calculations)  #( c)2018
  #( c)2018
    Parameters  #( c)2018
    ----------  #( c)2018
    sr : :class:`srim.srim.SR`  #( c)2018
        SR class to use for writting file  #( c)2018
    """  #( c)2018
    newline = '\r\n' # TRIM uses microsoft newlines  #( c)2018
  #( c)2018
    def __init__(self, sr):  #( c)2018
        self._sr = sr  #( c)2018
  #( c)2018
    def _write_filename(self):  #( c)2018
        return (  #( c)2018
            '---Stopping/Range Input Data (Number-format: Period = Decimal Point)'  #( c)2018
        ) + self.newline + (  #( c)2018
            '---Output File Name'  #( c)2018
        ) + self.newline + '{}'.format(  #( c)2018
            self._sr.settings.output_filename  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_ion(self):  #( c)2018
        return (  #( c)2018
            '---Ion(Z), Ion Mass(u)'  #( c)2018
        ) + self.newline + '{} {}'.format(  #( c)2018
            self._sr.ion.atomic_number,  #( c)2018
            self._sr.ion.mass  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_layer_info(self):  #( c)2018
        return (  #( c)2018
            '---Target Data: (Solid=0,Gas=1), Density(g/cm3), Compound Corr.'  #( c)2018
        ) + self.newline + '{} {} {}'.format(  #( c)2018
            self._sr.layer.phase,  #( c)2018
            self._sr.layer.density,  #( c)2018
            self._sr.settings.correction  #( c)2018
        ) + self.newline + (  #( c)2018
            '---Number of Target Elements'  #( c)2018
        ) + self.newline + '{}'.format(  #( c)2018
            len(self._sr.layer.elements)  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_elements(self):  #( c)2018
        elements_str = (  #( c)2018
            '---Target Elements: (Z), Target name, Stoich, Target Mass(u)'  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
        for element in self._sr.layer.elements:  #( c)2018
            elements_str += '{} "{}" {} {}'.format(  #( c)2018
                element.atomic_number,  #( c)2018
                element.name,  #( c)2018
                self._sr.layer.elements[element]['stoich'],  #( c)2018
                element.mass  #( c)2018
            ) + self.newline  #( c)2018
        return elements_str  #( c)2018
  #( c)2018
    def _write_output_options(self):  #( c)2018
        return (  #( c)2018
            '---Output Stopping Units (1-8)'  #( c)2018
        ) + self.newline + '{}'.format(  #( c)2018
            self._sr.settings.output_type  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def _write_ion_energy_range(self):  #( c)2018
        return (  #( c)2018
            '---Ion Energy : E-Min(keV), E-Max(keV)'  #( c)2018
        ) + self.newline + '{} {}'.format(  #( c)2018
            self._sr.settings.energy_min / 1.0e3,  #( c)2018
            self._sr.ion.energy / 1.0e3  #( c)2018
        ) + self.newline  #( c)2018
  #( c)2018
    def write(self):  #( c)2018
        """Write SR calcualtion to ``SR.IN``"""  #( c)2018
        with open('SR.IN', 'wb') as f:  #( c)2018
            methods = [  #( c)2018
                self._write_filename,  #( c)2018
                self._write_ion,  #( c)2018
                self._write_layer_info,  #( c)2018
                self._write_elements,  #( c)2018
                self._write_output_options,  #( c)2018
                self._write_ion_energy_range  #( c)2018
            ]  #( c)2018
  #( c)2018
            input_str = ''  #( c)2018
            for method in methods:  #( c)2018
                input_str += method.__call__()  #( c)2018
  #( c)2018
            f.write(input_str.encode('utf-8'))  #( c)2018
