<commit_before># -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Name:        zos.py
# Purpose:     COM interface class for easy ZOS-API
# Licence:     MIT License
#              This file is subject to the terms and conditions of the MIT License.
#              For further details, please refer to LICENSE.txt
#-------------------------------------------------------------------------------
"""Helper functions for accessing Zemax ZOS API from Python in standalone mode. 
"""
from __future__ import division, print_function
import os as _os
import win32com.client as _comclient
import warnings as _warnings
from pyzos.zosutils import (ZOSPropMapper as _ZOSPropMapper, 
                            replicate_methods as _replicate_methods,
                            wrapped_zos_object as wrapped_zos_object)

#%%
Const = None  # Constants (placeholder)
#%%
class _ConnectionError(Exception): pass 
class _InitializationError(Exception): pass
class _ZOSSystemError(Exception): pass

#%%
class _PyZOSApp(object):
    app = None
    connect = None
    
    def __new__(cls):
        global Const
        if not cls.app:
            #TODO: Add relavent exceptions
            # ensure win32com support files for ZOSAPI_Interfaces are available,
            # generate if necessary.
            _comclient.gencache.EnsureModule('ZOSAPI_Interfaces', 0, 1, 0)
            edispatch = _comclient.gencache.EnsureDispatch
            cls.connect = edispatch('ZOSAPI.ZOSAPI_Connection')
            cls.app = cls.connect.CreateNewApplication()
            Const = type('Const', (), _comclient.constants.__dicts__[0]) # Constants class
        return cls.app

