<commit_before># -*- coding: utf-8 -*-
import time
import numpy as np
from scipy import interpolate
import astropy.units as u
import astropy.constants as const
import os, inspect
try:
    import cPickle as pickle
except:
    import pickle
import hashlib
from EXOSIMS.Prototypes.Completeness import Completeness
from EXOSIMS.util.eccanom import eccanom
from EXOSIMS.util.deltaMag import deltaMag

class BrownCompleteness(Completeness):
    """Completeness class template
    
    This class contains all variables and methods necessary to perform 
    Completeness Module calculations in exoplanet mission simulation.
    
    Args:
        \*\*specs: 
            user specified values
    
    Attributes:
        Nplanets (integer):
            Number of planets for initial completeness Monte Carlo simulation
        classpath (string):
            Path on disk to Brown Completeness
        filename (string):
            Name of file where completeness interpolant is stored
        updates (float nx5 ndarray):
            Completeness values of successive observations of each star in the
            target list (initialized in gen_update)
        
    """
    
    def __init__(self, Nplanets=1e8, **specs):
        
        # bring in inherited Completeness prototype __init__ values
        Completeness.__init__(self, **specs)
        
        # Number of planets to sample
        self.Nplanets = int(Nplanets)
        
        # get path to completeness interpolant stored in a pickled .comp file
        self.classpath = os.path.split(inspect.getfile(self.__class__))[0]
        self.filename = specs['modules']['PlanetPopulation'] + specs['modules']['PlanetPhysicalModel']
        # get path to dynamic completeness array in a pickled .dcomp file
        self.dfilename = specs['modules']['PlanetPopulation'] + \
                        specs['modules']['PlanetPhysicalModel'] + \
                        specs['modules']['OpticalSystem'] + \
                        specs['modules']['StarCatalog'] + \
                        specs['modules']['TargetList']
        atts = self.PlanetPopulation.__dict__.keys()
        extstr = ''
        for att in sorted(atts, key=str.lower):
            if not callable(getattr(self.PlanetPopulation, att)) and att != 'PlanetPhysicalModel':
                extstr += '%s: ' % att + str(getattr(self.PlanetPopulation, att)) + ' '
        ext = hashlib.md5(extstr).hexdigest()
        self.filename += ext
        
