<commit_before>"""
Genes are the most basic building block in this genetic algorithm library.
A gene represents a particular trait of an individual solution.  Mutliple genes are
combined together to form a genome.  The entire genome represents a solution
to the problem being solved.

This module contains the base gene class from which all genes are derived.
It also has two gene classes, list_gene and float_gene, that are commonly used.
If you need to create your own gene class, derive it from the class gene.

history:
12/31/98 documentation added ej
"""

from ga_util import *
import scipy.stats as rv
from random import random
import copy

class gene:
    """
    Genes are the most basic building block in this genetic algorithm library.
    A gene represents a particular trait of an individual solution.  The gene class
    contains the current value of a gene object.  It also knows all the possible
    values that the gene can legally have (the allele set).  The gene itself does not
    know how to initialize itself to a value or mutate to another value.  Instead, it is
    closely coupled with initializer and mutator classes that perform these duties.
    By changing the initialization and mutation classes, the behavior of a gene can be
    altered without actually having to create a new gene class.

    This class is never actually instantiated.  Instead it is a base class from which
    specific gene classes are derived.  The duties of the derived class are
    pretty limited because this class defines almost all the necessary methods.  The
    derived class must define the allele set for the gene.  It usually will specify
    an __init__() method, and possibly some other methods specific to the derived
    gene.  It is also necessary to specifiy the initializer and mutator classes
    to operate on the new gene class

    There are several attributes for the class gene:

    mutation_rate -- Every gene has a possibility of mutating each generation.
                     This is a value between 0 and 1 that specifies, in percent,
                     how often the gene mutates.  mutation_rate can either be
                     set for the entire gene class or on a gene by gene basis.
                     Use the set_mutation() function to change the rate
    mr_bounds -- Sometimes it is useful for the mutation rate of the gene to
                 adapt over the course of evolution.  This 2 element tuple specifies
                 the upper and lower bounds that the mutation rate can have.
                 note:  I haven't really messed with this much and think there
                        is probably a better approach
    mutator -- a mutator object (instantiation of a mutator class) that is used
               to mutate the gene
    initializer -- an intializer object used to initialize the gene

    Take a look at float_gene and list_gene to see examples of derived gene classes.
    """
    mr_bounds = (0,.1)
    mutation_rate = .03
    mutator = None
    initializer = None
    is_gene = 1
    def clone(self):
        """Makes a shallow copy of the object.  override if you need more specialized behavior
        """
        return shallow_clone(self)
    def replicate(self,cnt):
        """Returns a list with cnt copies of this object in it
        """
        return map(lambda x: x.clone(),[self]*cnt)
    def initialize(self):
        """Calls the initializer objects evaluate() function to initialize the gene
        """
        self._value = self.initializer.evaluate(self)
        return self.value()
    def set_mutation(self,mrate):
        """
        Set the mutation rate of the gene.

            Arguments:

              mrate -- can be one of the following:

                * a number between 0 and 1 - sets the mutation rate of the gene to a specific value.
                * "gene" - use the mutation rate set in the class definition for this gene.
                * "adapt" - the mutation rate for the gene is chosen randomly from the range mr_bounds
        """
        if(mrate=='gene'):
            try: del self.mutation_rate #remove local mrates and use gene classes mrate
            except AttributeError: pass
        elif(mrate=='adapt'):
            self.mutation_rate = rv.uniform(self.mr_bounds[0],self.mr_bounds[1])[0]
        else:
            self.__class__.mutation_rate = mrate

    def mutate(self):
        """
            Returns 1 if gene mutated, 0 otherwise.

            Calls the **mutator.evaluate()** function to mutate the gene
            mutation_rate of the time. Otherwise, it does nothing.
        """
        #inlined 'flip_coin' for speed
        if random() < self.mutation_rate:
            self._value = self.mutator.evaluate(self)
            return 1
        return 0
    def value(self):
        """Return the current value of the gene. """
        try:
            return self._value
        except AttributeError:
            raise GAError, 'gene not initialized'
    def set_value(self,x):
        """ Set the value of a gene. NO CHECKING!!!
            Don't assign an incompatible value.
        """
        self._value = x
    def __repr__(self):
        try: return `self.value()`
        except GAError: return 'gene not initialized'
    def __add__(self, other):
        try: return self.value() + other.value()
        except AttributeError: return self.value() + other
    __radd__ = __add__
    def __mul__(self, other):
        try: return self.value() * other.value()
        except AttributeError: return self.value() * other
    __rmul__ = __mul__
    def __sub__(self, other):
        try: return self.value() - other.value()
        except AttributeError: return self.value() - other
    def __rsub__(self, other):
        try: return other.value() - self.value()
        except AttributeError: return other - self.value()
    def __div__(self, other):
        try: return self.value() / other.value()
        except: return self.value() / other
    def __rdiv__(self, other):
        try: return other.value() / self.value()
        except AttributeError: return other / self.value()
    def __float__(self): return float(self.value())
    def __complex__(self): return float(self.value())
    def __neg__(self): return -self.value()
    def __cmp__(self, other):
        try:
            if self.__class__ == other.__class__ and self.__dict__ == other.__dict__: return 0
        except AttributeError: pass
        v1 = self.value()
        try: v2 = other.value()
        except AttributeError: v2 = other
        return cmp(v1,v2)

class list_gene_uniform_mutator:
    """
    This class randomly chooses a new gene value from the allele set
    in a list_gene.  It is also useful as an initializer for list_gene.
    """
    def evaluate(self,gene):
        """ return a randomly chosen value from the genes allele set """
        return rv.choice(gene.allele_set)
class list_gene_gaussian_mutator:
    """
    This class chooses a new gene value from the allele set
    in a list_gene.  The new value is chosen from a gaussian
    distributed distance away from the current values location in the
    allele set list.  The mutated value is never equal to the current
    gene value.  The dev_width is the standard deviation of the gaussian
    distribution as a percentage of the length of the list.

    As an example, suppose a list_gene has the allele_set [0,1,2,3,4,5,6,7,8,9].
    There are 10 entries in this list.  If the dev_width is .1 (the default),
    then there is a 65% chance the new value will either be 1 position away from
    the current value.  If the current value is 4, then the new value will be
    3 or 5 66% of the time, 2 or 6 29% of the time, and so on based on a gaussian
    distribution.

    If the newly chosen index falls outside of the range of the list (for example
    -1), then a new value is chosen until the value falls inside the lists range.
    The index is NOT truncated to the bottom or top index in the range.
    """
    def __init__(self,dev_width = .1):
        """Arguments:
            dev_width -- a value between 0 and 1 that specifies the standard
            deviation as a percentage of the length of the list_gene's
            allele set.
        """
        self.dev_width = dev_width
    def evaluate(self,gene):
        """ return a new value from the genes allele set """
        size = len(gene.allele_set)
        if size == 1: return gene.allele_set[0]
        w = self.dev_width * size
        old = gene.index()
        new = -1; f = -1
        while not (0 <= new < size):
            f = rv.norm(old,w)[0]
            new = round(f)
            if(old == new and f > new): new = new + 1
            if(old == new and f < new): new = new - 1
        return gene.allele_set[int(new)]
class list_gene_walk_mutator:
    """
      This class chooses a new gene value from the allele set
      in a list_gene.  The newly chosen value is +/-1 element
    in the allele_set from the current gene value.
    This is like a random walk across the allele_set
    """
    def evaluate(self,gene):
        old = gene.index()
        move = rv.choice((-1,1))
        return gene.allele_set[old + move]

class list_gene(gene):
    """
    The value of a list_gene is chosen from a list of
    possible values - the allele_set.
    For example, the gene could be used to represent a
    mathematical oeprator.  Here the allele_set might be
    ['+','-','*','/'].  The list could just as easily be
    a list of numbers (ie. standard capacitor values),
    strings, or anything else.

    The default mutator is a gaussian mutator and the
    default initializer randomly chooses a value from the
    allele_set.
    """
    gaussian_mutator = list_gene_gaussian_mutator
    uniform_mutator = list_gene_uniform_mutator
    walk_mutator = list_gene_walk_mutator
    mutator = gaussian_mutator()
    initializer = uniform_mutator()
    def __init__(self, allele_set): self.allele_set = allele_set
    def index(self,*val):
        """set or retreive a specific value from the allele_set"""
        if len(val): self._value = self.allele_set[val[0]]
        return self.allele_set.index(self.value())

class list2_gene(list_gene):
    """
    this is something like we'll do to add part variance to capacitor
    and resistor values during evaluation
    """
    func = nop
    def value(self): return func(self._value)
    def __repr__(self): return `self._value` #???

class float_gene_uniform_mutator:
    """ randomly choose a value within the float_gene's bounds"""
    def evaluate(self,gene):
        bounds=gene.bounds
        new =rv.uniform(bounds[0], bounds[1]-bounds[0] ).rvs()[0]
        return new

class float_gene_gaussian_mutator:
    """
    chooses a new value for a float_gene with gaussian
    shaped distribution around the current value.

    dev_width -- a value between 0 and 1.  It is the standard
    deviation for the gaussian distribution as a percentage
    of the float_gene's range.  For example:  If the genes bounds
    are (0,10) and dev_width is .1, then the standard deviation
    is 1.
    """

    def __init__(self,dev_width = .1):
        self.dev_width = dev_width
    def evaluate(self,gene):
        dev = (gene.bounds[1]-gene.bounds[0]) * self.dev_width
        new = gene.bounds[1]
#       while not (gene.bounds[0] <= new < gene.bounds[1]):
#           new = rv.norm(gene.value(),dev)[0]
#       new = rv.norm(gene.value(),dev)[0]
        #get the _value explicitly so mutator will work for log_float also
        new = rv.norm(gene._value,dev).rvs()[0]
        if new > gene.bounds[1]: new = gene.bounds[1]
        if new < gene.bounds[0]: new = gene.bounds[0]
        return new

class float_gene(gene):
    """
    A float_gene is a gene that takes on a floating point value
    between some upper and lower bounds.

    The default mutator is a gaussian mutator and the
    default initializer randomly chooses a value from within
    the upper and lower bounds.

    bounds -- A 2 element tuple that specifies the lower and upper
    bounds for the gene.
    """
    gaussian_mutator = float_gene_gaussian_mutator
    uniform_mutator = float_gene_uniform_mutator
    mutator = gaussian_mutator()
    initializer = uniform_mutator()
    def __init__(self,bounds):
        if len(bounds) !=2: raise GAError, 'float_gene: init expects a 2 element tuple of the fomr (min,max)'
        self.bounds = bounds
    def set_value(self,x):
        """ Set the value of a gene.
            Convertthe value to a float first!
        """
        self._value = float(x)

from Numeric import *
from scipy_base.fastumath import *
class log_float_gene(float_gene):
    def __init__(self,bounds):
        if len(bounds) !=2: raise GAError, 'float_gene: init expects a 2 element tuple of the fomr (min,max)'
        self.bounds = log10(array(bounds))
    def value(self):
        """Return the current value of the gene. """
        try: return 10.**(self._value)
        except AttributeError: raise GAError, 'gene not initialized'

