<commit_before>from __future__ import print_function, division

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import scipy.stats as stats
import logging
import re, os, os.path
import numpy.random as rand

from astropy import units as u
from astropy.units import Quantity
from astropy.coordinates import SkyCoord

from orbitutils import OrbitPopulation,OrbitPopulation_FromH5
from orbitutils import OrbitPopulation_FromDF
from orbitutils import TripleOrbitPopulation, TripleOrbitPopulation_FromH5
from orbitutils import TripleOrbitPopulation_FromDF
from plotutils import setfig,plot2dhist

from simpledist import distributions as dists

from hashutils import hashcombine, hashdict, hashdf

from .constraints import Constraint,UpperLimit,LowerLimit,JointConstraintOr
from .constraints import ConstraintDict,MeasurementConstraint,RangeConstraint
from .constraints import ContrastCurveConstraint,VelocityContrastCurveConstraint

from .utils import randpos_in_circle, draw_raghavan_periods, draw_msc_periods, draw_eccs
from .utils import flat_massratio, mult_masses
from .utils import distancemodulus, addmags, dfromdm

from .trilegal import get_trilegal

try:
    from isochrones.dartmouth import Dartmouth_Isochrone
    DARTMOUTH = Dartmouth_Isochrone()
    DARTMOUTH.radius(1,9.6,0.0) #first call takes a long time for some reason
except ImportError:
    logging.warning('isochrones package not installed; population simulations will not be fully functional')
    DARTMOUTH = None

BANDS = ['g','r','i','z','J','H','K','Kepler']