#        atts = ['arange','erange','prange','Rprange','Mprange','scaleOrbits','constrainOrbits']
#        
#        extstr = ''
#        for att in atts:
#            extstr += '%s: ' % att + str(getattr(self.PlanetPopulation, att)) + ' '
#        ext = hashlib.md5(extstr).hexdigest()
#        self.filename += ext

    def target_completeness(self, TL):
        """Generates completeness values for target stars
        
        This method is called from TargetList __init__ method.
        
        Args:
            TL (TargetList module):
                TargetList class object
            
        Returns:
            comp0 (float ndarray): 
                Completeness values for each target star
        
        """
        
        # set up "ensemble visit photometric and obscurational completeness"
        # interpolant for initial completeness values
        # bins for interpolant
        bins = 1000
        # xedges is array of separation values for interpolant
        if self.PlanetPopulation.constrainOrbits:
            xedges = np.linspace(0.0, self.PlanetPopulation.arange[1].to('AU').value, bins+1)
        else:
            xedges = np.linspace(0.0, self.PlanetPopulation.rrange[1].to('AU').value, bins+1)
        
        # yedges is array of delta magnitude values for interpolant
        ymin = -2.5*np.log10(float(self.PlanetPopulation.prange[1]*\
                (self.PlanetPopulation.Rprange[1]/self.PlanetPopulation.rrange[0])**2))
        ymax = -2.5*np.log10(float(self.PlanetPopulation.prange[0]*\
                (self.PlanetPopulation.Rprange[0]/self.PlanetPopulation.rrange[1])**2)*1e-11)
        yedges = np.linspace(ymin, ymax, bins+1)
        # number of planets for each Monte Carlo simulation
        nplan = int(np.min([1e6,self.Nplanets]))
        # number of simulations to perform (must be integer)
        steps = int(self.Nplanets/nplan)
        
        # path to 2D completeness pdf array for interpolation
        Cpath = os.path.join(self.classpath, self.filename+'.comp')
        Cpdf, xedges2, yedges2 = self.genC(Cpath, nplan, xedges, yedges, steps)

        xcent = 0.5*(xedges2[1:]+xedges2[:-1])
        ycent = 0.5*(yedges2[1:]+yedges2[:-1])
        xnew = np.hstack((0.0,xcent,self.PlanetPopulation.rrange[1].to('AU').value))
        ynew = np.hstack((ymin,ycent,ymax))
        Cpdf = np.pad(Cpdf,1,mode='constant')

        #save interpolant to object
        self.EVPOCpdf = interpolate.RectBivariateSpline(xnew, ynew, Cpdf.T)
        self.EVPOC = np.vectorize(self.EVPOCpdf.integral)
        self.xnew = xnew
        self.ynew = ynew  
            
        # calculate separations based on IWA
        OS = TL.OpticalSystem
        mode = filter(lambda mode: mode['detectionMode'] == True, OS.observingModes)[0]
        IWA = mode['IWA']
        OWA = mode['OWA']
        smin = np.tan(IWA)*TL.dist
        if np.isinf(OWA):
            smax = xedges[-1]*u.AU
        else:
            smax = np.tan(OWA)*TL.dist
        
        # calculate dMags based on limiting dMag
        dMagmax = OS.dMagLim 
        if self.PlanetPopulation.scaleOrbits:
            L = np.where(TL.L>0, TL.L, 1e-10) #take care of zero/negative values
            smin = smin/np.sqrt(L)
            smax = smax/np.sqrt(L)
            dMagmax -= 2.5*np.log10(L)
            comp0 = np.zeros(smin.shape)
            comp0[dMagmax>ymin] = self.EVPOC(smin[dMagmax>ymin].to('AU').value, smax[dMagmax>ymin].to('AU').value, 0.0, dMagmax[dMagmax>ymin])
        else:
            comp0 = self.EVPOC(smin.to('AU').value, smax.to('AU').value, 0.0, dMagmax)
        comp0[comp0<1e-6] = 0.0
        
        return comp0

    def gen_update(self, TL):
        """Generates dynamic completeness values for multiple visits of each 
        star in the target list
        
        Args:
            TL (TargetList module):
                TargetList class object
        
        """
        
        OS = TL.OpticalSystem
        PPop = TL.PlanetPopulation
        
        # get name for stored dynamic completeness updates array
        atts = PPop.__dict__.keys()
        extstr = ''
        for att in sorted(atts, key=str.lower):
            if not callable(getattr(PPop, att)) and att != 'PlanetPhysicalModel':
                extstr += '%s: ' % att + str(getattr(PPop, att))
        atts2 = ['IWA','OWA','dMagLim']
        for att in atts2:
            extstr += '%s: ' % att + str(getattr(OS, att)) + ' '
        extstr += 'nStars: ' + str(TL.nStars)
        ext = hashlib.md5(extstr).hexdigest()
        self.dfilename += ext 
        self.dfilename += '.dcomp'
        
        path = os.path.join(self.classpath, self.dfilename)
        # if the 2D completeness update array exists as a .dcomp file load it
        if os.path.exists(path):
            print 'Loading cached dynamic completeness array from "%s".' % path
            self.updates = pickle.load(open(path, 'rb'))
            print 'Dynamic completeness array loaded from cache.'
        else:
            # run Monte Carlo simulation and pickle the resulting array
            print 'Cached dynamic completeness array not found at "%s".' % path
            print 'Beginning dynamic completeness calculations'
            # dynamic completeness values: rows are stars, columns are number of visits
            self.updates = np.zeros((TL.nStars, 5))
            # number of planets to simulate
            nplan = int(2e4)
            # normalization time
            dt = 1e9*u.day
            # sample quantities which do not change in time
            a = PPop.gen_sma(nplan) # AU
            if PPop.constrainOrbits:
                e = PPop.gen_eccen_from_sma(nplan,a)
            else:
                e = PPop.gen_eccen(nplan)
            I = PPop.gen_I(nplan) # deg
            O = PPop.gen_O(nplan) # deg
            w = PPop.gen_w(nplan) # deg
            p = PPop.gen_albedo(nplan)
            Rp = PPop.gen_radius(nplan) # km
            Mp = PPop.gen_mass(nplan) # kg
            rmax = a*(1.+e)
            # sample quantity which will be updated
            M = np.random.uniform(high=2.*np.pi,size=nplan)
            newM = np.zeros((nplan,))
            # population values
            smin = (np.tan(OS.IWA)*TL.dist).to('AU')
            if np.isfinite(OS.OWA):
                smax = (np.tan(OS.OWA)*TL.dist).to('AU')
            else:
                smax = np.array([np.max(PPop.arange.to('AU').value)*\
                        (1.+np.max(PPop.erange))]*TL.nStars)*u.AU
            # fill dynamic completeness values
            for sInd in xrange(TL.nStars):
                mu = const.G*(Mp + TL.MsTrue[sInd])
                n = np.sqrt(mu/a**3)
                # remove rmax < smin 
                pInds = np.where(rmax > smin[sInd])[0]
                # calculate for 5 successive observations
                for num in xrange(5):<commit_msg>fixing dynamic completeness hash<commit_after># -*- coding: utf-8 -*-