class frozen:
    """frozen is a gene that always maintains the same value.
    """
    def __init__(self,val): self._value = val
    def initialize(self): pass
    def set_mutation(self,mrate): pass
    def mutate(self): pass
    def value(self) : return self._value
    def clone(self): return shallow_clone(self)
    def __float__(self): return float(self._value)
    def __repr__(self): return `self._value`
    def __add__(self, other):
        try: return self._value + other.value()
        except AttributeError: return self._value + other
    __radd__ = __add__
    def __mul__(self, other):
        try: return self._value * other.value()
        except AttributeError: return self._value * other
    __rmul__ = __mul__
    def __sub__(self, other):
        try: return self._value - other.value()
        except AttributeError: return self._value - other
    def __rsub__(self, other):
        try: return other.value() - self._value
        except AttributeError: return other - self._value
    def __div__(self, other):
        try: return self._value / other.value()
        except: return self._value / other
    def __rdiv__(self, other):
        try: return other.value() / self._value
        except AttributeError: return other / self._value
    def __float__(self): return float(self._value)
    def __neg__(self): return -self._value
    def __cmp__(self, other):
        try:
            if self.__class__ == other.__class__ and self.__dict__ == other.__dict__: return 0
        except AttributeError: pass
        v1 = self.value()
        try: v2 = other.value()
        except AttributeError: v2 = other
        return cmp(v1,v2)

# not sure why this has to be fully qualified, but things are failing otherwise.
# import tree
from scipy.ga.tree import tree_node
class tree_gene(tree_node):
    mr_bounds = (0,.1)
    mutation_rate = .03
    model_properties = {}
    def __init__(self,child_count,node_type='',derive_type='', parent=None):
        tree_node.__init__(self,child_count,node_type,derive_type, parent)
    def initialize(self,propagate = 1):
        if propagate:
            for child in self._children: child.initialize()
    def defaultize(self):
        for child in self._children: child.defaultize()
    def set_mutation(self,mrate):
        if(mrate=='gene'):
            try: del self.mutation_rate #remove local mrates and use gene classes mrate
            except AttributeError: pass
        elif(mrate=='adapt'):
            self.mutation_rate = rv.uniform(self.mr_bounds[0],self.mr_bounds[1])[0]
        else:
            self.__class__.mutation_rate = mrate
        for child in self._children: child.set_mutation(mrate)

    def mutate(self,propagate = 1):
        mutated = 0
        #if flip_coin(self.mutation_rate): pass # handle tree mutation
        if propagate:
            for child in self._children:
                #careful with short circuit "or"
                mutated = child.mutate() or mutated
        return mutated

    def value(self):
        """Return the current value of the gene. """
        try: return self._value
        except AttributeError: raise GAError, 'gene not initialized'
    def set_value(self,x):
        """ Set the value of a gene. NO CHECKING!!!
            Don't assign an incompatible value.
        """
        self._value = x
<commit_msg>Fixed issue 216<commit_after>"""
Genes are the most basic building block in this genetic algorithm library.
A gene represents a particular trait of an individual solution.  Mutliple genes are
combined together to form a genome.  The entire genome represents a solution
to the problem being solved.

This module contains the base gene class from which all genes are derived.
It also has two gene classes, list_gene and float_gene, that are commonly used.
If you need to create your own gene class, derive it from the class gene.

history:
12/31/98 documentation added ej
"""

from ga_util import *
import scipy.stats as rv
from random import random
import copy

class gene:
    """
    Genes are the most basic building block in this genetic algorithm library.
    A gene represents a particular trait of an individual solution.  The gene class
    contains the current value of a gene object.  It also knows all the possible
    values that the gene can legally have (the allele set).  The gene itself does not
    know how to initialize itself to a value or mutate to another value.  Instead, it is
    closely coupled with initializer and mutator classes that perform these duties.
    By changing the initialization and mutation classes, the behavior of a gene can be
    altered without actually having to create a new gene class.

    This class is never actually instantiated.  Instead it is a base class from which
    specific gene classes are derived.  The duties of the derived class are
    pretty limited because this class defines almost all the necessary methods.  The
    derived class must define the allele set for the gene.  It usually will specify
    an __init__() method, and possibly some other methods specific to the derived
    gene.  It is also necessary to specifiy the initializer and mutator classes
    to operate on the new gene class

    There are several attributes for the class gene:

    mutation_rate -- Every gene has a possibility of mutating each generation.
                     This is a value between 0 and 1 that specifies, in percent,
                     how often the gene mutates.  mutation_rate can either be
                     set for the entire gene class or on a gene by gene basis.
                     Use the set_mutation() function to change the rate
    mr_bounds -- Sometimes it is useful for the mutation rate of the gene to
                 adapt over the course of evolution.  This 2 element tuple specifies
                 the upper and lower bounds that the mutation rate can have.
                 note:  I haven't really messed with this much and think there
                        is probably a better approach
    mutator -- a mutator object (instantiation of a mutator class) that is used
               to mutate the gene
    initializer -- an intializer object used to initialize the gene

    Take a look at float_gene and list_gene to see examples of derived gene classes.
    """
    mr_bounds = (0,.1)
    mutation_rate = .03
    mutator = None
    initializer = None
    is_gene = 1
    def clone(self):
        """Makes a shallow copy of the object.  override if you need more specialized behavior
        """
        return shallow_clone(self)
    def replicate(self,cnt):
        """Returns a list with cnt copies of this object in it
        """
        return map(lambda x: x.clone(),[self]*cnt)
    def initialize(self):
        """Calls the initializer objects evaluate() function to initialize the gene
        """
        self._value = self.initializer.evaluate(self)
        return self.value()
    def set_mutation(self,mrate):
        """
        Set the mutation rate of the gene.

            Arguments:

              mrate -- can be one of the following:

                * a number between 0 and 1 - sets the mutation rate of the gene to a specific value.
                * "gene" - use the mutation rate set in the class definition for this gene.
                * "adapt" - the mutation rate for the gene is chosen randomly from the range mr_bounds
        """
        if(mrate=='gene'):
            try: del self.mutation_rate #remove local mrates and use gene classes mrate
            except AttributeError: pass
        elif(mrate=='adapt'):
            self.mutation_rate = rv.uniform(self.mr_bounds[0],self.mr_bounds[1])[0]
        else:
            self.__class__.mutation_rate = mrate

    def mutate(self):
        """
            Returns 1 if gene mutated, 0 otherwise.

            Calls the **mutator.evaluate()** function to mutate the gene
            mutation_rate of the time. Otherwise, it does nothing.
        """
        #inlined 'flip_coin' for speed
        if random() < self.mutation_rate:
            self._value = self.mutator.evaluate(self)
            return 1
        return 0
    def value(self):
        """Return the current value of the gene. """
        try:
            return self._value
        except AttributeError:
            raise GAError, 'gene not initialized'
    def set_value(self,x):
        """ Set the value of a gene. NO CHECKING!!!
            Don't assign an incompatible value.
        """
        self._value = x
    def __repr__(self):
        try: return `self.value()`
        except GAError: return 'gene not initialized'
    def __add__(self, other):
        try: return self.value() + other.value()
        except AttributeError: return self.value() + other
    __radd__ = __add__
    def __mul__(self, other):
        try: return self.value() * other.value()
        except AttributeError: return self.value() * other
    __rmul__ = __mul__
    def __sub__(self, other):
        try: return self.value() - other.value()
        except AttributeError: return self.value() - other
    def __rsub__(self, other):
        try: return other.value() - self.value()
        except AttributeError: return other - self.value()
    def __div__(self, other):
        try: return self.value() / other.value()
        except: return self.value() / other
    def __rdiv__(self, other):
        try: return other.value() / self.value()
        except AttributeError: return other / self.value()
    def __float__(self): return float(self.value())
    def __complex__(self): return float(self.value())
    def __neg__(self): return -self.value()
    def __cmp__(self, other):
        try:
            if self.__class__ == other.__class__ and self.__dict__ == other.__dict__: return 0
        except AttributeError: pass
        v1 = self.value()
        try: v2 = other.value()
        except AttributeError: v2 = other
        return cmp(v1,v2)

class list_gene_uniform_mutator:
    """
    This class randomly chooses a new gene value from the allele set
    in a list_gene.  It is also useful as an initializer for list_gene.
    """
    def evaluate(self,gene):
        """ return a randomly chosen value from the genes allele set """
        return rv.choice(gene.allele_set)
class list_gene_gaussian_mutator:
    """
    This class chooses a new gene value from the allele set
    in a list_gene.  The new value is chosen from a gaussian
    distributed distance away from the current values location in the
    allele set list.  The mutated value is never equal to the current
    gene value.  The dev_width is the standard deviation of the gaussian
    distribution as a percentage of the length of the list.

    As an example, suppose a list_gene has the allele_set [0,1,2,3,4,5,6,7,8,9].
    There are 10 entries in this list.  If the dev_width is .1 (the default),
    then there is a 65% chance the new value will either be 1 position away from
    the current value.  If the current value is 4, then the new value will be
    3 or 5 66% of the time, 2 or 6 29% of the time, and so on based on a gaussian
    distribution.

    If the newly chosen index falls outside of the range of the list (for example
    -1), then a new value is chosen until the value falls inside the lists range.
    The index is NOT truncated to the bottom or top index in the range.
    """
    def __init__(self,dev_width = .1):
        """Arguments:
            dev_width -- a value between 0 and 1 that specifies the standard
            deviation as a percentage of the length of the list_gene's
            allele set.
        """
        self.dev_width = dev_width
    def evaluate(self,gene):
        """ return a new value from the genes allele set """
        size = len(gene.allele_set)
        if size == 1: return gene.allele_set[0]
        w = self.dev_width * size
        old = gene.index()
        new = -1; f = -1
        while not (0 <= new < size):
            f = rv.norm.rvs(old,w)[0]
            new = round(f)
            if(old == new and f > new): new = new + 1
            if(old == new and f < new): new = new - 1
        return gene.allele_set[int(new)]
class list_gene_walk_mutator:
    """
      This class chooses a new gene value from the allele set
      in a list_gene.  The newly chosen value is +/-1 element
    in the allele_set from the current gene value.
    This is like a random walk across the allele_set
    """
    def evaluate(self,gene):
        old = gene.index()
        move = rv.choice((-1,1))
        return gene.allele_set[old + move]

class list_gene(gene):
    """
    The value of a list_gene is chosen from a list of
    possible values - the allele_set.
    For example, the gene could be used to represent a
    mathematical oeprator.  Here the allele_set might be
    ['+','-','*','/'].  The list could just as easily be
    a list of numbers (ie. standard capacitor values),
    strings, or anything else.

    The default mutator is a gaussian mutator and the
    default initializer randomly chooses a value from the
    allele_set.
    """
    gaussian_mutator = list_gene_gaussian_mutator
    uniform_mutator = list_gene_uniform_mutator
    walk_mutator = list_gene_walk_mutator
    mutator = gaussian_mutator()
    initializer = uniform_mutator()
    def __init__(self, allele_set): self.allele_set = allele_set
    def index(self,*val):
        """set or retreive a specific value from the allele_set"""
        if len(val): self._value = self.allele_set[val[0]]
        return self.allele_set.index(self.value())

