<commit_before># The MIT License (MIT)

# Copyright (c) 2016 <NAME>
# Modified by <NAME>

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import numpy as np
from scipy.integrate import ode
import matplotlib.pyplot as plt
"""
import matplotlib
font = {'family' : 'normal',
        'size'   : 22}
matplotlib.rc('font', **font)
"""
import pdb
from decimal import Decimal
import collections

class hillmodel(object):
    '''
    This class takes a network file, a parameter sample file, and a Hill
    exponent and builds a Hill function model. The class has two public
    methods:
    1) time,timeseries = hillmodel.simulateHillModel(initialconditions,initialtime,finaltime,timestep)
    2) hillmodel.plotResults(times,timeseries)
    The first method generates a time series for a given set of initial conditions,
    and the second method plots the results. 
    '''
    def __init__(self,networkfile,samplefile,hillexp):
        '''
        Construct the Hill model for a given network and parameter sample.
        '''
        eqnstr,self.varnames = self._parseEqns(networkfile)
        parameternames,samples = self._parseSamples(self.varnames,samplefile)
        self.eqns=self._makeHillEqns(eqnstr,parameternames,samples,hillexp)
        self.d=len(eqnstr)

    def dim(self):
        #Dimension, or total # of genes in network
        return self.d

    def checkForOscillations(self,savein,parameterstring,timeseries):
        """
        This method relies on several assumptions, namely: We only desire oscillations with consistent amplitudes and periods. In other 
        words, all the max in the end behavior of the function are equal, and same with the min.

        For each gene's function, take its end slice, assuming that at this end slice the function would have already settled into the 
        desired behavior. Going from left to right in the end slice, just record each max/min based on whether the area around that point 
        changes its direction of increase or decrease (the basic definition of an extrema point; checking increasing or decreasing is done 
        just by seeing if adjacent points are bigger/smaller). 

        After this is done, it checks if the global max and min are within a degree of error to one another. If they are, that function 
        has probably gone to a fixed point, so conclude the function is not oscillating. Since we assume that we only want one unique 
        max and min in this end slice, if a min does not equal the global min within a degree of error, the behavior of that function
        is not considered a 'desired oscillation'; same with comparing each max with the global max. Later, another add-on to the method
        may be: If periods (distance b/w max/min) do not match, that function may also be ruled out as a 'desired oscillation'.

        So far this new method has been tested on the parameter node '923669' and found all its genes are oscillating. The extrema
        ordering that this method outputs also matches one of the experimental extrema ordering patterns
        """
        output=[]
        output.append(parameterstring)
        time_of_extrema={}
        numOfGenes=0 #records how many genes are oscillating
        for k in range(len(self.varnames)):
          extrema_order_k={}
          slope = ''
          for i in range(999):
            if slope == 'decreasing' and (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])<0:
              extrema_order_k[-1000+i] = timeseries[-1000+i][k]
              slope = 'increasing'
            elif slope == 'increasing' and (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])>0:
              extrema_order_k[-1000+i] = timeseries[-1000+i][k]
              slope = 'decreasing'
            elif (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])>0 and slope == '':
              slope = 'decreasing'
            elif (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])<0 and slope == '':
              slope = 'increasing'
          values=extrema_order_k.values()
          global_max = max(values)
          global_min = min(values)
          if abs(global_max - global_min) > 10**-3: #if True, function didn't go to a fixed point
          	numOfGenes+=1
            for time in extrema_order_k:
                if abs(extrema_order_k[time]-global_max)<10**-3:
                  time_of_extrema[time] = str(k)+' max'
                if abs(extrema_order_k[time]-global_min)<10**-3:
                  time_of_extrema[time] = str(k)+' min'
        if numOfGenes == self.dim():      #Checks if all genes oscillated
          ordered_extrema = collections.OrderedDict(sorted(time_of_extrema.items()))
          for time in ordered_extrema:
            if ordered_extrema[time] not in output:
              output.append(ordered_extrema[time])
          for j in range(len(output)): #replace index number, used in timeseries, with varname
            extrema = output[j]<commit_msg>improved checking if all genes oscillating<commit_after># The MIT License (MIT)