import time
import numpy as np
from scipy import interpolate
import astropy.units as u
import astropy.constants as const
import os, inspect
try:
    import cPickle as pickle
except:
    import pickle
import hashlib
from EXOSIMS.Prototypes.Completeness import Completeness
from EXOSIMS.util.eccanom import eccanom
from EXOSIMS.util.deltaMag import deltaMag

class BrownCompleteness(Completeness):
    """Completeness class template
    
    This class contains all variables and methods necessary to perform 
    Completeness Module calculations in exoplanet mission simulation.
    
    Args:
        \*\*specs: 
            user specified values
    
    Attributes:
        Nplanets (integer):
            Number of planets for initial completeness Monte Carlo simulation
        classpath (string):
            Path on disk to Brown Completeness
        filename (string):
            Name of file where completeness interpolant is stored
        updates (float nx5 ndarray):
            Completeness values of successive observations of each star in the
            target list (initialized in gen_update)
        
    """
    
    def __init__(self, Nplanets=1e8, **specs):
        
        # bring in inherited Completeness prototype __init__ values
        Completeness.__init__(self, **specs)
        
        # Number of planets to sample
        self.Nplanets = int(Nplanets)
        
        # get path to completeness interpolant stored in a pickled .comp file
        self.classpath = os.path.split(inspect.getfile(self.__class__))[0]
        self.filename = specs['modules']['PlanetPopulation'] + specs['modules']['PlanetPhysicalModel']
        # get path to dynamic completeness array in a pickled .dcomp file
        self.dfilename = specs['modules']['PlanetPopulation'] + \
                        specs['modules']['PlanetPhysicalModel'] + \
                        specs['modules']['OpticalSystem'] + \
                        specs['modules']['StarCatalog'] + \
                        specs['modules']['TargetList']
        atts = self.PlanetPopulation.__dict__.keys()
        self.extstr = ''
        for att in sorted(atts, key=str.lower):
            if not callable(getattr(self.PlanetPopulation, att)) and att != 'PlanetPhysicalModel':
                self.extstr += '%s: ' % att + str(getattr(self.PlanetPopulation, att)) + ' '
        ext = hashlib.md5(self.extstr).hexdigest()
        self.filename += ext

    def target_completeness(self, TL):
        """Generates completeness values for target stars
        
        This method is called from TargetList __init__ method.
        
        Args:
            TL (TargetList module):
                TargetList class object
            
        Returns:
            comp0 (float ndarray): 
                Completeness values for each target star
        
        """
        
        # set up "ensemble visit photometric and obscurational completeness"
        # interpolant for initial completeness values
        # bins for interpolant
        bins = 1000
        # xedges is array of separation values for interpolant
        if self.PlanetPopulation.constrainOrbits:
            xedges = np.linspace(0.0, self.PlanetPopulation.arange[1].to('AU').value, bins+1)
        else:
            xedges = np.linspace(0.0, self.PlanetPopulation.rrange[1].to('AU').value, bins+1)
        
        # yedges is array of delta magnitude values for interpolant
        ymin = -2.5*np.log10(float(self.PlanetPopulation.prange[1]*\
                (self.PlanetPopulation.Rprange[1]/self.PlanetPopulation.rrange[0])**2))
        ymax = -2.5*np.log10(float(self.PlanetPopulation.prange[0]*\
                (self.PlanetPopulation.Rprange[0]/self.PlanetPopulation.rrange[1])**2)*1e-11)
        yedges = np.linspace(ymin, ymax, bins+1)
        # number of planets for each Monte Carlo simulation
        nplan = int(np.min([1e6,self.Nplanets]))
        # number of simulations to perform (must be integer)
        steps = int(self.Nplanets/nplan)
        
        # path to 2D completeness pdf array for interpolation
        Cpath = os.path.join(self.classpath, self.filename+'.comp')
        Cpdf, xedges2, yedges2 = self.genC(Cpath, nplan, xedges, yedges, steps)

        xcent = 0.5*(xedges2[1:]+xedges2[:-1])
        ycent = 0.5*(yedges2[1:]+yedges2[:-1])
        xnew = np.hstack((0.0,xcent,self.PlanetPopulation.rrange[1].to('AU').value))
        ynew = np.hstack((ymin,ycent,ymax))
        Cpdf = np.pad(Cpdf,1,mode='constant')

        #save interpolant to object
        self.EVPOCpdf = interpolate.RectBivariateSpline(xnew, ynew, Cpdf.T)
        self.EVPOC = np.vectorize(self.EVPOCpdf.integral)
        self.xnew = xnew
        self.ynew = ynew  
            
        # calculate separations based on IWA and OWA
        OS = TL.OpticalSystem
        mode = filter(lambda mode: mode['detectionMode'] == True, OS.observingModes)[0]
        IWA = mode['IWA']
        OWA = mode['OWA']
        smin = np.tan(IWA)*TL.dist
        if np.isinf(OWA):
            smax = xedges[-1]*u.AU
        else:
            smax = np.tan(OWA)*TL.dist
        
        # calculate dMags based on limiting dMag
        dMagmax = OS.dMagLim 
        if self.PlanetPopulation.scaleOrbits:
            L = np.where(TL.L>0, TL.L, 1e-10) #take care of zero/negative values
            smin = smin/np.sqrt(L)
            smax = smax/np.sqrt(L)
            dMagmax -= 2.5*np.log10(L)
            comp0 = np.zeros(smin.shape)
            comp0[dMagmax>ymin] = self.EVPOC(smin[dMagmax>ymin].to('AU').value, smax[dMagmax>ymin].to('AU').value, 0.0, dMagmax[dMagmax>ymin])
        else:
            comp0 = self.EVPOC(smin.to('AU').value, smax.to('AU').value, 0.0, dMagmax)
        comp0[comp0<1e-6] = 0.0
        
        return comp0

    def gen_update(self, TL):
        """Generates dynamic completeness values for multiple visits of each 
        star in the target list
        
        Args:
            TL (TargetList module):
                TargetList class object
        
        """
        
        OS = TL.OpticalSystem
        PPop = TL.PlanetPopulation
        
        # get name for stored dynamic completeness updates array
        # inner and outer working angles for detection mode
        mode = filter(lambda mode: mode['detectionMode'] == True, OS.observingModes)[0]
        IWA = mode['IWA']
        OWA = mode['OWA']
        extstr = self.extstr + 'IWA: ' + str(IWA) + ' OWA: ' + str(OWA) + ' dMagLim: ' + str(OS.dMagLim) + ' '
        extstr += 'nStars: ' + str(TL.nStars)
        ext = hashlib.md5(extstr).hexdigest()
        self.dfilename += ext 
        self.dfilename += '.dcomp'
        
        path = os.path.join(self.classpath, self.dfilename)
        # if the 2D completeness update array exists as a .dcomp file load it
        if os.path.exists(path):
            print 'Loading cached dynamic completeness array from "%s".' % path
            self.updates = pickle.load(open(path, 'rb'))
            print 'Dynamic completeness array loaded from cache.'
        else:
            # run Monte Carlo simulation and pickle the resulting array
            print 'Cached dynamic completeness array not found at "%s".' % path
            print 'Beginning dynamic completeness calculations'
            # dynamic completeness values: rows are stars, columns are number of visits
            self.updates = np.zeros((TL.nStars, 5))
            # number of planets to simulate
            nplan = int(2e4)
            # normalization time
            dt = 1e9*u.day
            # sample quantities which do not change in time
            a = PPop.gen_sma(nplan) # AU
            if PPop.constrainOrbits:
                e = PPop.gen_eccen_from_sma(nplan,a)
            else:
                e = PPop.gen_eccen(nplan)
            I = PPop.gen_I(nplan) # deg
            O = PPop.gen_O(nplan) # deg
            w = PPop.gen_w(nplan) # deg
            p = PPop.gen_albedo(nplan)
            Rp = PPop.gen_radius(nplan) # km
            Mp = PPop.gen_mass(nplan) # kg
            rmax = a*(1.+e)
            # sample quantity which will be updated
            M = np.random.uniform(high=2.*np.pi,size=nplan)
            newM = np.zeros((nplan,))
            # population values
            smin = (np.tan(IWA)*TL.dist).to('AU')
            if np.isfinite(OWA):
                smax = (np.tan(OWA)*TL.dist).to('AU')
            else:
                smax = np.array([np.max(PPop.arange.to('AU').value)*\
                        (1.+np.max(PPop.erange))]*TL.nStars)*u.AU
            # fill dynamic completeness values
            for sInd in xrange(TL.nStars):
                mu = const.G*(Mp + TL.MsTrue[sInd])
                n = np.sqrt(mu/a**3)
                # remove rmax < smin 
                pInds = np.where(rmax > smin[sInd])[0]
                # calculate for 5 successive observations
                for num in xrange(5):
{'fraction_non_alphanumeric': 0.10797532616409193, 'fraction_numerical': 0.010917626507997161, 'mean_word_length': 1.9832274873799056, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3212311', 'n_tokens_mistral': 5741, 'n_tokens_neox': 5488, 'n_words': 1355}