class list2_gene(list_gene):
    """
    this is something like we'll do to add part variance to capacitor
    and resistor values during evaluation
    """
    func = nop
    def value(self): return func(self._value)
    def __repr__(self): return `self._value` #???

class float_gene_uniform_mutator:
    """ randomly choose a value within the float_gene's bounds"""
    def evaluate(self,gene):
        bounds=gene.bounds
        new =rv.uniform(bounds[0], bounds[1]-bounds[0] ).rvs()[0]
        return new

class float_gene_gaussian_mutator:
    """
    chooses a new value for a float_gene with gaussian
    shaped distribution around the current value.

    dev_width -- a value between 0 and 1.  It is the standard
    deviation for the gaussian distribution as a percentage
    of the float_gene's range.  For example:  If the genes bounds
    are (0,10) and dev_width is .1, then the standard deviation
    is 1.
    """

    def __init__(self,dev_width = .1):
        self.dev_width = dev_width
    def evaluate(self,gene):
        dev = (gene.bounds[1]-gene.bounds[0]) * self.dev_width
        new = gene.bounds[1]
#       while not (gene.bounds[0] <= new < gene.bounds[1]):
#           new = rv.norm.rvs(gene.value(),dev)[0]
#       new = rv.norm(gene.value(),dev)[0]
        #get the _value explicitly so mutator will work for log_float also
        new = rv.norm.rvs(gene._value,dev)[0]
        if new > gene.bounds[1]: new = gene.bounds[1]
        if new < gene.bounds[0]: new = gene.bounds[0]
        return new

class float_gene(gene):
    """
    A float_gene is a gene that takes on a floating point value
    between some upper and lower bounds.

    The default mutator is a gaussian mutator and the
    default initializer randomly chooses a value from within
    the upper and lower bounds.

    bounds -- A 2 element tuple that specifies the lower and upper
    bounds for the gene.
    """
    gaussian_mutator = float_gene_gaussian_mutator
    uniform_mutator = float_gene_uniform_mutator
    mutator = gaussian_mutator()
    initializer = uniform_mutator()
    def __init__(self,bounds):
        if len(bounds) !=2: raise GAError, 'float_gene: init expects a 2 element tuple of the fomr (min,max)'
        self.bounds = bounds
    def set_value(self,x):
        """ Set the value of a gene.
            Convertthe value to a float first!
        """
        self._value = float(x)

from Numeric import *
from scipy_base.fastumath import *
class log_float_gene(float_gene):
    def __init__(self,bounds):
        if len(bounds) !=2: raise GAError, 'float_gene: init expects a 2 element tuple of the fomr (min,max)'
        self.bounds = log10(array(bounds))
    def value(self):
        """Return the current value of the gene. """
        try: return 10.**(self._value)
        except AttributeError: raise GAError, 'gene not initialized'

class frozen:
    """frozen is a gene that always maintains the same value.
    """
    def __init__(self,val): self._value = val
    def initialize(self): pass
    def set_mutation(self,mrate): pass
    def mutate(self): pass
    def value(self) : return self._value
    def clone(self): return shallow_clone(self)
    def __float__(self): return float(self._value)
    def __repr__(self): return `self._value`
    def __add__(self, other):
        try: return self._value + other.value()
        except AttributeError: return self._value + other
    __radd__ = __add__
    def __mul__(self, other):
        try: return self._value * other.value()
        except AttributeError: return self._value * other
    __rmul__ = __mul__
    def __sub__(self, other):
        try: return self._value - other.value()
        except AttributeError: return self._value - other
    def __rsub__(self, other):
        try: return other.value() - self._value
        except AttributeError: return other - self._value
    def __div__(self, other):
        try: return self._value / other.value()
        except: return self._value / other
    def __rdiv__(self, other):
        try: return other.value() / self._value
        except AttributeError: return other / self._value
    def __float__(self): return float(self._value)
    def __neg__(self): return -self._value
    def __cmp__(self, other):
        try:
            if self.__class__ == other.__class__ and self.__dict__ == other.__dict__: return 0
        except AttributeError: pass
        v1 = self.value()
        try: v2 = other.value()
        except AttributeError: v2 = other
        return cmp(v1,v2)

# not sure why this has to be fully qualified, but things are failing otherwise.
# import tree
from scipy.ga.tree import tree_node
class tree_gene(tree_node):
    mr_bounds = (0,.1)
    mutation_rate = .03
    model_properties = {}
    def __init__(self,child_count,node_type='',derive_type='', parent=None):
        tree_node.__init__(self,child_count,node_type,derive_type, parent)
    def initialize(self,propagate = 1):
        if propagate:
            for child in self._children: child.initialize()
    def defaultize(self):
        for child in self._children: child.defaultize()
    def set_mutation(self,mrate):
        if(mrate=='gene'):
            try: del self.mutation_rate #remove local mrates and use gene classes mrate
            except AttributeError: pass
        elif(mrate=='adapt'):
            self.mutation_rate = rv.uniform(self.mr_bounds[0],self.mr_bounds[1])[0]
        else:
            self.__class__.mutation_rate = mrate
        for child in self._children: child.set_mutation(mrate)

    def mutate(self,propagate = 1):
        mutated = 0
        #if flip_coin(self.mutation_rate): pass # handle tree mutation
        if propagate:
            for child in self._children:
                #careful with short circuit "or"
                mutated = child.mutate() or mutated
        return mutated

    def value(self):
        """Return the current value of the gene. """
        try: return self._value
        except AttributeError: raise GAError, 'gene not initialized'
    def set_value(self,x):
        """ Set the value of a gene. NO CHECKING!!!
            Don't assign an incompatible value.
        """
        self._value = x
<|endoftext|>


<commit_before>import inspect
import types
import sys

# NOTE:  pydoc defines a help function which works simliarly to this
#  except it uses a pager to take over the screen.

# combine name and arguments and split to multiple lines of
#  width characters.  End lines on a comma and begin argument list
#  indented with the rest of the arguments.
def split_line(name, arguments, width):
    firstwidth = len(name)
    k = firstwidth
    newstr = name
    sepstr = ", "
    arglist = arguments.split(sepstr)
    for argument in arglist:
        if k == firstwidth:
            addstr = ""
        else:
            addstr = sepstr
        k = k + len(argument) + len(addstr)
        if k > width:
            k = firstwidth + 1 + len(argument)
            newstr = newstr + ",\n" + " "*(firstwidth+2) + argument
        else:
            newstr = newstr + addstr + argument
    return newstr

_namedict = None
_dictlist = None

# Traverse all module directories underneath globals to see if something is defined
def makenamedict():
    import scipy
    thedict = {'scipy':scipy.__dict__}
    dictlist = ['scipy']
    totraverse = [scipy.__dict__]
    while 1:
        if len(totraverse) == 0:
            break
        thisdict = totraverse.pop(0)
        for x in thisdict.keys():
            if isinstance(thisdict[x],types.ModuleType):
                modname = thisdict[x].__name__
                if modname not in dictlist:
                    moddict = thisdict[x].__dict__
                    dictlist.append(modname)
                    totraverse.append(moddict)
                    thedict[modname] = moddict
    return thedict, dictlist

def info(object=None,maxwidth=76,output=sys.stdout,):
    """Get help information for a function, class, or module.

       Example:
          >>> from scipy import *
          >>> info(polyval)
          polyval(p, x)

            Evaluate the polymnomial p at x.

            Description:
                If p is of length N, this function returns the value:
                p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1]
    """
    global _namedict, _dictlist

    if hasattr(object,'_ppimport_importer') or \
       hasattr(object, '_ppimport_module'):
	object = object._ppimport_module
    elif hasattr(object, '_ppimport_attr'):
        object = object._ppimport_attr

    if object is None:
        info(info)
    elif isinstance(object, types.StringType):
        if _namedict is None:
            _namedict, _dictlist = makenamedict()
        numfound = 0
        objlist = []
        for namestr in _dictlist:
            try:
                obj = _namedict[namestr][object]
                if id(obj) in objlist:
                    print >> output, "\n     *** Repeat reference found in %s *** " % namestr
                else:
                    objlist.append(id(obj))
                    print >> output, "     *** Found in %s ***" % namestr
                    info(obj)
                    print >> output, "-"*maxwidth
                numfound += 1
            except KeyError:
                pass
        if numfound == 0:
            print >> output, "Help for %s not found." % object
        else:
            print >> output, "\n     *** Total of %d references found. ***" % numfound

    elif inspect.isfunction(object):
        name = object.func_name
        arguments = apply(inspect.formatargspec, inspect.getargspec(object))

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        print >> output, inspect.getdoc(object)

    elif inspect.isclass(object):
        name = object.__name__
        if hasattr(object, '__init__'):
            arguments = apply(inspect.formatargspec, inspect.getargspec(object.__init__.im_func))
            arglist = arguments.split(', ')
            if len(arglist) > 1:
                arglist[1] = "("+arglist[1]
                arguments = ", ".join(arglist[1:])
            else:
                arguments = "()"
        else:
            arguments = "()"

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        doc1 = inspect.getdoc(object)
        if doc1 is None:
            if hasattr(object,'__init__'):
                print >> output, inspect.getdoc(object.__init__)
        else:
            print >> output, inspect.getdoc(object)

    elif type(object) is types.InstanceType: ## check for __call__ method
        print >> output, "Instance of class: ", object.__class__.__name__
        print >> output
        if hasattr(object, '__call__'):
            arguments = apply(inspect.formatargspec, inspect.getargspec(object.__call__.im_func))
            arglist = arguments.split(', ')
            if len(arglist) > 1:
                arglist[1] = "("+arglist[1]
                arguments = ", ".join(arglist[1:])
            else:
                arguments = "()"

            name = "<name>"
            if len(name+arguments) > maxwidth:
                argstr = split_line(name, arguments, maxwidth)
            else:
                argstr = name + arguments

            print >> output, " " + argstr + "\n"
            doc = inspect.getdoc(object.__call__)
            if doc is not None:
                print >> output, inspect.getdoc(object.__call__)
            print >> output, inspect.getdoc(object)

        else:
            print >> output, inspect.getdoc(object)

    elif inspect.ismethod(object):
        name = object.__name__
        arguments = apply(inspect.formatargspec, inspect.getargspec(object.im_func))
        arglist = arguments.split(', ')
        if len(arglist) > 1:
            arglist[1] = "("+arglist[1]
            arguments = ", ".join(arglist[1:])
        else:
            arguments = "()"

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        print >> output, inspect.getdoc(object)

    elif hasattr(object, '__doc__'):
        print >> output, inspect.getdoc(object)

def source(object, output=sys.stdout):
    if inspect.isroutine(object):
        print >> output,  "In file: %s\n" % inspect.getsourcefile(object)
        print >> output,  inspect.getsource(object)
    else:
        print >> output,  "Not available for this object."