#%%
class OpticalSystem(object):
    """Wrapper for IOpticalSystem interface
    """
    _instantiated = False
    _pyzosapp = None
    
    # Managed properties (prefix with 'p' to ease identification)
    pIsNonAxial = _ZOSPropMapper('_iopticalsystem', 'IsNonAxial')
    pMode = _ZOSPropMapper('_iopticalsystem', 'Mode')
    pNeedsSave = _ZOSPropMapper('_iopticalsystem', 'NeedsSave')
    pSystemFile = _ZOSPropMapper('_iopticalsystem', 'SystemFile')
    pSystemID = _ZOSPropMapper('_iopticalsystem', 'SystemID')
    pSystemName = _ZOSPropMapper('_iopticalsystem', 'SystemName', setter=True)
    
    def __init__(self, mode=0):
        """ mode : sequential (0) or non-sequential (1)
        """
        
        if OpticalSystem._instantiated:
            self._iopticalsystem = OpticalSystem._pyzosapp.CreateNewSystem(mode) # wrapped object
        else:
            OpticalSystem._pyzosapp = _PyZOSApp()               # wrapped object
            self._iopticalsystem = OpticalSystem._pyzosapp.GetSystemAt(0) # PrimarySystem
            if mode == 1:
                self._iopticalsystem.MakeNonSequential()
            OpticalSystem._instantiated = True
        
        ## patch methods from IOpticalSystem to the instance
        _replicate_methods(self._iopticalsystem, self)
            
    def __getattr__(self, attrname):
        """handle any method calls that were not accounted for by 
           `_replicate_methods` (shouldn't happen generally), or 
           property calls that are not managed.
        """
        #print('__getattr__ in OpticalSystem called for', attrname) ##TODO: remove print later
        return getattr(self._iopticalsystem, attrname)
    

    #%% Overridden Methods
    def SaveAs(self, filename):
        """Saves the current system to the specified file. 

        @param filename: absolute path (string)
        @return: None
        @raise: ValueError if path (excluding the zemax file name) is not valid

        All future calls to `Save()`  will use the same file.
        """
        directory = _os.path.split(filename)[0]
        if not _os.path.exists(directory):
            raise ValueError('{} is not valid.'.format(directory))
        else:
            self._iopticalsystem.SaveAs(filename)

    #%% Overridden Properties
    @property
    def pConnectIsAlive(self):
        """ZOS-API connection active/inactive status"""
        return _PyZOSApp.connect.IsAlive
    
    @property
    def pAnalyses(self):
        """Gets the analyses for the current system (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.Analyses)
    
    @property
    def pLDE(self):
        """Gets the lens data editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.LDE)
    
    @property
    def pMCE(self):
        """Gets the Gets the multi-configuration editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.MCE)
    
    @property
    def pMFE(self):
        """Gets the Gets the multi-function editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.MFE)

    @property
    def pNCE(self):
        """Gets the Gets the Non-Sequential Component editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.NCE)
    
    @property
    def pSystemData(self):
        """Gets the System Explorer interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.SystemData)

    @property
    def pTDE(self):
        """Gets the tolerance data editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.TDE)

    @property
    def pTheApplication(self):
        """The ZOSAPI_Application (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.TheApplication)
    
    @property
    def pTools(self):
        """Gets an interface used to run various tools on the optical system (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.Tools)
    
    # Extra added helper methods 
    def zInsertNewSurfaceAt(self, surfNum):
        if self.pMode == 0:
            lde = self.pLDE
            lde.InsertNewSurfaceAt(surfNum)
        else:
            raise NotImplementedError('Function not implemented for non-sequential mode')

    def zSetSurfaceData(self, surfNum, radius=None, thick=None, material=None, semidia=None, conic=None, comment=None):
        if self.pMode == 0: # sequential mode
            surf = self.pLDE.GetSurfaceAt(surfNum)
            if radius is not None:
                surf.pRadius = radius<commit_msg>added custom method to OpticalSystem class<commit_after># -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Name:        zos.py
# Purpose:     COM interface class for easy ZOS-API
# Licence:     MIT License
#              This file is subject to the terms and conditions of the MIT License.
#              For further details, please refer to LICENSE.txt
#-------------------------------------------------------------------------------
"""Helper functions for accessing Zemax ZOS API from Python in standalone mode. 
"""
from __future__ import division, print_function
import os as _os
import collections as _co
import win32com.client as _comclient
import warnings as _warnings
from pyzos.zosutils import (ZOSPropMapper as _ZOSPropMapper, 
                            replicate_methods as _replicate_methods,
                            wrapped_zos_object as wrapped_zos_object)

#%% Global variables
Const = None  # Constants (placeholder)

#%% Custom Exceptions
class _ConnectionError(Exception): pass 
class _InitializationError(Exception): pass
class _ZOSSystemError(Exception): pass

#%% ZOS API Application Class
class _PyZOSApp(object):
    app = None
    connect = None
    
    def __new__(cls):
        global Const
        if not cls.app:
            #TODO: Add relavent exceptions
            # ensure win32com support files for ZOSAPI_Interfaces are available,
            # generate if necessary.
            _comclient.gencache.EnsureModule('ZOSAPI_Interfaces', 0, 1, 0)
            edispatch = _comclient.gencache.EnsureDispatch
            cls.connect = edispatch('ZOSAPI.ZOSAPI_Connection')
            cls.app = cls.connect.CreateNewApplication()
            Const = type('Const', (), _comclient.constants.__dicts__[0]) # Constants class
        return cls.app

#%% Optical System Class
class OpticalSystem(object):
    """Wrapper for IOpticalSystem interface
    """
    _instantiated = False
    _pyzosapp = None
    
    # Managed properties (prefix with 'p' to ease identification)
    pIsNonAxial = _ZOSPropMapper('_iopticalsystem', 'IsNonAxial')
    pMode = _ZOSPropMapper('_iopticalsystem', 'Mode')
    pNeedsSave = _ZOSPropMapper('_iopticalsystem', 'NeedsSave')
    pSystemFile = _ZOSPropMapper('_iopticalsystem', 'SystemFile')
    pSystemID = _ZOSPropMapper('_iopticalsystem', 'SystemID')
    pSystemName = _ZOSPropMapper('_iopticalsystem', 'SystemName', setter=True)
    
    def __init__(self, mode=0):
        """ mode : sequential (0) or non-sequential (1)
        """
        
        if OpticalSystem._instantiated:
            self._iopticalsystem = OpticalSystem._pyzosapp.CreateNewSystem(mode) # wrapped object
        else:
            OpticalSystem._pyzosapp = _PyZOSApp()               # wrapped object
            self._iopticalsystem = OpticalSystem._pyzosapp.GetSystemAt(0) # PrimarySystem
            if mode == 1:
                self._iopticalsystem.MakeNonSequential()
            OpticalSystem._instantiated = True
        
        ## patch methods from IOpticalSystem to the instance
        _replicate_methods(self._iopticalsystem, self)
            
    def __getattr__(self, attrname):
        """handle any method calls that were not accounted for by 
           `_replicate_methods` (shouldn't happen generally), or 
           property calls that are not managed.
        """
        #print('__getattr__ in OpticalSystem called for', attrname) ##TODO: remove print later
        return getattr(self._iopticalsystem, attrname)
    

    #%% Overridden Methods
    def SaveAs(self, filename):
        """Saves the current system to the specified file. 

        @param filename: absolute path (string)
        @return: None
        @raise: ValueError if path (excluding the zemax file name) is not valid

        All future calls to `Save()`  will use the same file.
        """
        directory = _os.path.split(filename)[0]
        if not _os.path.exists(directory):
            raise ValueError('{} is not valid.'.format(directory))
        else:
            self._iopticalsystem.SaveAs(filename)

    #%% Overridden Properties
    @property
    def pConnectIsAlive(self):
        """ZOS-API connection active/inactive status"""
        return _PyZOSApp.connect.IsAlive
    
    @property
    def pAnalyses(self):
        """Gets the analyses for the current system (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.Analyses)
    
    @property
    def pLDE(self):
        """Gets the lens data editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.LDE)
    
    @property
    def pMCE(self):
        """Gets the Gets the multi-configuration editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.MCE)
    
    @property
    def pMFE(self):
        """Gets the Gets the multi-function editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.MFE)

    @property
    def pNCE(self):
        """Gets the Gets the Non-Sequential Component editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.NCE)
    
    @property
    def pSystemData(self):
        """Gets the System Explorer interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.SystemData)

    @property
    def pTDE(self):
        """Gets the tolerance data editor interface (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.TDE)

    @property
    def pTheApplication(self):
        """The ZOSAPI_Application (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.TheApplication)
    
    @property
    def pTools(self):
        """Gets an interface used to run various tools on the optical system (wrapped)"""
        return wrapped_zos_object(self._iopticalsystem.Tools)
    
    #%% Extra/ Custom methods 
    def zGetSurfaceData(self, surfNum):
        """Return surface data"""
        if self.pMode == 0: # Sequential mode
            surf_data = _co.namedtuple('surface_data', ['radius', 'thick', 'material', 'semidia', 
                                                        'conic', 'comment'])
            surf = self.pLDE.GetSurfaceAt(surfNum)
            return surf_data(surf.pRadius, surf.pThickness, surf.pMaterial, surf.pSemiDiameter,
                             surf.pConic, surf.pComment)
        else:
            raise NotImplementedError('Function not implemented for non-sequential mode')

    def zInsertNewSurfaceAt(self, surfNum):
        if self.pMode == 0:
            lde = self.pLDE
            lde.InsertNewSurfaceAt(surfNum)
        else:
            raise NotImplementedError('Function not implemented for non-sequential mode')

    def zSetSurfaceData(self, surfNum, radius=None, thick=None, material=None, semidia=None, 
                        conic=None, comment=None):
        """Sets surface data"""
        if self.pMode == 0: # Sequential mode
            surf = self.pLDE.GetSurfaceAt(surfNum)
            if radius is not None:
                surf.pRadius = radius
{'fraction_non_alphanumeric': 0.11032001798695945, 'fraction_numerical': 0.00262309825376602, 'mean_word_length': 2.4303341902313624, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3042410', 'n_tokens_mistral': 3783, 'n_tokens_neox': 3615, 'n_words': 995}