# Copyright (c) 2016 <NAME>
# Modified by <NAME>

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import numpy as np
from scipy.integrate import ode
import matplotlib.pyplot as plt
"""
import matplotlib
font = {'family' : 'normal',
        'size'   : 22}
matplotlib.rc('font', **font)
"""
import pdb
from decimal import Decimal
import collections

class hillmodel(object):
    '''
    This class takes a network file, a parameter sample file, and a Hill
    exponent and builds a Hill function model. The class has two public
    methods:
    1) time,timeseries = hillmodel.simulateHillModel(initialconditions,initialtime,finaltime,timestep)
    2) hillmodel.plotResults(times,timeseries)
    The first method generates a time series for a given set of initial conditions,
    and the second method plots the results. 
    '''
    def __init__(self,networkfile,samplefile,hillexp):
        '''
        Construct the Hill model for a given network and parameter sample.
        '''
        eqnstr,self.varnames = self._parseEqns(networkfile)
        parameternames,samples = self._parseSamples(self.varnames,samplefile)
        self.eqns=self._makeHillEqns(eqnstr,parameternames,samples,hillexp)
        self.d=len(eqnstr)

    def dim(self):
        #Dimension, or total # of genes in network
        return self.d

    def checkForOscillations(self,savein,parameterstring,timeseries):
        """
        This method relies on several assumptions, namely: We only desire oscillations with consistent amplitudes and periods. In other 
        words, all the max in the end behavior of the function are equal, and same with the min.

        For each gene's function, take its end slice, assuming that at this end slice the function would have already settled into the 
        desired behavior. Going from left to right in the end slice, just record each max/min based on whether the area around that point 
        changes its direction of increase or decrease (the basic definition of an extrema point; checking increasing or decreasing is done 
        just by seeing if adjacent points are bigger/smaller). 

        After this is done, it checks if the global max and min are within a degree of error to one another. If they are, that function 
        has probably gone to a fixed point, so conclude the function is not oscillating. Since we assume that we only want one unique 
        max and min in this end slice, if a min does not equal the global min within a degree of error, the behavior of that function
        is not considered a 'desired oscillation'; same with comparing each max with the global max. Later, another add-on to the method
        may be: If periods (distance b/w max/min) do not match, that function may also be ruled out as a 'desired oscillation'.

        So far this new method has been tested on the parameter node '923669' and found all its genes are oscillating. The extrema
        ordering that this method outputs also matches one of the experimental extrema ordering patterns
        """
        output=[]
        output.append(parameterstring)
        time_of_extrema={}
        numOfGenes=0 #records how many genes are oscillating
        for k in range(len(self.varnames)):
          extrema_order_k={}
          slope = ''
          for i in range(999):
            if slope == 'decreasing' and (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])<0:
              extrema_order_k[-1000+i] = timeseries[-1000+i][k]
              slope = 'increasing'
            elif slope == 'increasing' and (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])>0:
              extrema_order_k[-1000+i] = timeseries[-1000+i][k]
              slope = 'decreasing'
            elif (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])>0 and slope == '':
              slope = 'decreasing'
            elif (timeseries[-1000+i][k] - timeseries[-1000+i+1][k])<0 and slope == '':
              slope = 'increasing'
          values=extrema_order_k.values()
          global_max = max(values)
          global_min = min(values)
          if abs(global_max - global_min) > 10**-3: #if True, function didn't go to a fixed point
            numOfGenes+=1
            for time in extrema_order_k:
                if abs(extrema_order_k[time]-global_max)<10**-3:
                  time_of_extrema[time] = str(k)+' max'
                if abs(extrema_order_k[time]-global_min)<10**-3:
                  time_of_extrema[time] = str(k)+' min'
        if numOfGenes == self.dim():      #Checks if all genes oscillated
          ordered_extrema = collections.OrderedDict(sorted(time_of_extrema.items()))
          for time in ordered_extrema:
            if ordered_extrema[time] not in output:
              output.append(ordered_extrema[time])
          for j in range(len(output)): #replace index number, used in timeseries, with varname
            extrema = output[j]
{'fraction_non_alphanumeric': 0.07752978687699279, 'fraction_numerical': 0.01409632488672596, 'mean_word_length': 3.0280500168976006, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4025690', 'n_tokens_mistral': 3377, 'n_tokens_neox': 3154, 'n_words': 1348}