try:
    import pydoc as _pydoc
except ImportError:
    _pydoc = None

if _pydoc is not None:

    # Define new built-in 'help'.
    # This is a wrapper around pydoc.help (with a twist
    # (as in debian site.py) and ppimport support).
    class _Helper:
        def __repr__ (self):
            return "Type help () for interactive help, " \
                   "or help (object) for help about object."
        def __call__ (self, *args, **kwds):
            new_args = []
            for a in args:
                if hasattr(a,'_ppimport_importer') or \
		   hasattr(a,'_ppimport_module'):
                    a = a._ppimport_module
                if hasattr(a,'_ppimport_attr'):
		    a = a._ppimport_attr
                new_args.append(a)
            return _pydoc.help(*new_args, **kwds)
    import __builtin__
    __builtin__.help = _Helper()

    import inspect as _inspect
    _old_inspect_getfile = _inspect.getfile
    def _inspect_getfile(object):
	try:
	    if hasattr(object,'_ppimport_importer') or \
	       hasattr(object,'_ppimport_module'):
                object = object._ppimport_module
            if hasattr(object,'_ppimport_attr'):
		object = object._ppimport_attr
	except ImportError:
	    object = object.__class__
	return _old_inspect_getfile(object)
    _inspect.getfile = _inspect_getfile
<commit_msg>Backported ppimport to Py2.1. Moved help/ppimport hooks to ppimport.py so that they will be available also for standalone installations<commit_after>import inspect
import types
import sys

# NOTE:  pydoc defines a help function which works simliarly to this
#  except it uses a pager to take over the screen.

# combine name and arguments and split to multiple lines of
#  width characters.  End lines on a comma and begin argument list
#  indented with the rest of the arguments.
def split_line(name, arguments, width):
    firstwidth = len(name)
    k = firstwidth
    newstr = name
    sepstr = ", "
    arglist = arguments.split(sepstr)
    for argument in arglist:
        if k == firstwidth:
            addstr = ""
        else:
            addstr = sepstr
        k = k + len(argument) + len(addstr)
        if k > width:
            k = firstwidth + 1 + len(argument)
            newstr = newstr + ",\n" + " "*(firstwidth+2) + argument
        else:
            newstr = newstr + addstr + argument
    return newstr

_namedict = None
_dictlist = None

# Traverse all module directories underneath globals to see if something is defined
def makenamedict():
    import scipy
    thedict = {'scipy':scipy.__dict__}
    dictlist = ['scipy']
    totraverse = [scipy.__dict__]
    while 1:
        if len(totraverse) == 0:
            break
        thisdict = totraverse.pop(0)
        for x in thisdict.keys():
            if isinstance(thisdict[x],types.ModuleType):
                modname = thisdict[x].__name__
                if modname not in dictlist:
                    moddict = thisdict[x].__dict__
                    dictlist.append(modname)
                    totraverse.append(moddict)
                    thedict[modname] = moddict
    return thedict, dictlist

def info(object=None,maxwidth=76,output=sys.stdout,):
    """Get help information for a function, class, or module.

       Example:
          >>> from scipy import *
          >>> info(polyval)
          polyval(p, x)

            Evaluate the polymnomial p at x.

            Description:
                If p is of length N, this function returns the value:
                p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1]
    """
    global _namedict, _dictlist

    if hasattr(object,'_ppimport_importer') or \
       hasattr(object, '_ppimport_module'):
	object = object._ppimport_module
    elif hasattr(object, '_ppimport_attr'):
        object = object._ppimport_attr

    if object is None:
        info(info)
    elif isinstance(object, types.StringType):
        if _namedict is None:
            _namedict, _dictlist = makenamedict()
        numfound = 0
        objlist = []
        for namestr in _dictlist:
            try:
                obj = _namedict[namestr][object]
                if id(obj) in objlist:
                    print >> output, "\n     *** Repeat reference found in %s *** " % namestr
                else:
                    objlist.append(id(obj))
                    print >> output, "     *** Found in %s ***" % namestr
                    info(obj)
                    print >> output, "-"*maxwidth
                numfound += 1
            except KeyError:
                pass
        if numfound == 0:
            print >> output, "Help for %s not found." % object
        else:
            print >> output, "\n     *** Total of %d references found. ***" % numfound

    elif inspect.isfunction(object):
        name = object.func_name
        arguments = apply(inspect.formatargspec, inspect.getargspec(object))

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        print >> output, inspect.getdoc(object)

    elif inspect.isclass(object):
        name = object.__name__
        if hasattr(object, '__init__'):
            arguments = apply(inspect.formatargspec, inspect.getargspec(object.__init__.im_func))
            arglist = arguments.split(', ')
            if len(arglist) > 1:
                arglist[1] = "("+arglist[1]
                arguments = ", ".join(arglist[1:])
            else:
                arguments = "()"
        else:
            arguments = "()"

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        doc1 = inspect.getdoc(object)
        if doc1 is None:
            if hasattr(object,'__init__'):
                print >> output, inspect.getdoc(object.__init__)
        else:
            print >> output, inspect.getdoc(object)

    elif type(object) is types.InstanceType: ## check for __call__ method
        print >> output, "Instance of class: ", object.__class__.__name__
        print >> output
        if hasattr(object, '__call__'):
            arguments = apply(inspect.formatargspec, inspect.getargspec(object.__call__.im_func))
            arglist = arguments.split(', ')
            if len(arglist) > 1:
                arglist[1] = "("+arglist[1]
                arguments = ", ".join(arglist[1:])
            else:
                arguments = "()"

            name = "<name>"
            if len(name+arguments) > maxwidth:
                argstr = split_line(name, arguments, maxwidth)
            else:
                argstr = name + arguments

            print >> output, " " + argstr + "\n"
            doc = inspect.getdoc(object.__call__)
            if doc is not None:
                print >> output, inspect.getdoc(object.__call__)
            print >> output, inspect.getdoc(object)

        else:
            print >> output, inspect.getdoc(object)

    elif inspect.ismethod(object):
        name = object.__name__
        arguments = apply(inspect.formatargspec, inspect.getargspec(object.im_func))
        arglist = arguments.split(', ')
        if len(arglist) > 1:
            arglist[1] = "("+arglist[1]
            arguments = ", ".join(arglist[1:])
        else:
            arguments = "()"

        if len(name+arguments) > maxwidth:
            argstr = split_line(name, arguments, maxwidth)
        else:
            argstr = name + arguments

        print >> output, " " + argstr + "\n"
        print >> output, inspect.getdoc(object)

    elif hasattr(object, '__doc__'):
        print >> output, inspect.getdoc(object)

def source(object, output=sys.stdout):
    if inspect.isroutine(object):
        print >> output,  "In file: %s\n" % inspect.getsourcefile(object)
        print >> output,  inspect.getsource(object)
    else:
        print >> output,  "Not available for this object."

<|endoftext|>


<commit_before>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module containing the boiler plate required to construct templates
"""

__authors__ = [
  '"Daniel Hans" <daniel.m.hans@gmail.com>',
  ]

from soc.views import forms
from soc.views import org_app

TEMPLATE_PATH = 'v2/modules/gci/_form.html'

class GCIModelForm(forms.ModelForm):
  """Django ModelForm class which uses our implementation of BoundField.
  """

  def __init__(self, *args, **kwargs):
    super(GCIModelForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class OrgAppEditForm(org_app.OrgAppEditForm):
  """Form to create/edit GCI organization application survey.
  """

  def __init__(self, *args, **kwargs):
    super(OrgAppEditForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class OrgAppTakeForm(org_app.OrgAppTakeForm):
  """Form for would-be organization admins to apply for a GCI program.
  """

  def __init__(self, *args, **kwargs):
    super(OrgAppTakeForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class GCIBoundField(forms.BoundField):
  """GCI specific BoundField representation.
  """

  def render(self):
    raise NotImplementedError
<commit_msg>Initial (not working) implementation of render function in GCIBoundField.<commit_after>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module containing the boiler plate required to construct templates
"""

__authors__ = [
  '"Daniel Hans" <daniel.m.hans@gmail.com>',
  ]

from soc.views import forms
from soc.views import org_app

TEMPLATE_PATH = 'v2/modules/gci/_form.html'