class StarPopulation(object):
    def __init__(self,stars=None,distance=None,
                 max_distance=1000*u.pc,convert_absmags=True,
                 name='', orbpop=None):
        """A population of stars.  Initialized with no constraints.

        Intended to be subclassed.  

        stars : ``pandas`` ``DataFrame`` object
            Data table containing properties of stars.
            Magnitude properties end with "_mag".  Default
            is that these magnitudes are absolute, and get 
            converted to apparent magnitudes based on distance,
            which is either provided or randomly assigned.

        distance : ``Quantity`` or float, optional
            If not ``None``, then distances of stars are assigned
            randomly out to max_distance.  If float,
            then assumed to be in parsec.  Or, if stars already 
            has a distance column, this is ignored.

        max_distance : ``Quantity`` or float, optional
            Max distance out to which distances will be simulated,
            according to random placements in volume ($p(d)\simd^2$).  
            Ignored if stars already has a distance column.

        convert_absmags : bool
            If ``True``, then magnitudes in ``stars`` will be converted
            to apparent magnitudes based on distance.  If ``False,``
            then magnitudes will be kept as-is.  Ignored if stars already
            has a distance column.

        """
        self.orbpop = orbpop
        self.name = name

        if stars is None:
            self.stars = None
        else:
            self.stars = stars.copy()
            N = len(self.stars)

            #if stars does not have a 'distance' column already, then
            # we define distances based on the provided arguments,
            # and covert absolute magnitudes into apparent (unless explicitly
            # forbidden from doing so by 'convert_absmags' being set
            # to False).

            if 'distance' not in self.stars:
                if type(max_distance) != Quantity:
                    max_distance = max_distance * u.pc


                if distance is None:
                    #generate random distances
                    dmax = max_distance.to('pc').value
                    distance_distribution = dists.PowerLaw_Distribution(2.,1,dmax) # p(d)~d^2
                    distance = distance_distribution.rvs(N)

                if type(distance) != Quantity:
                    distance = distance * u.pc

                distmods = distancemodulus(distance)
                if convert_absmags:
                    for col in self.stars.columns:
                        if re.search('_mag',col):
                            self.stars[col] += distmods

                self.stars['distance'] = distance
                self.stars['distmod'] = distmods


            if 'distmod' not in self.stars:
                self.stars['distmod'] = distancemodulus(self.stars['distance'])

        #initialize empty constraint list
        self.constraints = ConstraintDict()
        self.hidden_constraints = ConstraintDict()
        self.selectfrac_skip = []
        self.distribution_skip = []

        #apply constraints,  initializing the following attributes:
        # self.distok, self.countok, self.selected, self.selectfrac
        
        self._apply_all_constraints()


    def append(self, other):
        """Appends stars from another StarPopulations, in place.
        """
        if not isinstance(other,StarPopulation):
            raise TypeError('Only StarPopulation objects can be appended to a StarPopulation.')
        if not np.all(self.stars.columns == other.stars.columns):
            raise ValueError('Two populations must have same columns to combine them.')

        if len(self.constraints) > 0:
            logging.warning('All constraints are cleared when appending another population.')
            
        self.stars = pd.concat((self.stars, other.stars))
        
        if self.orbpop is not None and other.orbpop is not None:
            self.orbpop = self.orbpop + other.orbpop

        #Clear all constraints that might exist
        self.constraints = ConstraintDict()
        self.hidden_constraints = ConstraintDict()
        self.selectfrac_skip = []
        self.distribution_skip = []

        #apply constraints,  initializing the following attributes:
        # self.distok, self.countok, self.selected, self.selectfrac
        
        self._apply_all_constraints()

    def __getitem__(self,prop):
        return self.selected[prop]

    def __hash__(self):
        return hashcombine(self.constraints, self.hidden_constraints,<commit_msg>removed hidden_constraints from hash<commit_after>from __future__ import print_function, division

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import scipy.stats as stats
import logging
import re, os, os.path
import numpy.random as rand

from astropy import units as u
from astropy.units import Quantity
from astropy.coordinates import SkyCoord

from orbitutils import OrbitPopulation,OrbitPopulation_FromH5
from orbitutils import OrbitPopulation_FromDF
from orbitutils import TripleOrbitPopulation, TripleOrbitPopulation_FromH5
from orbitutils import TripleOrbitPopulation_FromDF
from plotutils import setfig,plot2dhist

from simpledist import distributions as dists

from hashutils import hashcombine, hashdict, hashdf

from .constraints import Constraint,UpperLimit,LowerLimit,JointConstraintOr
from .constraints import ConstraintDict,MeasurementConstraint,RangeConstraint
from .constraints import ContrastCurveConstraint,VelocityContrastCurveConstraint

from .utils import randpos_in_circle, draw_raghavan_periods, draw_msc_periods, draw_eccs
from .utils import flat_massratio, mult_masses
from .utils import distancemodulus, addmags, dfromdm

from .trilegal import get_trilegal

try:
    from isochrones.dartmouth import Dartmouth_Isochrone
    DARTMOUTH = Dartmouth_Isochrone()
    DARTMOUTH.radius(1,9.6,0.0) #first call takes a long time for some reason
except ImportError:
    logging.warning('isochrones package not installed; population simulations will not be fully functional')
    DARTMOUTH = None

BANDS = ['g','r','i','z','J','H','K','Kepler']

class StarPopulation(object):
    def __init__(self,stars=None,distance=None,
                 max_distance=1000*u.pc,convert_absmags=True,
                 name='', orbpop=None):
        """A population of stars.  Initialized with no constraints.

        Intended to be subclassed.  

        stars : ``pandas`` ``DataFrame`` object
            Data table containing properties of stars.
            Magnitude properties end with "_mag".  Default
            is that these magnitudes are absolute, and get 
            converted to apparent magnitudes based on distance,
            which is either provided or randomly assigned.

        distance : ``Quantity`` or float, optional
            If not ``None``, then distances of stars are assigned
            randomly out to max_distance.  If float,
            then assumed to be in parsec.  Or, if stars already 
            has a distance column, this is ignored.

        max_distance : ``Quantity`` or float, optional
            Max distance out to which distances will be simulated,
            according to random placements in volume ($p(d)\simd^2$).  
            Ignored if stars already has a distance column.

        convert_absmags : bool
            If ``True``, then magnitudes in ``stars`` will be converted
            to apparent magnitudes based on distance.  If ``False,``
            then magnitudes will be kept as-is.  Ignored if stars already
            has a distance column.

        """
        self.orbpop = orbpop
        self.name = name

        if stars is None:
            self.stars = None
        else:
            self.stars = stars.copy()
            N = len(self.stars)

            #if stars does not have a 'distance' column already, then
            # we define distances based on the provided arguments,
            # and covert absolute magnitudes into apparent (unless explicitly
            # forbidden from doing so by 'convert_absmags' being set
            # to False).

            if 'distance' not in self.stars:
                if type(max_distance) != Quantity:
                    max_distance = max_distance * u.pc


                if distance is None:
                    #generate random distances
                    dmax = max_distance.to('pc').value
                    distance_distribution = dists.PowerLaw_Distribution(2.,1,dmax) # p(d)~d^2
                    distance = distance_distribution.rvs(N)

                if type(distance) != Quantity:
                    distance = distance * u.pc

                distmods = distancemodulus(distance)
                if convert_absmags:
                    for col in self.stars.columns:
                        if re.search('_mag',col):
                            self.stars[col] += distmods

                self.stars['distance'] = distance
                self.stars['distmod'] = distmods


            if 'distmod' not in self.stars:
                self.stars['distmod'] = distancemodulus(self.stars['distance'])

        #initialize empty constraint list
        self.constraints = ConstraintDict()
        self.hidden_constraints = ConstraintDict()
        self.selectfrac_skip = []
        self.distribution_skip = []

        #apply constraints,  initializing the following attributes:
        # self.distok, self.countok, self.selected, self.selectfrac
        
        self._apply_all_constraints()


    def append(self, other):
        """Appends stars from another StarPopulations, in place.
        """
        if not isinstance(other,StarPopulation):
            raise TypeError('Only StarPopulation objects can be appended to a StarPopulation.')
        if not np.all(self.stars.columns == other.stars.columns):
            raise ValueError('Two populations must have same columns to combine them.')

        if len(self.constraints) > 0:
            logging.warning('All constraints are cleared when appending another population.')
            
        self.stars = pd.concat((self.stars, other.stars))
        
        if self.orbpop is not None and other.orbpop is not None:
            self.orbpop = self.orbpop + other.orbpop

        #Clear all constraints that might exist
        self.constraints = ConstraintDict()
        self.hidden_constraints = ConstraintDict()
        self.selectfrac_skip = []
        self.distribution_skip = []

        #apply constraints,  initializing the following attributes:
        # self.distok, self.countok, self.selected, self.selectfrac
        
        self._apply_all_constraints()

    def __getitem__(self,prop):
        return self.selected[prop]

    def __hash__(self):
        return hashcombine(self.constraints,
{'fraction_non_alphanumeric': 0.07174887892376682, 'fraction_numerical': 0.0027226137091607944, 'mean_word_length': 2.4614745011086474, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '1970554', 'n_tokens_mistral': 3332, 'n_tokens_neox': 3132, 'n_words': 1049}