class GCIModelForm(forms.ModelForm):
  """Django ModelForm class which uses our implementation of BoundField.
  """

  def __init__(self, *args, **kwargs):
    super(GCIModelForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class OrgAppEditForm(org_app.OrgAppEditForm):
  """Form to create/edit GCI organization application survey.
  """

  def __init__(self, *args, **kwargs):
    super(OrgAppEditForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class OrgAppTakeForm(org_app.OrgAppTakeForm):
  """Form for would-be organization admins to apply for a GCI program.
  """

  def __init__(self, *args, **kwargs):
    super(OrgAppTakeForm, self).__init__(
        GCIBoundField, TEMPLATE_PATH, *args, **kwargs)

class GCIBoundField(forms.BoundField):
  """GCI specific BoundField representation.
  """

  def render(self):
    widget = self.field.widget

    return self.NOT_SUPPORTED_MSG_FMT % (
        widget.__class__.__name__)
<|endoftext|>


<commit_before>#! /usr/bin/env python

"""Classes to handle Unix style, MMDF style, and MH style mailboxes."""

import rfc822
import os

class _Mailbox:

	def __init__(self, fp):
		self.fp = fp
		self.seekp = 0

	def seek(self, pos, whence=0):
		if whence==1:		# Relative to current position
			self.pos = self.pos + pos
		if whence==2:		# Relative to file's end
			self.pos = self.stop + pos
		else:			# Default - absolute position
			self.pos = self.start + pos

	def next(self):
		while 1:
			self.fp.seek(self.seekp)
			try:
				self._search_start()
			except EOFError:
				self.seekp = self.fp.tell()
				return None
			start = self.fp.tell()
			self._search_end()
			self.seekp = stop = self.fp.tell()
			if start <> stop:
				break
		return rfc822.Message(_Subfile(self.fp, start, stop))

class _Subfile:

	def __init__(self, fp, start, stop):
		self.fp = fp
		self.start = start
		self.stop = stop
		self.pos = self.start

	def read(self, length = None):
		if self.pos >= self.stop:
			return ''
		if length is None:
			length = self.stop - self.pos
		self.fp.seek(self.pos)
		self.pos = self.pos + length
		return self.fp.read(length)

	def readline(self, length = None):
		if self.pos >= self.stop:
			return ''
		if length is None:
			length = self.stop - self.pos
		self.fp.seek(self.pos)
		data = self.fp.readline(length)
		if len(data) < length:
			length = len(data)
		self.pos = self.pos + length
		return data

	def tell(self):
		return self.pos - self.start

	def seek(self, pos, whence=0):
		if whence == 0:
			self.pos = self.start + pos
		elif whence == 1:
			self.pos = self.pos + pos
		elif whence == 2:
			self.pos = self.stop + pos

	def close(self):
		pass

class UnixMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line[:5] == 'From ':
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line[:5] == 'From ':
				self.fp.seek(pos)
				return

class MmdfMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line[:5] == '\001\001\001\001\n':
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line == '\001\001\001\001\n':
				self.fp.seek(pos)
				return

class MHMailbox:

	def __init__(self, dirname):
		import re
		pat = re.compile('^[0-9][0-9]*$')
		self.dirname = dirname
		files = os.listdir(self.dirname)
		self.boxes = []
		for f in files:
			if pat.match(f):
				self.boxes.append(f)

	def next(self):
		if not self.boxes:
			return None
		fn = self.boxes[0]
		del self.boxes[0]
		fp = open(os.path.join(self.dirname, fn))
		return rfc822.Message(fp)

class BabylMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line == '*** EOOH ***\n':
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line == '\037\014\n':
				self.fp.seek(pos)
				return

def _test():
	import time
	import sys
	import string
	import os

	args = sys.argv[1:]
	if not args:
		for key in 'MAIL', 'LOGNAME', 'USER':
			if os.environ.has_key(key):
				mbox = os.environ[key]
				break
		else:
			print "$MAIL, $LOGNAME nor $USER set -- who are you?"
			return
	else:
		mbox = args[0]
	if mbox[:1] == '+':
		mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
	elif not '/' in mbox:
		mbox = '/usr/mail/' + mbox
	if os.path.isdir(mbox):
		mb = MHMailbox(mbox)
	else:
		fp = open(mbox, 'r')
		mb = UnixMailbox(fp)

	msgs = []
	while 1:
		msg = mb.next()
		if not msg:
			break
		msgs.append(msg)
		msg.fp = None
	if len(args) > 1:
		num = string.atoi(args[1])
		print 'Message %d body:'%num
		msg = msgs[num-1]
		msg.rewindbody()
		sys.stdout.write(msg.fp.read())
	else:
		print 'Mailbox',mbox,'has',len(msgs),'messages:'
		for msg in msgs:
			f = msg.getheader('from')
			s = msg.getheader('subject')
			d = (msg.getheader('date'))
			print '%20.20s   %18.18s   %-30.30s'%(f, d[5:], s)

if __name__ == '__main__':
	_test()
<commit_msg>UnixMailbox: don't be fooled by lines that begin with "From " but otherwise don't look like headers at all... Also robustify the test code a bit.<commit_after>#! /usr/bin/env python

"""Classes to handle Unix style, MMDF style, and MH style mailboxes."""

import rfc822
import os

class _Mailbox:

	def __init__(self, fp):
		self.fp = fp
		self.seekp = 0

	def seek(self, pos, whence=0):
		if whence==1:		# Relative to current position
			self.pos = self.pos + pos
		if whence==2:		# Relative to file's end
			self.pos = self.stop + pos
		else:			# Default - absolute position
			self.pos = self.start + pos

	def next(self):
		while 1:
			self.fp.seek(self.seekp)
			try:
				self._search_start()
			except EOFError:
				self.seekp = self.fp.tell()
				return None
			start = self.fp.tell()
			self._search_end()
			self.seekp = stop = self.fp.tell()
			if start <> stop:
				break
		return rfc822.Message(_Subfile(self.fp, start, stop))

class _Subfile:

	def __init__(self, fp, start, stop):
		self.fp = fp
		self.start = start
		self.stop = stop
		self.pos = self.start

	def read(self, length = None):
		if self.pos >= self.stop:
			return ''
		if length is None:
			length = self.stop - self.pos
		self.fp.seek(self.pos)
		self.pos = self.pos + length
		return self.fp.read(length)

	def readline(self, length = None):
		if self.pos >= self.stop:
			return ''
		if length is None:
			length = self.stop - self.pos
		self.fp.seek(self.pos)
		data = self.fp.readline(length)
		if len(data) < length:
			length = len(data)
		self.pos = self.pos + length
		return data

	def tell(self):
		return self.pos - self.start

	def seek(self, pos, whence=0):
		if whence == 0:
			self.pos = self.start + pos
		elif whence == 1:
			self.pos = self.pos + pos
		elif whence == 2:
			self.pos = self.stop + pos

	def close(self):
		pass

class UnixMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line[:5] == 'From ' and self._isrealfromline(line):
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line[:5] == 'From ' and self._isrealfromline(line):
				self.fp.seek(pos)
				return

	# An overridable mechanism to test for From-line-ness.
	# You can either specify a different regular expression
	# or define a whole new _isrealfromline() method.
	# Note that this only gets called for lines starting with
	# the 5 characters "From ".

	_fromlinepattern = r"From \s*[^\s]+\s+\w\w\w\s+\w\w\w\s+\d?\d\s+" \
			   r"\d?\d:\d\d:\d\d(\s+[^\s]+)?\s+\d\d\d\d\s*$"
	_regexp = None

	def _isrealfromline(self, line):
		if not self._regexp:
			import re
			self._regexp = re.compile(self._fromlinepattern)
		return self._regexp.match(line)

class MmdfMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line[:5] == '\001\001\001\001\n':
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line == '\001\001\001\001\n':
				self.fp.seek(pos)
				return

class MHMailbox:

	def __init__(self, dirname):
		import re
		pat = re.compile('^[0-9][0-9]*$')
		self.dirname = dirname
		files = os.listdir(self.dirname)
		self.boxes = []
		for f in files:
			if pat.match(f):
				self.boxes.append(f)

	def next(self):
		if not self.boxes:
			return None
		fn = self.boxes[0]
		del self.boxes[0]
		fp = open(os.path.join(self.dirname, fn))
		return rfc822.Message(fp)

class BabylMailbox(_Mailbox):

	def _search_start(self):
		while 1:
			line = self.fp.readline()
			if not line:
				raise EOFError
			if line == '*** EOOH ***\n':
				return

	def _search_end(self):
		while 1:
			pos = self.fp.tell()
			line = self.fp.readline()
			if not line:
				return
			if line == '\037\014\n':
				self.fp.seek(pos)
				return

def _test():
	import time
	import sys
	import string
	import os

	args = sys.argv[1:]
	if not args:
		for key in 'MAIL', 'LOGNAME', 'USER':
			if os.environ.has_key(key):
				mbox = os.environ[key]
				break
		else:
			print "$MAIL, $LOGNAME nor $USER set -- who are you?"
			return
	else:
		mbox = args[0]
	if mbox[:1] == '+':
		mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
	elif not '/' in mbox:
		mbox = '/usr/mail/' + mbox
	if os.path.isdir(mbox):
		mb = MHMailbox(mbox)
	else:
		fp = open(mbox, 'r')
		mb = UnixMailbox(fp)

	msgs = []
	while 1:
		msg = mb.next()
		if msg is None:
			break
		msgs.append(msg)
		msg.fp = None
	if len(args) > 1:
		num = string.atoi(args[1])
		print 'Message %d body:'%num
		msg = msgs[num-1]
		msg.rewindbody()
		sys.stdout.write(msg.fp.read())
	else:
		print 'Mailbox',mbox,'has',len(msgs),'messages:'
		for msg in msgs:
			f = msg.getheader('from') or ""
			s = msg.getheader('subject') or ""
			d = msg.getheader('date') or ""
			print '%20.20s   %18.18s   %-30.30s'%(f, d[5:], s)

if __name__ == '__main__':
	_test()
<|endoftext|>


<commit_before># persist.py
#
# Implement limited persistence.
#
# Simple interface:
#	persist.save()		save __main__ module on file (overwrite)
#	persist.load()		load __main__ module from file (merge)
#
# These use the filename persist.defaultfile, initialized to 'wsrestore.py'.
#
# A raw interface also exists:
#	persist.writedict(dict, fp)	save dictionary to open file
#	persist.readdict(dict, fp)	read (merge) dictionary from open file
#
# Internally, the function dump() and a whole bunch of support of functions
# traverse a graph of objects and print them in a restorable form
# (which happens to be a Python module).
#
# XXX Limitations:
# - Volatile objects are dumped as strings:
#   - open files, windows etc.
# - Other 'obscure' objects are dumped as strings:
#   - classes, instances and methods
#   - compiled regular expressions
#   - anything else reasonably obscure (e.g., capabilities)
#   - type objects for obscure objects
# - It's slow when there are many of lists or dictionaries
#   (This could be fixed if there were a quick way to compute a hash
#   function of any object, even if recursive)

defaultfile = 'wsrestore.py'

def save():
	import __main__
	import posix
	# XXX On SYSV, if len(defaultfile) >= 14, this is wrong!
	backup = defaultfile + '~'
	try:
		posix.unlink(backup)
	except posix.error:
		pass
	try:
		posix.rename(defaultfile, backup)
	except posix.error:
		pass
	fp = open(defaultfile, 'w')
	writedict(__main__.__dict__, fp)
	fp.close()

def load():
	import __main__
	fp = open(defaultfile, 'r')
	readdict(__main__.__dict__, fp)

def writedict(dict, fp):
	import sys
	savestdout = sys.stdout
	try:
		sys.stdout = fp
		dump(dict)	# Writes to sys.stdout
	finally:
		sys.stdout = savestdout

def readdict(dict, fp):
	contents = fp.read()		# Or: util.readopenfile(fp)
	globals = {}
	exec(contents, globals)
	top = globals['top']
	for key in top.keys():
		if dict.has_key(key):
			print 'warning:', key, 'not overwritten'
		else:
			dict[key] = top[key]

# Function dump(x) prints (on sys.stdout!) a sequence of Python statements
# that, when executed in an empty environment, will reconstruct the
# contents of an arbitrary dictionary.

import sys

# Name used for objects dict on output.
#
FUNNYNAME = FN = 'A'

# Top-level function.  Call with the object you want to dump.
#
def dump(x):
	types = {}
	stack = []			# Used by test for recursive objects
	print FN, '= {}'
	topuid = dumpobject(x, types, stack)
	print 'top =', FN, '[', `topuid`, ']'

# Generic function to dump any object.
#
dumpswitch = {}
#
def dumpobject(x, types, stack):
	typerepr = `type(x)`
	if not types.has_key(typerepr):
		types[typerepr] = {}
	typedict = types[typerepr]
	if dumpswitch.has_key(typerepr):
		return dumpswitch[typerepr](x, typedict, types, stack)
	else:
		return dumpbadvalue(x, typedict, types, stack)

# Generic function to dump unknown values.
# This assumes that the Python interpreter prints such values as
# <foo object at xxxxxxxx>.
# The object will be read back as a string: '<foo object at xxxxxxxx>'.
# In some cases it may be possible to fix the dump manually;
# to ease the editing, these cases are labeled with an XXX comment.
#
def dumpbadvalue(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] =', `xrepr`, '# XXX'
	return uid

# Generic function to dump pure, simple values, except strings
#
def dumpvalue(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] =', `x`
	return uid

# Functions to dump string objects
#
def dumpstring(x, typedict, types, stack):
	# XXX This can break if strings have embedded '\0' bytes
	# XXX because of a bug in the dictionary module
	if typedict.has_key(x):
		return typedict[x]
	uid = genuid()
	typedict[x] = uid
	print FN, '[', `uid`, '] =', `x`
	return uid

# Function to dump type objects
#
typeswitch = {}
class some_class():
	def method(self): pass
some_instance = some_class()
#
def dumptype(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	if typeswitch.has_key(xrepr):
		print FN, '[', `uid`, '] =', typeswitch[xrepr]
	elif x = type(sys):
		print 'import sys'
		print FN, '[', `uid`, '] = type(sys)'
	elif x = type(sys.stderr):
		print 'import sys'
		print FN, '[', `uid`, '] = type(sys.stderr)'
	elif x = type(dumptype):
		print 'def some_function(): pass'
		print FN, '[', `uid`, '] = type(some_function)'
	elif x = type(some_class):
		print 'class some_class(): pass'
		print FN, '[', `uid`, '] = type(some_class)'
	elif x = type(some_instance):
		print 'class another_class(): pass'
		print 'some_instance = another_class()'
		print FN, '[', `uid`, '] = type(some_instance)'
	elif x = type(some_instance.method):
		print 'class yet_another_class():'
		print '    def method(): pass'
		print 'another_instance = yet_another_class()'
		print FN, '[', `uid`, '] = type(another_instance.method)'
	else:
		# Unknown type
		print FN, '[', `uid`, '] =', `xrepr`, '# XXX'
	return uid

# Initialize the typeswitch
#
for x in None, 0, 0.0, '', (), [], {}:
	typeswitch[`type(x)`] = 'type(' + `x` + ')'
for s in 'type(0)', 'abs', '[].append':
	typeswitch[`type(eval(s))`] = 'type(' + s + ')'

# Dump a tuple object
#
def dumptuple(x, typedict, types, stack):
	item_uids = []
	xrepr = ''
	for item in x:
		item_uid = dumpobject(item, types, stack)
		item_uids.append(item_uid)
		xrepr = xrepr + ' ' + item_uid
	del stack[-1:]
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] = (',
	for item_uid in item_uids:
		print FN, '[', `item_uid`, '],',
	print ')'
	return uid

# Dump a list object
#
def dumplist(x, typedict, types, stack):
	# Check for recursion
	for x1, uid1 in stack:
		if x is x1: return uid1
	# Check for occurrence elsewhere in the typedict
	for uid1 in typedict.keys():
		if x is typedict[uid1]: return uid1
	# This uses typedict differently!
	uid = genuid()
	typedict[uid] = x
	print FN, '[', `uid`, '] = []'
	stack.append(x, uid)
	item_uids = []
	for item in x:
		item_uid = dumpobject(item, types, stack)
		item_uids.append(item_uid)
	del stack[-1:]
	for item_uid in item_uids:
		print FN, '[', `uid`, '].append(', FN, '[', `item_uid`, '])'
	return uid

# Dump a dictionary object
#
def dumpdict(x, typedict, types, stack):
	# Check for recursion
	for x1, uid1 in stack:
		if x is x1: return uid1
	# Check for occurrence elsewhere in the typedict
	for uid1 in typedict.keys():
		if x is typedict[uid1]: return uid1
	# This uses typedict differently!
	uid = genuid()
	typedict[uid] = x
	print FN, '[', `uid`, '] = {}'
	stack.append(x, uid)
	item_uids = []
	for key in x.keys():
		val_uid = dumpobject(x[key], types, stack)
		item_uids.append(key, val_uid)
	del stack[-1:]
	for key, val_uid in item_uids:
		print FN, '[', `uid`, '][', `key`, '] =',
		print FN, '[', `val_uid`, ']'
	return uid

# Dump a module object
#
def dumpmodule(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	from string import split
	# `x` has the form <module 'foo'>
	name = xrepr[9:-2]
	uid = genuid()
	typedict[xrepr] = uid
	print 'import', name
	print FN, '[', `uid`, '] =', name
	return uid

# Initialize dumpswitch, a table of functions to dump various objects,
# indexed by `type(x)`.
#
for x in None, 0, 0.0:
	dumpswitch[`type(x)`] = dumpvalue
for x, f in ('', dumpstring), (type(0), dumptype), ((), dumptuple), \
		([], dumplist), ({}, dumpdict), (sys, dumpmodule):
	dumpswitch[`type(x)`] = f

# Generate the next unique id; a string consisting of digits.
# The seed is stored as seed[0].
#
seed = [0]
#
def genuid():
	x = seed[0]
	seed[0] = seed[0] + 1
	return `x`
<commit_msg>Remove reference to util.<commit_after># persist.py
#
# Implement limited persistence.
#
# Simple interface:
#	persist.save()		save __main__ module on file (overwrite)
#	persist.load()		load __main__ module from file (merge)
#
# These use the filename persist.defaultfile, initialized to 'wsrestore.py'.
#
# A raw interface also exists:
#	persist.writedict(dict, fp)	save dictionary to open file
#	persist.readdict(dict, fp)	read (merge) dictionary from open file
#
# Internally, the function dump() and a whole bunch of support of functions
# traverse a graph of objects and print them in a restorable form
# (which happens to be a Python module).
#
# XXX Limitations:
# - Volatile objects are dumped as strings:
#   - open files, windows etc.
# - Other 'obscure' objects are dumped as strings:
#   - classes, instances and methods
#   - compiled regular expressions
#   - anything else reasonably obscure (e.g., capabilities)
#   - type objects for obscure objects
# - It's slow when there are many of lists or dictionaries
#   (This could be fixed if there were a quick way to compute a hash
#   function of any object, even if recursive)

defaultfile = 'wsrestore.py'

def save():
	import __main__
	import posix
	# XXX On SYSV, if len(defaultfile) >= 14, this is wrong!
	backup = defaultfile + '~'
	try:
		posix.unlink(backup)
	except posix.error:
		pass
	try:
		posix.rename(defaultfile, backup)
	except posix.error:
		pass
	fp = open(defaultfile, 'w')
	writedict(__main__.__dict__, fp)
	fp.close()

def load():
	import __main__
	fp = open(defaultfile, 'r')
	readdict(__main__.__dict__, fp)

def writedict(dict, fp):
	import sys
	savestdout = sys.stdout
	try:
		sys.stdout = fp
		dump(dict)	# Writes to sys.stdout
	finally:
		sys.stdout = savestdout

def readdict(dict, fp):
	contents = fp.read()
	globals = {}
	exec(contents, globals)
	top = globals['top']
	for key in top.keys():
		if dict.has_key(key):
			print 'warning:', key, 'not overwritten'
		else:
			dict[key] = top[key]

# Function dump(x) prints (on sys.stdout!) a sequence of Python statements
# that, when executed in an empty environment, will reconstruct the
# contents of an arbitrary dictionary.

import sys

# Name used for objects dict on output.
#
FUNNYNAME = FN = 'A'

# Top-level function.  Call with the object you want to dump.
#
def dump(x):
	types = {}
	stack = []			# Used by test for recursive objects
	print FN, '= {}'
	topuid = dumpobject(x, types, stack)
	print 'top =', FN, '[', `topuid`, ']'

# Generic function to dump any object.
#
dumpswitch = {}
#
def dumpobject(x, types, stack):
	typerepr = `type(x)`
	if not types.has_key(typerepr):
		types[typerepr] = {}
	typedict = types[typerepr]
	if dumpswitch.has_key(typerepr):
		return dumpswitch[typerepr](x, typedict, types, stack)
	else:
		return dumpbadvalue(x, typedict, types, stack)

# Generic function to dump unknown values.
# This assumes that the Python interpreter prints such values as
# <foo object at xxxxxxxx>.
# The object will be read back as a string: '<foo object at xxxxxxxx>'.
# In some cases it may be possible to fix the dump manually;
# to ease the editing, these cases are labeled with an XXX comment.
#
def dumpbadvalue(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] =', `xrepr`, '# XXX'
	return uid

# Generic function to dump pure, simple values, except strings
#
def dumpvalue(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] =', `x`
	return uid

# Functions to dump string objects
#
def dumpstring(x, typedict, types, stack):
	# XXX This can break if strings have embedded '\0' bytes
	# XXX because of a bug in the dictionary module
	if typedict.has_key(x):
		return typedict[x]
	uid = genuid()
	typedict[x] = uid
	print FN, '[', `uid`, '] =', `x`
	return uid

# Function to dump type objects
#
typeswitch = {}
class some_class():
	def method(self): pass
some_instance = some_class()
#
def dumptype(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	if typeswitch.has_key(xrepr):
		print FN, '[', `uid`, '] =', typeswitch[xrepr]
	elif x = type(sys):
		print 'import sys'
		print FN, '[', `uid`, '] = type(sys)'
	elif x = type(sys.stderr):
		print 'import sys'
		print FN, '[', `uid`, '] = type(sys.stderr)'
	elif x = type(dumptype):
		print 'def some_function(): pass'
		print FN, '[', `uid`, '] = type(some_function)'
	elif x = type(some_class):
		print 'class some_class(): pass'
		print FN, '[', `uid`, '] = type(some_class)'
	elif x = type(some_instance):
		print 'class another_class(): pass'
		print 'some_instance = another_class()'
		print FN, '[', `uid`, '] = type(some_instance)'
	elif x = type(some_instance.method):
		print 'class yet_another_class():'
		print '    def method(): pass'
		print 'another_instance = yet_another_class()'
		print FN, '[', `uid`, '] = type(another_instance.method)'
	else:
		# Unknown type
		print FN, '[', `uid`, '] =', `xrepr`, '# XXX'
	return uid

# Initialize the typeswitch
#
for x in None, 0, 0.0, '', (), [], {}:
	typeswitch[`type(x)`] = 'type(' + `x` + ')'
for s in 'type(0)', 'abs', '[].append':
	typeswitch[`type(eval(s))`] = 'type(' + s + ')'

# Dump a tuple object
#
def dumptuple(x, typedict, types, stack):
	item_uids = []
	xrepr = ''
	for item in x:
		item_uid = dumpobject(item, types, stack)
		item_uids.append(item_uid)
		xrepr = xrepr + ' ' + item_uid
	del stack[-1:]
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	uid = genuid()
	typedict[xrepr] = uid
	print FN, '[', `uid`, '] = (',
	for item_uid in item_uids:
		print FN, '[', `item_uid`, '],',
	print ')'
	return uid

# Dump a list object
#
def dumplist(x, typedict, types, stack):
	# Check for recursion
	for x1, uid1 in stack:
		if x is x1: return uid1
	# Check for occurrence elsewhere in the typedict
	for uid1 in typedict.keys():
		if x is typedict[uid1]: return uid1
	# This uses typedict differently!
	uid = genuid()
	typedict[uid] = x
	print FN, '[', `uid`, '] = []'
	stack.append(x, uid)
	item_uids = []
	for item in x:
		item_uid = dumpobject(item, types, stack)
		item_uids.append(item_uid)
	del stack[-1:]
	for item_uid in item_uids:
		print FN, '[', `uid`, '].append(', FN, '[', `item_uid`, '])'
	return uid

# Dump a dictionary object
#
def dumpdict(x, typedict, types, stack):
	# Check for recursion
	for x1, uid1 in stack:
		if x is x1: return uid1
	# Check for occurrence elsewhere in the typedict
	for uid1 in typedict.keys():
		if x is typedict[uid1]: return uid1
	# This uses typedict differently!
	uid = genuid()
	typedict[uid] = x
	print FN, '[', `uid`, '] = {}'
	stack.append(x, uid)
	item_uids = []
	for key in x.keys():
		val_uid = dumpobject(x[key], types, stack)
		item_uids.append(key, val_uid)
	del stack[-1:]
	for key, val_uid in item_uids:
		print FN, '[', `uid`, '][', `key`, '] =',
		print FN, '[', `val_uid`, ']'
	return uid

# Dump a module object
#
def dumpmodule(x, typedict, types, stack):
	xrepr = `x`
	if typedict.has_key(xrepr):
		return typedict[xrepr]
	from string import split
	# `x` has the form <module 'foo'>
	name = xrepr[9:-2]
	uid = genuid()
	typedict[xrepr] = uid
	print 'import', name
	print FN, '[', `uid`, '] =', name
	return uid

# Initialize dumpswitch, a table of functions to dump various objects,
# indexed by `type(x)`.
#
for x in None, 0, 0.0:
	dumpswitch[`type(x)`] = dumpvalue
for x, f in ('', dumpstring), (type(0), dumptype), ((), dumptuple), \
		([], dumplist), ({}, dumpdict), (sys, dumpmodule):
	dumpswitch[`type(x)`] = f

# Generate the next unique id; a string consisting of digits.
# The seed is stored as seed[0].
#
seed = [0]
#
def genuid():
	x = seed[0]
	seed[0] = seed[0] + 1
	return `x`
<|endoftext|>


<commit_before>import numpy as np
import matplotlib.pyplot as plt
import scipy.stats.mstats as ssm
import metallicity
import os

##############################################################################
##Reads the flux file and returns it as an array.
##Ignores non-numeric lines
##Returns  (flux array,num)
##############################################################################
def readfile(filename):
    a=open(filename,'r')
    b=np.array([])
    i=0
    j=0

    for line in a:
        err_count=0
        strs=np.array(line.rstrip('\n').split())
        i=strs.size
        for word in range(i):
            try:
                strs[word]=strs[word].astype(np.float)
            except ValueError:
                err_count+=1
                strs[word]=-1
        strs=strs.astype(np.float)
        if err_count<i/2-1:
            b=np.append(b,strs,axis=0)
            j+=1
    b.resize(j,i)
    b=np.transpose(b)
    a.close()

    return b,j

##############################################################################
##a simple gaussian
##############################################################################
def gaussian(x,m,s):
    return 1./(s*np.sqrt(2*np.pi)) * np.exp(-(x-m)**2 /(2 *s**2))

##############################################################################
##returns appropriate bin size for the number of data
##mode 'd' calculates this based on Doane's formula (default)
##mode 's' calculates this based on sqrt of number of data
##mode 't' calculates this based on 2*n**1/3
##############################################################################
def getbinsize(n,data,mode='t'):
    if mode=='d':
        g1=ssm.moment(data,moment=3)
        s1=np.sqrt(6.*(n-2.)/((n+1.)*(n+3.)))
        k=1+np.log2(n)+np.log2(1+np.abs(g1/s1))
    elif mode=='s':
        k=np.sqrt(n)
    elif mode=='t':
        k=2.*n**(1./3.)
    return k
##############################################################################
##almost (symmetric) method
##estimating error starting at the peak.
##almost (symmetric) - make it go same l and r
##not well behaved in case of multiple peaks
##code not up to date(oct 21 2013)
##############################################################################
def err_est1(count,prob=0.68):
    peak=np.argmax(count)
    total=np.sum(count)
    temp=0
    l=0
    r=0
    while temp<total*prob:
        if count[peak-l]>=count[peak+r]:
            temp+=count[peak-l]
            l+=1
        else:
            temp+=count[peak+r]
            r+=1

    return peak-l,peak-r,(total-temp)/total,0,0

##############################################################################
##(central) method
#estmating error starting from the ends.
##input: 'count' returned from plt.hist, 'prob' default 68%
##output: the index of left boundary, right boundary, confidence,
#fraction to be shifted to left, fraction to be shifted from the right
##############################################################################
def err_est(count,prob=0.68):
    total=np.sum(count)
    l=0
    fl=0.
    r=len(count)-1
    fr=0.
    ltemp=count[l]
    rtemp=count[r]

    thresh=total*(1.-prob)/2.
    while ltemp<=thresh:
        l+=1
        ltemp+=count[l]
        if ltemp>thresh:
            ltemp-=count[l]
            fl=(thresh-ltemp)/count[l]
            l-=1
            break
    while rtemp<=thresh:
        r-=1
        rtemp+=count[r]
        if rtemp>thresh:
            rtemp-=count[r]
            fr=(thresh-rtemp)/count[r]
            r+=1
            break
    return l,r,(total-2*thresh)/total,fl,1-fr

##############################################################################
##Save the result as histogram as name
## delog - if true de-logs the data. False by default
##############################################################################
def savehist(data,filename,Zs,nsample,i,delog=False,mode='t'):
    p=os.path.abspath('..')
    name='%s_n%d_%s_i%d'%((filename,nsample,Zs,i))
    outfile=p+'\\bins\\%s\\hist\\%s.png'%(filename,name)
    plt.clf()

    ###de-log###
    if delog==True:
        data=np.power(10,np.absolute(data-12))

    data=np.sort(data)
    data=data[np.where(np.isfinite(data)==True)]

    ####kill outliers###
    mean=np.mean(data)
    std=np.std(data)
    data=data[np.where(data>mean-5*std)]
    data=data[np.where(data<mean+5*std)]
    n=data.shape[0]
    if data.shape[0]<=0:
        print name,'is blank' ##if no data
        return "-1, -1"

    try:
        ######find fit and save hist######
        ###find appropriate bin size###
        numbin=getbinsize(data.shape[0],data,mode)

        ###make hist###
        count, bins, ignored = plt.hist(data, numbin, normed=1.0)

        ###find error###
        l,r,t,fl,fr=err_est(count)
        y=np.zeros(len(bins))
        left=bins[l]+(bins[l+1]-bins[l])*fl
        right=bins[r]-(bins[r]-bins[r-1])*fr

        ###plot hist###
        plt.plot(bins,y)
        plt.axvspan(left,right,color='red',alpha=0.4)
        st='n=%d\nconfidence: %f\nleft: %f\nright: %f'%(n,t,left,right)
        plt.annotate(st, xy=(0.70, 0.80), xycoords='axes fraction')
        plt.title(name)
        if delog==True:
            plt.xlabel('O/H')
        else:
            plt.xlabel('12+log(O/H)')
        plt.ylabel('counts')
        plt.savefig(outfile)

        ###print out the confidence interval###
        print name, ':\t%f +- %f'%((left+right)/2.,(right-left)/2.)
        return "%f, %f"%((left+right)/2.,(right-left)/2.)

    except (OverflowError,AttributeError,ValueError):
        print data
        print name, 'had infinities'
        return "-2, -2"

##############################################################################
## The main function. takes the flux and its error as input.
##  filename - a string 'filename' common to the three flux files
##  flux - np array of the fluxes
##  err - the flux errors, must be the same dimension as flux
##  nsample - the number of samples the code will generate. Default is 100
##  errmode - determines which method to choose the bin size.
##      mode 'd' calculates this based on Doane's formula
##      mode 's' calculates this based on sqrt of number of data
##      mode 't' calculates this based on 2*n**1/3 (default)
##############################################################################
def run((filename, flux, err), nsample,binmode='t'):
    p=os.path.abspath('..')
    ###flux and err must be same dimensions
    if flux.shape != err.shape:
        print "flux and err must be of same dimensions"
        return
    nm = flux.shape[1]

    ###retrieve the metallicity keys
    Zs= metallicity.get_keys()

    ###make necessary paths
    if not os.path.exists(p+'\\bins\\%s'%filename):
        os.makedirs(p+'\\bins\\%s'%filename)
        os.makedirs(p+'\\bins\\%s\\hist'%filename)
    binp=p+'\\bins\\%s\\'%filename

    ###Sample 'nsample' points from a gaussian###
    ##a gaussian centered on 0 with std 1
    mu=0
    sigma=1
    sample=np.random.normal(mu,sigma,nsample)

    ###save this sampled gaussians into a png file###
    count, bins, ignored = plt.hist(sample, 40,normed=1)
    plt.plot(bins,gaussian(bins,mu,sigma))
    plt.title("Sampled")
    st="n=%d"%nsample
    plt.annotate(st, xy=(0.70, 0.85), xycoords='axes fraction')
    plt.savefig(binp+filename+'_n%d_sample.png'%nsample)
    plt.clf()

    ###Start calculation###
    ## the flux to be feed to the calculation will be
    ## flux + error*i
    ## where i is the sampled gaussian
    print "Starting iteration"

    #initialize the dictionary
    res={}
    for key in Zs:
        res[key]=[]

    #do the iterations
    for i in range(len(sample)):
        temp=flux+err*sample[i]
        t=metallicity.calculation(temp,nm)
        for key in Zs:
            res[key].append(t[key])

    #make the result a np.array
    for key in Zs:
        res[key]=np.array(res[key])

    print "Iteration Complete"

    ###Bin the results and save the uncertainty###
    for i in range(nm):
        fi=open(binp+'%s_n%d_i%d.csv'%(filename,nsample,i),'w')
        fi.write("%s, Metalicity, Uncertainty\n"%filename)

        for key in Zs:
            s=key+", "+savehist(res[key][:,i],filename,key,nsample,i,binmode)+'\n'
            fi.write(s)
        print "---------------------------------------------"
        fi.close()

    print "uncertainty calculation complete"

##############################################################################
##The input format generator
##############################################################################
def input_format(filename):
    p=os.path.abspath('..')

    if os.path.isfile(p+'\\sn_data\\%s_max.txt'%filename):
        if os.path.isfile(p+'\\sn_data\\%s_min.txt'%filename):
            if os.path.isfile(p+'\\sn_data\\%s_med.txt'%filename):
                return in_mmm(filename)
            else:
                return in_mm(filename)
    print "Unable to find _min and _max files in directory sn_data"
    return -1

def in_mmm(filename):
    p=os.path.abspath('..')
    p+='\\sn_data\\'
    ###Initialize###
    maxfile=p+filename+"_max.txt"
    medfile=p+filename+"_med.txt"
    minfile=p+filename+"_min.txt"

    ###read the max, med, min flux files###
    maxf,nm=readfile(maxfile)
    medf,num=readfile(medfile)
    minf,nn=readfile(minfile)

    ###calculate the flux error as 1/2 [(max-med)+(med-min)]###
    err=0.5*((maxf-medf)+(medf-minf))
    return (filename, medf, err)

def in_mm(filename):
    p=os.path.abspath('..')
    p+='\\sn_data\\'
    ###Initialize###
    maxfile=p+filename+"_max.txt"
    minfile=p+filename+"_min.txt"

    ###read the max, med, min flux files###
    maxf,nm=readfile(maxfile)
    minf,nn=readfile(minfile)
    ###calculate the flux error as 1/2 [(max-min)]###
    err=0.5*(maxf - minf)
    medf= minf+err
    return (filename, medf, err)
##############################################################################
##############################################################################
#### How to Use this code:
##############################################################################
##############################################################################
####example) if you have:
####     sn2006ss_max.txt
####     sn2006ss_med.txt
####     sn2006ss_min.txt
####
####     and you want to sample 5000 points
####     do:
####
#### filename="sn2006ss"
#### nsample=5000
####
##############################################################################
####Just edit this part to use
##############################################################################

files=['sn2006ss','ptf10eqi-z']
filename=files[1]

nsample=10000
fi=input_format(filename)
if fi!=-1:
    run(fi,nsample)
<commit_msg>Made the command line make sense<commit_after>import numpy as np
import matplotlib.pyplot as plt
import scipy.stats.mstats as ssm
import metallicity
import os

import sys, argparse

##############################################################################
##Reads the flux file and returns it as an array.
##Ignores non-numeric lines
##Returns  (flux array,num)
##############################################################################
def readfile(filename):
    a=open(filename,'r')
    b=np.array([])
    i=0
    j=0

    for line in a:
        err_count=0
        strs=np.array(line.rstrip('\n').split())
        i=strs.size
        for word in range(i):
            try:
                strs[word]=strs[word].astype(np.float)
            except ValueError:
                err_count+=1
                strs[word]=-1
        strs=strs.astype(np.float)
        if err_count<i/2-1:
            b=np.append(b,strs,axis=0)
            j+=1
    b.resize(j,i)
    b=np.transpose(b)
    a.close()

    return b,j

##############################################################################
##a simple gaussian
##############################################################################
def gaussian(x,m,s):
    return 1./(s*np.sqrt(2*np.pi)) * np.exp(-(x-m)**2 /(2 *s**2))

##############################################################################
##returns appropriate bin size for the number of data
##mode 'd' calculates this based on Doane's formula (default)
##mode 's' calculates this based on sqrt of number of data
##mode 't' calculates this based on 2*n**1/3
##############################################################################
def getbinsize(n,data,mode='t'):
    if mode=='d':
        g1=ssm.moment(data,moment=3)
        s1=np.sqrt(6.*(n-2.)/((n+1.)*(n+3.)))
        k=1+np.log2(n)+np.log2(1+np.abs(g1/s1))
    elif mode=='s':
        k=np.sqrt(n)
    elif mode=='t':
        k=2.*n**(1./3.)
    return k
##############################################################################
##almost (symmetric) method
##estimating error starting at the peak.
##almost (symmetric) - make it go same l and r
##not well behaved in case of multiple peaks
##code not up to date(oct 21 2013)
##############################################################################
def err_est1(count,prob=0.68):
    peak=np.argmax(count)
    total=np.sum(count)
    temp=0
    l=0
    r=0
    while temp<total*prob:
        if count[peak-l]>=count[peak+r]:
            temp+=count[peak-l]
            l+=1
        else:
            temp+=count[peak+r]
            r+=1

    return peak-l,peak-r,(total-temp)/total,0,0

##############################################################################
##(central) method
#estmating error starting from the ends.
##input: 'count' returned from plt.hist, 'prob' default 68%
##output: the index of left boundary, right boundary, confidence,
#fraction to be shifted to left, fraction to be shifted from the right
##############################################################################
def err_est(count,prob=0.68):
    total=np.sum(count)
    l=0
    fl=0.
    r=len(count)-1
    fr=0.
    ltemp=count[l]
    rtemp=count[r]

    thresh=total*(1.-prob)/2.
    while ltemp<=thresh:
        l+=1
        ltemp+=count[l]
        if ltemp>thresh:
            ltemp-=count[l]
            fl=(thresh-ltemp)/count[l]
            l-=1
            break
    while rtemp<=thresh:
        r-=1
        rtemp+=count[r]
        if rtemp>thresh:
            rtemp-=count[r]
            fr=(thresh-rtemp)/count[r]
            r+=1
            break
    return l,r,(total-2*thresh)/total,fl,1-fr

##############################################################################
##Save the result as histogram as name
## delog - if true de-logs the data. False by default
##############################################################################
def savehist(data,filename,Zs,nsample,i,delog=False,mode='t'):
    p=os.path.abspath('..')
    name='%s_n%d_%s_i%d'%((filename,nsample,Zs,i))
    outfile=p+'\\bins\\%s\\hist\\%s.png'%(filename,name)
    plt.clf()

    ###de-log###
    if delog==True:
        data=np.power(10,np.absolute(data-12))

    data=np.sort(data)
    data=data[np.where(np.isfinite(data)==True)]

    ####kill outliers###
    mean=np.mean(data)
    std=np.std(data)
    data=data[np.where(data>mean-5*std)]
    data=data[np.where(data<mean+5*std)]
    n=data.shape[0]
    if data.shape[0]<=0:
        print name,'is blank' ##if no data
        return "-1, -1"

    try:
        ######find fit and save hist######
        ###find appropriate bin size###
        numbin=getbinsize(data.shape[0],data,mode)

        ###make hist###
        count, bins, ignored = plt.hist(data, numbin, normed=1.0)

        ###find error###
        l,r,t,fl,fr=err_est(count)
        y=np.zeros(len(bins))
        left=bins[l]+(bins[l+1]-bins[l])*fl
        right=bins[r]-(bins[r]-bins[r-1])*fr

        ###plot hist###
        plt.plot(bins,y)
        plt.axvspan(left,right,color='red',alpha=0.4)
        st='n=%d\nconfidence: %f\nleft: %f\nright: %f'%(n,t,left,right)
        plt.annotate(st, xy=(0.70, 0.80), xycoords='axes fraction')
        plt.title(name)
        if delog==True:
            plt.xlabel('O/H')
        else:
            plt.xlabel('12+log(O/H)')
        plt.ylabel('counts')
        plt.savefig(outfile)

        ###print out the confidence interval###
        print name, ':\t%f +- %f'%((left+right)/2.,(right-left)/2.)
        return "%f, %f"%((left+right)/2.,(right-left)/2.)

    except (OverflowError,AttributeError,ValueError):
        print data
        print name, 'had infinities'
        return "-2, -2"

##############################################################################
## The main function. takes the flux and its error as input.
##  filename - a string 'filename' common to the three flux files
##  flux - np array of the fluxes
##  err - the flux errors, must be the same dimension as flux
##  nsample - the number of samples the code will generate. Default is 100
##  errmode - determines which method to choose the bin size.
##      mode 'd' calculates this based on Doane's formula
##      mode 's' calculates this based on sqrt of number of data
##      mode 't' calculates this based on 2*n**1/3 (default)
##############################################################################
def run((filename, flux, err), nsample,binmode='t'):
    p=os.path.abspath('..')
    ###flux and err must be same dimensions
    if flux.shape != err.shape:
        print "flux and err must be of same dimensions"
        return
    nm = flux.shape[1]

    ###retrieve the metallicity keys
    Zs= metallicity.get_keys()

    ###make necessary paths
    if not os.path.exists(p+'\\bins\\%s'%filename):
        os.makedirs(p+'\\bins\\%s'%filename)
        os.makedirs(p+'\\bins\\%s\\hist'%filename)
    binp=p+'\\bins\\%s\\'%filename

    ###Sample 'nsample' points from a gaussian###
    ##a gaussian centered on 0 with std 1
    mu=0
    sigma=1
    sample=np.random.normal(mu,sigma,nsample)

    ###save this sampled gaussians into a png file###
    count, bins, ignored = plt.hist(sample, 40,normed=1)
    plt.plot(bins,gaussian(bins,mu,sigma))
    plt.title("Sampled")
    st="n=%d"%nsample
    plt.annotate(st, xy=(0.70, 0.85), xycoords='axes fraction')
    plt.savefig(binp+filename+'_n%d_sample.png'%nsample)
    plt.clf()

    ###Start calculation###
    ## the flux to be feed to the calculation will be
    ## flux + error*i
    ## where i is the sampled gaussian
    print "Starting iteration"

    #initialize the dictionary
    res={}
    for key in Zs:
        res[key]=[]

    #do the iterations
    for i in range(len(sample)):
        temp=flux+err*sample[i]
        t=metallicity.calculation(temp,nm)
        for key in Zs:
            res[key].append(t[key])

    #make the result a np.array
    for key in Zs:
        res[key]=np.array(res[key])

    print "Iteration Complete"

    ###Bin the results and save the uncertainty###
    for i in range(nm):
        fi=open(binp+'%s_n%d_i%d.csv'%(filename,nsample,i),'w')
        fi.write("%s, Metalicity, Uncertainty\n"%filename)

        for key in Zs:
            s=key+", "+savehist(res[key][:,i],filename,key,nsample,i,binmode)+'\n'
            fi.write(s)
        print "---------------------------------------------"
        fi.close()

    print "uncertainty calculation complete"

##############################################################################
##The input format generator
##############################################################################
def input_format(filename):
    p=os.path.abspath('..')

    if os.path.isfile(p+'\\sn_data\\%s_max.txt'%filename):
        if os.path.isfile(p+'\\sn_data\\%s_min.txt'%filename):
            if os.path.isfile(p+'\\sn_data\\%s_med.txt'%filename):
                return in_mmm(filename)
            else:
                return in_mm(filename)
    print "Unable to find _min and _max files in directory sn_data"
    return -1

def in_mmm(filename):
    p=os.path.abspath('..')
    p+='\\sn_data\\'
    ###Initialize###
    maxfile=p+filename+"_max.txt"
    medfile=p+filename+"_med.txt"
    minfile=p+filename+"_min.txt"

    ###read the max, med, min flux files###
    maxf,nm=readfile(maxfile)
    medf,num=readfile(medfile)
    minf,nn=readfile(minfile)

    ###calculate the flux error as 1/2 [(max-med)+(med-min)]###
    err=0.5*((maxf-medf)+(medf-minf))
    return (filename, medf, err)

def in_mm(filename):
    p=os.path.abspath('..')
    p+='\\sn_data\\'
    ###Initialize###
    maxfile=p+filename+"_max.txt"
    minfile=p+filename+"_min.txt"

    ###read the max, med, min flux files###
    maxf,nm=readfile(maxfile)
    minf,nn=readfile(minfile)
    ###calculate the flux error as 1/2 [(max-min)]###
    err=0.5*(maxf - minf)
    medf= minf+err
    return (filename, medf, err)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('filename', metavar='<filename>', type=str, help="the common filename")
    parser.add_argument('nsample', metavar='N', type=int, help="number of iterations")

    args=parser.parse_args()

    if args.nsample>0:
        fi=input_format(args.filename)
        if fi!=-1:
            run(fi,args.nsample)

    else:
        print "nsample must be positive"

if __name__ == "__main__":
    main()
    #files=['sn2006ss','ptf10eqi-z']
    #filename=files[1]
    #nsample=10000

<|endoftext|>