text:
#!/usr/bin/env python

# lse.py
# Copyright (c) 2020. All rights reserved.

from typing import Sequence, TypeVar, Union, Dict
import os
import sys
import numpy as np
import networkx

from scipy.stats import norm
from scipy.stats import rankdata
from sklearn.decomposition import TruncatedSVD

from d3m.primitive_interfaces.transformer import TransformerPrimitiveBase
from d3m import utils, container
from d3m.metadata import hyperparams, base as metadata_module, params
from d3m.primitive_interfaces import base
from d3m.primitive_interfaces.base import CallResult

from graspy.embed import LaplacianSpectralEmbed as graspyLSE
from graspy.embed import OmnibusEmbed as graspyOMNI
from graspy.utils import pass_to_ranks as graspyPTR

Inputs = container.List
Outputs = container.List

class Params(params.Params):
    pass

class Hyperparams(hyperparams.Hyperparams):
    max_dimension = hyperparams.Hyperparameter[int](
        default=2,
        semantic_types=[
            'https://metadata.datadrivendiscovery.org/types/TuningParameter'
        ])

    which_elbow = hyperparams.Hyperparameter[int](
        default=1,
        semantic_types=[
            'https://metadata.datadrivendiscovery.org/types/TuningParameter'
        ])

    use_attributes = hyperparams.Hyperparameter[bool](
        default = False,
        semantic_types = [
            'https://metadata.datadrivendiscovery.org/types/TuningParameter'
        ])

class LaplacianSpectralEmbedding(TransformerPrimitiveBase[Inputs, Outputs, Hyperparams]):
    """
    Spectral-based trasformation of the Laplacian.
    """
    # This should contain only metadata which cannot be automatically determined from the code.
    metadata = metadata_module.PrimitiveMetadata({
        # Simply an UUID generated once and fixed forever. Generated using "uuid.uuid4()".
        'id': '8fa6178b-84f7-37d8-87e8-4d3a44c86569',
        'version': "0.1.0",
        'name': "jhu.lse",
        # The same path the primitive is registered with entry points in setup.py.
        'python_path': 'd3m.primitives.data_transformation.laplacian_spectral_embedding.JHU',
        # Keywords do not have a controlled vocabulary. Authors can put here whatever they find suitable.
        'keywords': ['laplacian embedding'],
        'source': {
            'name': "JHU",
            'uris': [
                # Unstructured URIs. Link to file and link to repo in this case.
                'https://github.com/neurodata/primitives-interfaces/blob/master/jhu_primitives/lse/lse.py',
#                'https://github.com/youngser/primitives-interfaces/blob/jp-devM1/jhu_primitives/ase/ase.py',
                'https://github.com/neurodata/primitives-interfaces.git',
            ],
            'contact': 'mailto:hhelm2@jhu.edu'
        },
        'description': 'Spectral-based trasformation of the Laplacian',
        'hyperparams_configuration': {
            'max_dimension': 'The maximum dimension that can be used for eigendecomposition',
            'which_elbow': 'The scree plot "elbow" to use for dimensionality reduction. High values leads to more dimensions selected.',
            'use_attributes': 'Boolean which indicates whether to use the attributes of the nodes.'
        },
        # A list of dependencies in order. These can be Python packages, system packages, or Docker images.
        # Of course Python packages can also have their own dependencies, but sometimes it is necessary to
        # install a Python package first to be even able to run setup.py of another package. Or you have
        # a dependency which is not on PyPi.
        'installation': [
            {
                'type': 'UBUNTU',
                'package': 'libxml2-dev',
                'version': '2.9.4'
            },
            {
                'type': 'UBUNTU',
                'package': 'libpcre3-dev',
                'version': '2.9.4'
            },{
            'type': metadata_module.PrimitiveInstallationType.PIP,
            'package_uri': 'git+https://github.com/neurodata/primitives-interfaces.git@{git_commit}#egg=jhu_primitives'.format(
                git_commit=utils.current_git_commit(os.path.dirname(__file__)),
                ),
        }],
        # URIs at which one can obtain code for the primitive, if available.
        # 'location_uris': [
        #     'https://gitlab.com/datadrivendiscovery/tests-data/raw/{git_commit}/primitives/test_primitives/monomial.py'.format(
        #         git_commit=utils.current_git_commit(os.path.dirname(__file__)),
        #     ),
        # ],
        # Choose these from a controlled vocabulary in the schema. If anything is missing which would
        # best describe the primitive, make a merge request.
        'algorithm_types': [
            "HIGHER_ORDER_SINGULAR_VALUE_DECOMPOSITION"
        ],
        'primitive_family': "DATA_TRANSFORMATION"
    })

    def __init__(self, *, hyperparams: Hyperparams, random_seed: int = 0,
                 docker_containers: Dict[str, base.DockerContainer] = None) -> None:
        super().__init__(hyperparams=hyperparams,
                         random_seed=random_seed,
                         docker_containers=docker_containers)

    def produce(self, *, inputs: Inputs,
                timeout: float = None,
                iterations: int = None) -> CallResult[Outputs]:
        # print('lse produce started', file=sys.stderr)
        # np.random.seed(self.random_seed)

        # unpacks necessary input arguments
        # note that inputs 2 and on are passed through untouched !
        learning_data = inputs[0]
        graphs_all = inputs[1]

        # lse only works for one graph (but we can change that)
        G = graphs_all[0].copy()

        # applies pass to ranks - rescales edge weights based on their relative ranks
        g = graspyPTR(G)

        n = g.shape[0]

        max_dimension = self.hyperparams['max_dimension']

        if max_dimension > n:
            max_dimension = n

        n_elbows = self.hyperparams['which_elbow']

        """
        What does Omni(DAD) even look like?

        if self.hyperparams['use_attributes']:
            adj = [g]
            MORE_ATTR = True
            attr_number = 1

            while MORE_ATTR:
                attr = 'attr'
                temp_attr = np.array(list(networkx.get_node_attributes(G, 'attr' + str(attr_number)).values()))
                if len(temp_attr) == 0:
                    MORE_ATTR = False
                else:
                    K = np.sum((temp_attr[:, np.newaxis][:, np.newaxis, :] - temp_attr[:, np.newaxis][np.newaxis, :, :])**2, axis = -1)
                    adj.append(graspyPTR(K))
                    attr_number += 1
            M = len(adj)
            if M > 1:
                g = self._omni(adj)
                lse_object = graspyLSE(n_components = max_dimension, n_elbows=n_elbows)
                X_hats = lse_object.fit_transform(g)

                d = X_hats.shape[1]

                X_hats_reshaped = X_hats.reshape((M, n, d))
                X_hat = np.mean(X_hats_reshaped, axis = 0)

                embedding = X_hat.copy()

                inputs[0] = container.ndarray(embedding)

                return base.CallResult(inputs)
        """

        lse_object = graspyLSE(n_components = max_dimension, n_elbows=n_elbows)
        X_hat = lse_object.fit_transform(g)

        inputs[1][0] = container.ndarray(X_hat)

        # print("lse produce ended (omni not used)", file=sys.stderr)

        return base.CallResult(inputs)

reason: import numpy,from scipy,import networkx


text:
import sys

sys.path.append("../")

import time as time

import numpy as np
from stable_baselines3 import PPO
from stable_baselines3.ppo.policies import MlpPolicy

from Hack import load, rl

def objective(num_episodes=100):
    """
    Function to take in hyperparameters, train a reinforcement model, and output the "profit" of the model as a metric
    """
    epex = load.epex().load()
    price_array = epex["apx_da_hourly"].values

    start_idx = 0
    end_idx = 4 * 2 * 24 * 7  # start_of_2020 # 2019->2020 # 2*24*7
    obs_price_array = price_array[start_idx:end_idx]

    power = 0.5
    env = rl.energy_price_env(obs_price_array, window_size=24 * 2, power=power)
    model = PPO(MlpPolicy, env, verbose=0)
    model.learn(100)
    val_list = []

    for i in range(num_episodes):
        val = rl.quick_eval(i, model)
        val_list.append(val)

    return np.mean(val_list)

if __name__ == "__main__":
    time_start = time.time()
    a = objective(num_episodes=150)
    time_stop = time.time()
    print(a)
    print("time = ", time_stop - time_start)

ext: py

max_stars_repo_name: rlaker/Hackathon

max_issues_repo_name: rlaker/Hackathon

max_forks_repo_name: rlaker/Hackathon

reason: import numpy


text:
from __future__ import absolute_import
from .stringdata import read_stringdata, StringData
from ._examples import examplestringdata, get_examplestringdata
from . import stringcomparison
from . import stringsetcomparison
from . import plotting
from . import htmltables

from numpy.testing import Tester
test = Tester().test
bench = Tester().bench

from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions

max_stars_repo_name: gjlbeckers-uu/aglcheck

max_issues_repo_name: gjlbeckers-uu/aglcheck

max_forks_repo_name: gjlbeckers-uu/aglcheck

reason: from numpy


text:
from django.core.checks import messages
from django.http.response import HttpResponse
from django.shortcuts import render,redirect
from django.http import HttpResponse
from django.contrib.auth.models import User,auth
from django.contrib import messages
from .models import AD_User
import pandas as pd
# Create your views here.
from django.db.models import Q
import numpy as np
import json
from django.template.defaultfilters import register
from pathlib import Path
import os
# Create your views here.
def login(request):

    if request.method == "POST":
        username = request.POST['username']
        password = request.POST['pass']

        if AD_User.objects.filter(username=username,password=password).exists():

            messages.info(request,'Granted')

            request.session['username'] = username # set 'token' in the session
            request.session['password'] = password

            return redirect("terms")
        else:
            messages.info(request, 'Invalid Credentials')
            return redirect('login')

    else:
        return render(request,'login.html')

max_stars_repo_name: Vishesh-Conbi/Chatbot

max_issues_repo_name: Vishesh-Conbi/Chatbot

max_forks_repo_name: Vishesh-Conbi/Chatbot


text:
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import pandas as pd
import sys
from pyfaidx import Faidx
from clonesig.data_loader import PAT_LIST, DataWriter
import pathlib
from scipy.stats import beta
import numpy as np

tumor = sys.argv[1]
seq_depth = sys.argv[2]

"""
tumor = "T2"
seq_depth = "8X"
#sed 's/^\#\#/\&/g' data/salcedo_dream_challenge/MuTect_inputs/mutect_filtered_T2.T.16XnoXY.vcf >  data/salcedo_dream_challenge/MuTect_inputs/mutect_filtered_T2.T.16XnoXY_clean.vcf
"""

np.random.seed(int(seq_depth[:-1])*int(tumor[1]))
def get_context(x):
    match_dict = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A'}
    if x['REF'] in ('C', 'T'):
        context = x['triplet'][0] + '[' + x['REF'] + '>' + x['ALT'] + ']' + \
            x['triplet'][2]
    else:
        context = match_dict[x['triplet'][2]] + '[' + match_dict[x['REF']] +\
            '>' + match_dict[x['ALT']] + ']' + match_dict[x['triplet'][0]]
    return context

vcf_filename = 'data/salcedo_dream_challenge/MuTect_inputs/mutect_filtered_{}.T.{}noXY_clean.vcf'.format(tumor, seq_depth)
cnv_filename = 'data/salcedo_dream_challenge/MuTect_inputs/{}-{}_refit_subclones_noXY.txt'.format(tumor, seq_depth)
purity_filename = 'data/salcedo_dream_challenge/MuTect_inputs/{}-{}_refit_cellularity_ploidy.txt'.format(tumor, seq_depth)
ref_fasta = 'external_data/hs37d5.fa'
fa = Faidx(ref_fasta)
# downloaded from ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/technical/reference/phase2_reference_assembly_sequence

vcf_data = pd.read_csv(vcf_filename, sep='\t', comment='&')

vcf_data = vcf_data.assign(chromosome=vcf_data['#CHROM'].astype(int))
vcf_data = vcf_data.assign(position=vcf_data['POS'].astype(int))
vcf_data = vcf_data.assign(mutation_id=vcf_data.chromosome.astype(str) + '_' +
                           vcf_data.position.astype(str) + '_' +
                           vcf_data.REF + vcf_data.ALT)
vcf_data = vcf_data.assign(ref_counts=vcf_data.tumor.str.split(':').str[1].
                           str.split(',').str[0].astype(int))
vcf_data = vcf_data.assign(var_counts=vcf_data.tumor.str.split(':').str[1].
                           str.split(',').str[1].astype(int))
vcf_data = vcf_data.assign(triplet=vcf_data.apply(
    lambda x: fa.fetch(str(x.chromosome), x.position-1, x.position+1).seq,
    axis=1))
vcf_data = vcf_data.assign(pattern=pd.Categorical(
            vcf_data.apply(get_context, axis=1),
            categories=PAT_LIST, ordered=True))
vcf_data = vcf_data.assign(
        trinucleotide=pd.Categorical(
            vcf_data.apply(lambda x: PAT_LIST.index(x['pattern']),
                                     axis=1),
            categories=list(range(len(PAT_LIST))), ordered=True))
foldername = 'salcedo_dream_challenge/{}_{}'.format(tumor, seq_depth)
pathlib.Path(foldername).mkdir(parents=True, exist_ok=True)
vcf_data.to_csv(
    '{}/unrestricted_input_mut.csv'.format(foldername), sep='\t')
cnv_table = pd.read_csv(cnv_filename, sep='\t')

def get_major_minor(x):
    if x.frac1_A==1:
        return pd.Series([x.nMaj1_A, x.nMin1_A])
    else:
        if x.frac1_A > x.frac2_A:
            return pd.Series([x.nMaj1_A, x.nMin1_A])
        else:
            return pd.Series([x.nMaj2_A, x.nMin2_A])

new_data = cnv_table.apply(get_major_minor, axis=1)
new_data.columns = ['major_cn', 'minor_cn']
cnv_final = pd.concat((cnv_table[['chr', 'startpos', 'endpos']],
                       new_data.astype(int)), axis=1)

vcf_data_cnv = pd.merge(vcf_data, cnv_final, left_on='chromosome',
                        right_on='chr', how='left')
vcf_data_cnv_filter = vcf_data_cnv[(vcf_data_cnv.position>=vcf_data_cnv.startpos)&(vcf_data_cnv.position<=vcf_data_cnv.endpos)]
vcf_data_cnv_filter = vcf_data_cnv_filter.assign(normal_cn=2)

vcf_data_cnv_filter = vcf_data_cnv_filter[vcf_data_cnv_filter.major_cn>0]
purity_data = pd.read_csv(purity_filename, sep='\t')
purity = purity_data.cellularity.values[0]

data = DataWriter()
data.data = vcf_data_cnv_filter.copy()
data.cn_profile = cnv_final.copy()
data.purity = purity

foldername = 'salcedo_dream_challenge/{}_{}'.format(tumor, seq_depth)
pathlib.Path(foldername).mkdir(parents=True, exist_ok=True)
data.write_clonesig(foldername)
data.data = data.data.assign(total_cn=data.data.major_cn + data.data.minor_cn)
data.write_pyclone_sciclone_ccube(foldername)
data.write_deconstructsig(foldername)
data.data = data.data.assign(mut_cn=1)
data.write_tracksig(foldername)
data.write_tracksigfreq(foldername)
data.cn_profile = data.cn_profile.assign(chromosome=data.cn_profile.chr,
                                         start=data.cn_profile.startpos,
                                         end=data.cn_profile.endpos,
                                         minor=data.cn_profile.minor_cn,
                                         major=data.cn_profile.major_cn)
data.write_palimpsest(foldername) # need column chromosome in cn data
data.write_dpclust(foldername)
data.write_phylogicndt(foldername) # mut_cn

reason: import numpy,from scipy


text:
import numpy as np
from .Unwrapping.Arevallilo2002 import Arevallilo2002
from .Smooth.DownSample import DownSample
from .Smooth.FFTSmooth import FFTSmooth
from .Smooth.UniformFilter import UniformFilter
from .PlotMatrix3D import PlotMatrix3D
import matplotlib.pyplot as plt

class MatrixUnwrap(object):
	def __init__(self,C):
		self.C0 = C
		self.P0 = np.angle(C)
		self.A0 = np.abs(C)

		self.P1 = None
		self.P2 = None
		self.dP = None
		self.Pu = None

	def Unwrap(self,DS=None,FFT=None,UF=None):

		#create a copy of the complex array
		C = np.copy(self.C0)

		#down sample
		if not DS is None:
			C,I,J = DownSample(C,DS)
			self.I = I
			self.J = J

		#FFT filter
		if not FFT is None:
			C = FFTSmooth(C,FFT)

		#Uniform filter
		if not UF is None:
			C = UniformFilter(C,UF)

		#extract phase before unwrapping
		self.P1 = np.angle(C)

		#unwrap
		self.P2 = Arevallilo2002(self.P1)

		#calculate change in phase
		self.dP = self.P2 - self.P1

		#if we down sampled then we need to adjust the original array
		if DS is None:
			self.Pu = self.P2
		else:
			dP = self.P2 - self.P1
			self.Pt = self.P1[I,J] + dP[I,J]
			self.Put = self.P0 + dP[I,J]
			dPt = 2*np.pi*np.round((self.Put - self.Pt)/(2*np.pi))
			self.Pu = self.Put - dPt

	def Plot(self):

		fig = plt
		fig.figure(figsize=(11,8))

		ax0 = PlotMatrix3D(self.A0,fig,[2,2,0,0],title='Amplitude')
		ax1 = PlotMatrix3D(self.P0,fig,[2,2,1,0],title='Wrapped Phase')
		ax2 = PlotMatrix3D(self.P2,fig,[2,2,0,1],title='Unwrapped Phase')
		ax3 = PlotMatrix3D(self.Pu,fig,[2,2,1,1],title='Unwrapped Phase')


text:
"""Integration method that emulates by-hand techniques.

This module also provides functionality to get the steps used to evaluate a
particular integral, in the ``integral_steps`` function. This will return
nested namedtuples representing the integration rules used. The
``manualintegrate`` function computes the integral using those steps given
an integrand; given the steps, ``_manualintegrate`` will evaluate them.

The integrator can be extended with new heuristics and evaluation
techniques. To do so, write a function that accepts an ``IntegralInfo``
object and returns either a namedtuple representing a rule or
``None``. Then, write another function that accepts the namedtuple's fields
and returns the antiderivative, and decorate it with
``@evaluates(namedtuple_type)``.  If the new technique requires a new
match, add the key and call to the antiderivative function to integral_steps.
To enable simple substitutions, add the match to find_substitutions.

"""

from typing import Dict as tDict, Optional

from collections import namedtuple, defaultdict

import sympy

from sympy.core.compatibility import reduce, Mapping, iterable
from sympy.core.containers import Dict
from sympy.core.expr import Expr
from sympy.core.logic import fuzzy_not
from sympy.functions.elementary.trigonometric import TrigonometricFunction
from sympy.functions.special.polynomials import OrthogonalPolynomial
from sympy.functions.elementary.piecewise import Piecewise
from sympy.strategies.core import switch, do_one, null_safe, condition
from sympy.core.relational import Eq, Ne
from sympy.polys.polytools import degree
from sympy.ntheory.factor_ import divisors
from sympy.utilities.misc import debug

ZERO = sympy.S.Zero

def Rule(name, props=""):
    # GOTCHA: namedtuple class name not considered!
    def __eq__(self, other):
        return self.__class__ == other.__class__ and tuple.__eq__(self, other)
    __neq__ = lambda self, other: not __eq__(self, other)
    cls = namedtuple(name, props + " context symbol")
    cls.__eq__ = __eq__
    cls.__ne__ = __neq__
    return cls

ConstantRule = Rule("ConstantRule", "constant")
ConstantTimesRule = Rule("ConstantTimesRule", "constant other substep")
PowerRule = Rule("PowerRule", "base exp")
AddRule = Rule("AddRule", "substeps")
URule = Rule("URule", "u_var u_func constant substep")
PartsRule = Rule("PartsRule", "u dv v_step second_step")
CyclicPartsRule = Rule("CyclicPartsRule", "parts_rules coefficient")
TrigRule = Rule("TrigRule", "func arg")
ExpRule = Rule("ExpRule", "base exp")
ReciprocalRule = Rule("ReciprocalRule", "func")
ArcsinRule = Rule("ArcsinRule")
InverseHyperbolicRule = Rule("InverseHyperbolicRule", "func")
AlternativeRule = Rule("AlternativeRule", "alternatives")
DontKnowRule = Rule("DontKnowRule")
DerivativeRule = Rule("DerivativeRule")
RewriteRule = Rule("RewriteRule", "rewritten substep")
PiecewiseRule = Rule("PiecewiseRule", "subfunctions")
HeavisideRule = Rule("HeavisideRule", "harg ibnd substep")
TrigSubstitutionRule = Rule("TrigSubstitutionRule",
                            "theta func rewritten substep restriction")
ArctanRule = Rule("ArctanRule", "a b c")
ArccothRule = Rule("ArccothRule", "a b c")
ArctanhRule = Rule("ArctanhRule", "a b c")
JacobiRule = Rule("JacobiRule", "n a b")
GegenbauerRule = Rule("GegenbauerRule", "n a")
ChebyshevTRule = Rule("ChebyshevTRule", "n")
ChebyshevURule = Rule("ChebyshevURule", "n")
LegendreRule = Rule("LegendreRule", "n")
HermiteRule = Rule("HermiteRule", "n")
LaguerreRule = Rule("LaguerreRule", "n")
AssocLaguerreRule = Rule("AssocLaguerreRule", "n a")
CiRule = Rule("CiRule", "a b")
ChiRule = Rule("ChiRule", "a b")
EiRule = Rule("EiRule", "a b")
SiRule = Rule("SiRule", "a b")
ShiRule = Rule("ShiRule", "a b")
ErfRule = Rule("ErfRule", "a b c")
FresnelCRule = Rule("FresnelCRule", "a b c")
FresnelSRule = Rule("FresnelSRule", "a b c")
LiRule = Rule("LiRule", "a b")
PolylogRule = Rule("PolylogRule", "a b")
UpperGammaRule = Rule("UpperGammaRule", "a e")
EllipticFRule = Rule("EllipticFRule", "a d")
EllipticERule = Rule("EllipticERule", "a d")

IntegralInfo = namedtuple('IntegralInfo', 'integrand symbol')

evaluators = {}
def evaluates(rule):
    def _evaluates(func):
        func.rule = rule
        evaluators[rule] = func
        return func
    return _evaluates

def contains_dont_know(rule):
    if isinstance(rule, DontKnowRule):
        return True
    else:
        for val in rule:
            if isinstance(val, tuple):
                if contains_dont_know(val):
                    return True
            elif isinstance(val, list):
                if any(contains_dont_know(i) for i in val):
                    return True
    return False

def manual_diff(f, symbol):
    """Derivative of f in form expected by find_substitutions

    SymPy's derivatives for some trig functions (like cot) aren't in a form
    that works well with finding substitutions; this replaces the
    derivatives for those particular forms with something that works better.

    """
    if f.args:
        arg = f.args[0]
        if isinstance(f, sympy.tan):
            return arg.diff(symbol) * sympy.sec(arg)**2
        elif isinstance(f, sympy.cot):
            return -arg.diff(symbol) * sympy.csc(arg)**2
        elif isinstance(f, sympy.sec):
            return arg.diff(symbol) * sympy.sec(arg) * sympy.tan(arg)
        elif isinstance(f, sympy.csc):
            return -arg.diff(symbol) * sympy.csc(arg) * sympy.cot(arg)
        elif isinstance(f, sympy.Add):
            return sum([manual_diff(arg, symbol) for arg in f.args])
        elif isinstance(f, sympy.Mul):
            if len(f.args) == 2 and isinstance(f.args[0], sympy.Number):
                return f.args[0] * manual_diff(f.args[1], symbol)
    return f.diff(symbol)

def manual_subs(expr, *args):
    """
    A wrapper for `expr.subs(*args)` with additional logic for substitution
    of invertible functions.
    """
    if len(args) == 1:
        sequence = args[0]
        if isinstance(sequence, (Dict, Mapping)):
            sequence = sequence.items()
        elif not iterable(sequence):
            raise ValueError("Expected an iterable of (old, new) pairs")
    elif len(args) == 2:
        sequence = [args]
    else:
        raise ValueError("subs accepts either 1 or 2 arguments")

    new_subs = []
    for old, new in sequence:
        if isinstance(old, sympy.log):
            # If log(x) = y, then exp(a*log(x)) = exp(a*y)
            # that is, x**a = exp(a*y). Replace nontrivial powers of x
            # before subs turns them into `exp(y)**a`, but
            # do not replace x itself yet, to avoid `log(exp(y))`.
            x0 = old.args[0]
            expr = expr.replace(lambda x: x.is_Pow and x.base == x0,
                lambda x: sympy.exp(x.exp*new))
            new_subs.append((x0, sympy.exp(new)))

    return expr.subs(list(sequence) + new_subs)

# Method based on that on SIN, described in "Symbolic Integration: The
# Stormy Decade"

def find_substitutions(integrand, symbol, u_var):
    results = []

    def test_subterm(u, u_diff):
        if u_diff == 0:
            return False
        substituted = integrand / u_diff
        if symbol not in substituted.free_symbols:
            # replaced everything already
            return False
        debug("substituted: {}, u: {}, u_var: {}".format(substituted, u, u_var))
        substituted = manual_subs(substituted, u, u_var).cancel()

        if symbol not in substituted.free_symbols:
            # avoid increasing the degree of a rational function
            if integrand.is_rational_function(symbol) and substituted.is_rational_function(u_var):
                deg_before = max([degree(t, symbol) for t in integrand.as_numer_denom()])
                deg_after = max([degree(t, u_var) for t in substituted.as_numer_denom()])
                if deg_after > deg_before:
                    return False
            return substituted.as_independent(u_var, as_Add=False)

        # special treatment for substitutions u = (a*x+b)**(1/n)
        if (isinstance(u, sympy.Pow) and (1/u.exp).is_Integer and
            sympy.Abs(u.exp) < 1):
                a = sympy.Wild('a', exclude=[symbol])
                b = sympy.Wild('b', exclude=[symbol])
                match = u.base.match(a*symbol + b)
                if match:
                    a, b = [match.get(i, ZERO) for i in (a, b)]
                    if a != 0 and b != 0:
                        substituted = substituted.subs(symbol,
                            (u_var**(1/u.exp) - b)/a)
                        return substituted.as_independent(u_var, as_Add=False)

        return False

    def possible_subterms(term):
        if isinstance(term, (TrigonometricFunction,
                             sympy.asin, sympy.acos, sympy.atan,
                             sympy.exp, sympy.log, sympy.Heaviside)):
            return [term.args[0]]
        elif isinstance(term, (sympy.chebyshevt, sympy.chebyshevu,
                        sympy.legendre, sympy.hermite, sympy.laguerre)):
            return [term.args[1]]
        elif isinstance(term, (sympy.gegenbauer, sympy.assoc_laguerre)):
            return [term.args[2]]
        elif isinstance(term, sympy.jacobi):
            return [term.args[3]]
        elif isinstance(term, sympy.Mul):
            r = []
            for u in term.args:
                r.append(u)
                r.extend(possible_subterms(u))
            return r
        elif isinstance(term, sympy.Pow):
            r = []
            if term.args[1].is_constant(symbol):
                r.append(term.args[0])
            elif term.args[0].is_constant(symbol):
                r.append(term.args[1])
            if term.args[1].is_Integer:
                r.extend([term.args[0]**d for d in divisors(term.args[1])
                    if 1 < d < abs(term.args[1])])
                if term.args[0].is_Add:
                    r.extend([t for t in possible_subterms(term.args[0])
                        if t.is_Pow])
            return r
        elif isinstance(term, sympy.Add):
            r = []
            for arg in term.args:
                r.append(arg)
                r.extend(possible_subterms(arg))
            return r
        return []

    for u in possible_subterms(integrand):
        if u == symbol:
            continue
        u_diff = manual_diff(u, symbol)
        new_integrand = test_subterm(u, u_diff)
        if new_integrand is not False:
            constant, new_integrand = new_integrand
            if new_integrand == integrand.subs(symbol, u_var):
                continue
            substitution = (u, constant, new_integrand)
            if substitution not in results:
                results.append(substitution)

    return results

def rewriter(condition, rewrite):
    """Strategy that rewrites an integrand."""
    def _rewriter(integral):
        integrand, symbol = integral
        debug("Integral: {} is rewritten with {} on symbol: {}".format(integrand, rewrite, symbol))
        if condition(*integral):
            rewritten = rewrite(*integral)
            if rewritten != integrand:
                substep = integral_steps(rewritten, symbol)
                if not isinstance(substep, DontKnowRule) and substep:
                    return RewriteRule(
                        rewritten,
                        substep,
                        integrand, symbol)
    return _rewriter

def proxy_rewriter(condition, rewrite):
    """Strategy that rewrites an integrand based on some other criteria."""
    def _proxy_rewriter(criteria):
        criteria, integral = criteria
        integrand, symbol = integral
        debug("Integral: {} is rewritten with {} on symbol: {} and criteria: {}".format(integrand, rewrite, symbol, criteria))
        args = criteria + list(integral)
        if condition(*args):
            rewritten = rewrite(*args)
            if rewritten != integrand:
                return RewriteRule(
                    rewritten,
                    integral_steps(rewritten, symbol),
                    integrand, symbol)
    return _proxy_rewriter

def multiplexer(conditions):
    """Apply the rule that matches the condition, else None"""
    def multiplexer_rl(expr):
        for key, rule in conditions.items():
            if key(expr):
                return rule(expr)
    return multiplexer_rl

def alternatives(*rules):
    """Strategy that makes an AlternativeRule out of multiple possible results."""
    def _alternatives(integral):
        alts = []
        count = 0
        debug("List of Alternative Rules")
        for rule in rules:
            count = count + 1
            debug("Rule {}: {}".format(count, rule))

            result = rule(integral)
            if (result and not isinstance(result, DontKnowRule) and
                result != integral and result not in alts):
                alts.append(result)
        if len(alts) == 1:
            return alts[0]
        elif alts:
            doable = [rule for rule in alts if not contains_dont_know(rule)]
            if doable:
                return AlternativeRule(doable, *integral)
            else:
                return AlternativeRule(alts, *integral)
    return _alternatives

def constant_rule(integral):
    integrand, symbol = integral
    return ConstantRule(integral.integrand, *integral)

def power_rule(integral):
    integrand, symbol = integral
    base, exp = integrand.as_base_exp()

    if symbol not in exp.free_symbols and isinstance(base, sympy.Symbol):
        if sympy.simplify(exp + 1) == 0:
            return ReciprocalRule(base, integrand, symbol)
        return PowerRule(base, exp, integrand, symbol)
    elif symbol not in base.free_symbols and isinstance(exp, sympy.Symbol):
        rule = ExpRule(base, exp, integrand, symbol)

        if fuzzy_not(sympy.log(base).is_zero):
            return rule
        elif sympy.log(base).is_zero:
            return ConstantRule(1, 1, symbol)

        return PiecewiseRule([
            (rule, sympy.Ne(sympy.log(base), 0)),
            (ConstantRule(1, 1, symbol), True)
        ], integrand, symbol)

def exp_rule(integral):
    integrand, symbol = integral
    if isinstance(integrand.args[0], sympy.Symbol):
        return ExpRule(sympy.E, integrand.args[0], integrand, symbol)

def orthogonal_poly_rule(integral):
    orthogonal_poly_classes = {
        sympy.jacobi: JacobiRule,
        sympy.gegenbauer: GegenbauerRule,
        sympy.chebyshevt: ChebyshevTRule,
        sympy.chebyshevu: ChebyshevURule,
        sympy.legendre: LegendreRule,
        sympy.hermite: HermiteRule,
        sympy.laguerre: LaguerreRule,
        sympy.assoc_laguerre: AssocLaguerreRule
        }
    orthogonal_poly_var_index = {
        sympy.jacobi: 3,
        sympy.gegenbauer: 2,
        sympy.assoc_laguerre: 2
        }
    integrand, symbol = integral
    for klass in orthogonal_poly_classes:
        if isinstance(integrand, klass):
            var_index = orthogonal_poly_var_index.get(klass, 1)
            if (integrand.args[var_index] is symbol and not
                any(v.has(symbol) for v in integrand.args[:var_index])):
                    args = integrand.args[:var_index] + (integrand, symbol)
                    return orthogonal_poly_classes[klass](*args)

def special_function_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[symbol], properties=[lambda x: not x.is_zero])
    b = sympy.Wild('b', exclude=[symbol])
    c = sympy.Wild('c', exclude=[symbol])
    d = sympy.Wild('d', exclude=[symbol], properties=[lambda x: not x.is_zero])
    e = sympy.Wild('e', exclude=[symbol], properties=[
        lambda x: not (x.is_nonnegative and x.is_integer)])
    wilds = (a, b, c, d, e)
    # patterns consist of a SymPy class, a wildcard expr, an optional
    # condition coded as a lambda (when Wild properties are not enough),
    # followed by an applicable rule
    patterns = (
        (sympy.Mul, sympy.exp(a*symbol + b)/symbol, None, EiRule),
        (sympy.Mul, sympy.cos(a*symbol + b)/symbol, None, CiRule),
        (sympy.Mul, sympy.cosh(a*symbol + b)/symbol, None, ChiRule),
        (sympy.Mul, sympy.sin(a*symbol + b)/symbol, None, SiRule),
        (sympy.Mul, sympy.sinh(a*symbol + b)/symbol, None, ShiRule),
        (sympy.Pow, 1/sympy.log(a*symbol + b), None, LiRule),
        (sympy.exp, sympy.exp(a*symbol**2 + b*symbol + c), None, ErfRule),
        (sympy.sin, sympy.sin(a*symbol**2 + b*symbol + c), None, FresnelSRule),
        (sympy.cos, sympy.cos(a*symbol**2 + b*symbol + c), None, FresnelCRule),
        (sympy.Mul, symbol**e*sympy.exp(a*symbol), None, UpperGammaRule),
        (sympy.Mul, sympy.polylog(b, a*symbol)/symbol, None, PolylogRule),
        (sympy.Pow, 1/sympy.sqrt(a - d*sympy.sin(symbol)**2),
            lambda a, d: a != d, EllipticFRule),
        (sympy.Pow, sympy.sqrt(a - d*sympy.sin(symbol)**2),
            lambda a, d: a != d, EllipticERule),
    )
    for p in patterns:
        if isinstance(integrand, p[0]):
            match = integrand.match(p[1])
            if match:
                wild_vals = tuple(match.get(w) for w in wilds
                                  if match.get(w) is not None)
                if p[2] is None or p[2](*wild_vals):
                    args = wild_vals + (integrand, symbol)
                    return p[3](*args)

def inverse_trig_rule(integral):
    integrand, symbol = integral
    base, exp = integrand.as_base_exp()
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    match = base.match(a + b*symbol**2)

    if not match:
        return

    def negative(x):
        return x.is_negative or x.could_extract_minus_sign()

    def ArcsinhRule(integrand, symbol):
        return InverseHyperbolicRule(sympy.asinh, integrand, symbol)

    def ArccoshRule(integrand, symbol):
        return InverseHyperbolicRule(sympy.acosh, integrand, symbol)

    def make_inverse_trig(RuleClass, base_exp, a, sign_a, b, sign_b):
        u_var = sympy.Dummy("u")
        current_base = base
        current_symbol = symbol
        constant = u_func = u_constant = substep = None
        factored = integrand
        if a != 1:
            constant = a**base_exp
            current_base = sign_a + sign_b * (b/a) * current_symbol**2
            factored = current_base ** base_exp
        if (b/a) != 1:
            u_func = sympy.sqrt(b/a) * symbol
            u_constant = sympy.sqrt(a/b)
            current_symbol = u_var
            current_base = sign_a + sign_b * current_symbol**2

        substep = RuleClass(current_base ** base_exp, current_symbol)
        if u_func is not None:
            if u_constant != 1 and substep is not None:
                substep = ConstantTimesRule(
                    u_constant, current_base ** base_exp, substep,
                    u_constant * current_base ** base_exp, symbol)
            substep = URule(u_var, u_func, u_constant, substep, factored, symbol)
        if constant is not None and substep is not None:
            substep = ConstantTimesRule(constant, factored, substep, integrand, symbol)
        return substep

    a, b = [match.get(i, ZERO) for i in (a, b)]
    # list of (rule, base_exp, a, sign_a, b, sign_b, condition)
    possibilities = []

    if sympy.simplify(2*exp + 1) == 0:
        possibilities.append((ArcsinRule, exp, a, 1, -b, -1, sympy.And(a > 0, b < 0)))
        possibilities.append((ArcsinhRule, exp, a, 1, b, 1, sympy.And(a > 0, b > 0)))
        possibilities.append((ArccoshRule, exp, -a, -1, b, 1, sympy.And(a < 0, b > 0)))

    possibilities = [p for p in possibilities if p[-1] is not sympy.false]
    if a.is_number and b.is_number:
        possibility = [p for p in possibilities if p[-1] is sympy.true]
        if len(possibility) == 1:
            return make_inverse_trig(*possibility[0][:-1])
    elif possibilities:
        return PiecewiseRule(
            [(make_inverse_trig(*p[:-1]), p[-1]) for p in possibilities],
            integrand, symbol)

def add_rule(integral):
    integrand, symbol = integral
    results = [integral_steps(g, symbol)
              for g in integrand.as_ordered_terms()]
    return None if None in results else AddRule(results, integrand, symbol)

def mul_rule(integral):
    integrand, symbol = integral

    # Constant times function case
    coeff, f = integrand.as_independent(symbol)
    next_step = integral_steps(f, symbol)

    if coeff != 1 and next_step is not None:
        return ConstantTimesRule(
            coeff, f,
            next_step,
            integrand, symbol)

def _parts_rule(integrand, symbol):
    # LIATE rule:
    # log, inverse trig, algebraic, trigonometric, exponential
    def pull_out_algebraic(integrand):
        integrand = integrand.cancel().together()
        # iterating over Piecewise args would not work here
        algebraic = ([] if isinstance(integrand, sympy.Piecewise)
            else [arg for arg in integrand.args if arg.is_algebraic_expr(symbol)])
        if algebraic:
            u = sympy.Mul(*algebraic)
            dv = (integrand / u).cancel()
            return u, dv

    def pull_out_u(*functions):
        def pull_out_u_rl(integrand):
            if any([integrand.has(f) for f in functions]):
                args = [arg for arg in integrand.args
                        if any(isinstance(arg, cls) for cls in functions)]
                if args:
                    u = reduce(lambda a,b: a*b, args)
                    dv = integrand / u
                    return u, dv

        return pull_out_u_rl

    liate_rules = [pull_out_u(sympy.log), pull_out_u(sympy.atan, sympy.asin, sympy.acos),
                   pull_out_algebraic, pull_out_u(sympy.sin, sympy.cos),
                   pull_out_u(sympy.exp)]

    dummy = sympy.Dummy("temporary")
    # we can integrate log(x) and atan(x) by setting dv = 1
    if isinstance(integrand, (sympy.log, sympy.atan, sympy.asin, sympy.acos)):
        integrand = dummy * integrand

    for index, rule in enumerate(liate_rules):
        result = rule(integrand)

        if result:
            u, dv = result

            # Don't pick u to be a constant if possible
            if symbol not in u.free_symbols and not u.has(dummy):
                return

            u = u.subs(dummy, 1)
            dv = dv.subs(dummy, 1)

            # Don't pick a non-polynomial algebraic to be differentiated
            if rule == pull_out_algebraic and not u.is_polynomial(symbol):
                return
            # Don't trade one logarithm for another
            if isinstance(u, sympy.log):
                rec_dv = 1/dv
                if (rec_dv.is_polynomial(symbol) and
                    degree(rec_dv, symbol) == 1):
                        return

            # Can integrate a polynomial times OrthogonalPolynomial
            if rule == pull_out_algebraic and isinstance(dv, OrthogonalPolynomial):
                    v_step = integral_steps(dv, symbol)
                    if contains_dont_know(v_step):
                        return
                    else:
                        du = u.diff(symbol)
                        v = _manualintegrate(v_step)
                        return u, dv, v, du, v_step

            # make sure dv is amenable to integration
            accept = False
            if index < 2:  # log and inverse trig are usually worth trying
                accept = True
            elif (rule == pull_out_algebraic and dv.args and
                all(isinstance(a, (sympy.sin, sympy.cos, sympy.exp))
                for a in dv.args)):
                    accept = True
            else:
                for rule in liate_rules[index + 1:]:
                    r = rule(integrand)
                    if r and r[0].subs(dummy, 1).equals(dv):
                        accept = True
                        break

            if accept:
                du = u.diff(symbol)
                v_step = integral_steps(sympy.simplify(dv), symbol)
                if not contains_dont_know(v_step):
                    v = _manualintegrate(v_step)
                    return u, dv, v, du, v_step

def parts_rule(integral):
    integrand, symbol = integral
    constant, integrand = integrand.as_coeff_Mul()

    result = _parts_rule(integrand, symbol)

    steps = []
    if result:
        u, dv, v, du, v_step = result
        debug("u : {}, dv : {}, v : {}, du : {}, v_step: {}".format(u, dv, v, du, v_step))
        steps.append(result)

        if isinstance(v, sympy.Integral):
            return

        # Set a limit on the number of times u can be used
        if isinstance(u, (sympy.sin, sympy.cos, sympy.exp, sympy.sinh, sympy.cosh)):
            cachekey = u.xreplace({symbol: _cache_dummy})
            if _parts_u_cache[cachekey] > 2:
                return
            _parts_u_cache[cachekey] += 1

        # Try cyclic integration by parts a few times
        for _ in range(4):
            debug("Cyclic integration {} with v: {}, du: {}, integrand: {}".format(_, v, du, integrand))
            coefficient = ((v * du) / integrand).cancel()
            if coefficient == 1:
                break
            if symbol not in coefficient.free_symbols:
                rule = CyclicPartsRule(
                    [PartsRule(u, dv, v_step, None, None, None)
                     for (u, dv, v, du, v_step) in steps],
                    (-1) ** len(steps) * coefficient,
                    integrand, symbol
                )
                if (constant != 1) and rule:
                    rule = ConstantTimesRule(constant, integrand, rule,
                                             constant * integrand, symbol)
                return rule

            # _parts_rule is sensitive to constants, factor it out
            next_constant, next_integrand = (v * du).as_coeff_Mul()
            result = _parts_rule(next_integrand, symbol)

            if result:
                u, dv, v, du, v_step = result
                u *= next_constant
                du *= next_constant
                steps.append((u, dv, v, du, v_step))
            else:
                break

    def make_second_step(steps, integrand):
        if steps:
            u, dv, v, du, v_step = steps[0]
            return PartsRule(u, dv, v_step,
                             make_second_step(steps[1:], v * du),
                             integrand, symbol)
        else:
            steps = integral_steps(integrand, symbol)
            if steps:
                return steps
            else:
                return DontKnowRule(integrand, symbol)

    if steps:
        u, dv, v, du, v_step = steps[0]
        rule = PartsRule(u, dv, v_step,
                         make_second_step(steps[1:], v * du),
                         integrand, symbol)
        if (constant != 1) and rule:
            rule = ConstantTimesRule(constant, integrand, rule,
                                     constant * integrand, symbol)
        return rule

def trig_rule(integral):
    integrand, symbol = integral
    if isinstance(integrand, sympy.sin) or isinstance(integrand, sympy.cos):
        arg = integrand.args[0]

        if not isinstance(arg, sympy.Symbol):
            return  # perhaps a substitution can deal with it

        if isinstance(integrand, sympy.sin):
            func = 'sin'
        else:
            func = 'cos'

        return TrigRule(func, arg, integrand, symbol)

    if integrand == sympy.sec(symbol)**2:
        return TrigRule('sec**2', symbol, integrand, symbol)
    elif integrand == sympy.csc(symbol)**2:
        return TrigRule('csc**2', symbol, integrand, symbol)

    if isinstance(integrand, sympy.tan):
        rewritten = sympy.sin(*integrand.args) / sympy.cos(*integrand.args)
    elif isinstance(integrand, sympy.cot):
        rewritten = sympy.cos(*integrand.args) / sympy.sin(*integrand.args)
    elif isinstance(integrand, sympy.sec):
        arg = integrand.args[0]
        rewritten = ((sympy.sec(arg)**2 + sympy.tan(arg) * sympy.sec(arg)) /
                     (sympy.sec(arg) + sympy.tan(arg)))
    elif isinstance(integrand, sympy.csc):
        arg = integrand.args[0]
        rewritten = ((sympy.csc(arg)**2 + sympy.cot(arg) * sympy.csc(arg)) /
                     (sympy.csc(arg) + sympy.cot(arg)))
    else:
        return

    return RewriteRule(
        rewritten,
        integral_steps(rewritten, symbol),
        integrand, symbol
    )

def trig_product_rule(integral):
    integrand, symbol = integral

    sectan = sympy.sec(symbol) * sympy.tan(symbol)
    q = integrand / sectan

    if symbol not in q.free_symbols:
        rule = TrigRule('sec*tan', symbol, sectan, symbol)
        if q != 1 and rule:
            rule = ConstantTimesRule(q, sectan, rule, integrand, symbol)

        return rule

    csccot = -sympy.csc(symbol) * sympy.cot(symbol)
    q = integrand / csccot

    if symbol not in q.free_symbols:
        rule = TrigRule('csc*cot', symbol, csccot, symbol)
        if q != 1 and rule:
            rule = ConstantTimesRule(q, csccot, rule, integrand, symbol)

        return rule

def quadratic_denom_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    c = sympy.Wild('c', exclude=[symbol])

    match = integrand.match(a / (b * symbol ** 2 + c))

    if match:
        a, b, c = match[a], match[b], match[c]
        if b.is_extended_real and c.is_extended_real:
            return PiecewiseRule([(ArctanRule(a, b, c, integrand, symbol), sympy.Gt(c / b, 0)),
                                (ArccothRule(a, b, c, integrand, symbol), sympy.And(sympy.Gt(symbol ** 2, -c / b), sympy.Lt(c / b, 0))),
                                (ArctanhRule(a, b, c, integrand, symbol), sympy.And(sympy.Lt(symbol ** 2, -c / b), sympy.Lt(c / b, 0))),
            ], integrand, symbol)
        else:
            return ArctanRule(a, b, c, integrand, symbol)

    d = sympy.Wild('d', exclude=[symbol])
    match2 = integrand.match(a / (b * symbol ** 2 + c * symbol + d))
    if match2:
        b, c =  match2[b], match2[c]
        if b.is_zero:
            return
        u = sympy.Dummy('u')
        u_func = symbol + c/(2*b)
        integrand2 = integrand.subs(symbol, u - c / (2*b))
        next_step = integral_steps(integrand2, u)
        if next_step:
            return URule(u, u_func, None, next_step, integrand2, symbol)
        else:
            return
    e = sympy.Wild('e', exclude=[symbol])
    match3 = integrand.match((a* symbol + b) / (c * symbol ** 2 + d * symbol + e))
    if match3:
        a, b, c, d, e = match3[a], match3[b], match3[c], match3[d], match3[e]
        if c.is_zero:
            return
        denominator = c * symbol**2 + d * symbol + e
        const =  a/(2*c)
        numer1 =  (2*c*symbol+d)
        numer2 = - const*d + b
        u = sympy.Dummy('u')
        step1 = URule(u,
                      denominator,
                      const,
                      integral_steps(u**(-1), u),
                      integrand,
                      symbol)
        if const != 1:
            step1 = ConstantTimesRule(const,
                                      numer1/denominator,
                                      step1,
                                      const*numer1/denominator,
                                      symbol)
        if numer2.is_zero:
            return step1
        step2 = integral_steps(numer2/denominator, symbol)
        substeps = AddRule([step1, step2], integrand, symbol)
        rewriten = const*numer1/denominator+numer2/denominator
        return RewriteRule(rewriten, substeps, integrand, symbol)

    return

def root_mul_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    c = sympy.Wild('c')
    match = integrand.match(sympy.sqrt(a * symbol + b) * c)

    if not match:
        return

    a, b, c = match[a], match[b], match[c]
    d = sympy.Wild('d', exclude=[symbol])
    e = sympy.Wild('e', exclude=[symbol])
    f = sympy.Wild('f')
    recursion_test = c.match(sympy.sqrt(d * symbol + e) * f)
    if recursion_test:
        return

    u = sympy.Dummy('u')
    u_func = sympy.sqrt(a * symbol + b)
    integrand = integrand.subs(u_func, u)
    integrand = integrand.subs(symbol, (u**2 - b) / a)
    integrand = integrand * 2 * u / a
    next_step = integral_steps(integrand, u)
    if next_step:
        return URule(u, u_func, None, next_step, integrand, symbol)

@sympy.cacheit
def make_wilds(symbol):
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    m = sympy.Wild('m', exclude=[symbol], properties=[lambda n: isinstance(n, sympy.Integer)])
    n = sympy.Wild('n', exclude=[symbol], properties=[lambda n: isinstance(n, sympy.Integer)])

    return a, b, m, n

@sympy.cacheit
def sincos_pattern(symbol):
    a, b, m, n = make_wilds(symbol)
    pattern = sympy.sin(a*symbol)**m * sympy.cos(b*symbol)**n

    return pattern, a, b, m, n

@sympy.cacheit
def tansec_pattern(symbol):
    a, b, m, n = make_wilds(symbol)
    pattern = sympy.tan(a*symbol)**m * sympy.sec(b*symbol)**n

    return pattern, a, b, m, n

@sympy.cacheit
def cotcsc_pattern(symbol):
    a, b, m, n = make_wilds(symbol)
    pattern = sympy.cot(a*symbol)**m * sympy.csc(b*symbol)**n

    return pattern, a, b, m, n

@sympy.cacheit
def heaviside_pattern(symbol):
    m = sympy.Wild('m', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    g = sympy.Wild('g')
    pattern = sympy.Heaviside(m*symbol + b) * g

    return pattern, m, b, g

def uncurry(func):
    def uncurry_rl(args):
        return func(*args)
    return uncurry_rl

def trig_rewriter(rewrite):
    def trig_rewriter_rl(args):
        a, b, m, n, integrand, symbol = args
        rewritten = rewrite(a, b, m, n, integrand, symbol)
        if rewritten != integrand:
            return RewriteRule(
                rewritten,
                integral_steps(rewritten, symbol),
                integrand, symbol)
    return trig_rewriter_rl

sincos_botheven_condition = uncurry(
    lambda a, b, m, n, i, s: m.is_even and n.is_even and
    m.is_nonnegative and n.is_nonnegative)

sincos_botheven = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (((1 - sympy.cos(2*a*symbol)) / 2) ** (m / 2)) *
                                    (((1 + sympy.cos(2*b*symbol)) / 2) ** (n / 2)) ))

sincos_sinodd_condition = uncurry(lambda a, b, m, n, i, s: m.is_odd and m >= 3)

sincos_sinodd = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (1 - sympy.cos(a*symbol)**2)**((m - 1) / 2) *
                                    sympy.sin(a*symbol) *
                                    sympy.cos(b*symbol) ** n))

sincos_cosodd_condition = uncurry(lambda a, b, m, n, i, s: n.is_odd and n >= 3)

sincos_cosodd = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (1 - sympy.sin(b*symbol)**2)**((n - 1) / 2) *
                                    sympy.cos(b*symbol) *
                                    sympy.sin(a*symbol) ** m))

tansec_seceven_condition = uncurry(lambda a, b, m, n, i, s: n.is_even and n >= 4)
tansec_seceven = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (1 + sympy.tan(b*symbol)**2) ** (n/2 - 1) *
                                    sympy.sec(b*symbol)**2 *
                                    sympy.tan(a*symbol) ** m ))

tansec_tanodd_condition = uncurry(lambda a, b, m, n, i, s: m.is_odd)
tansec_tanodd = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (sympy.sec(a*symbol)**2 - 1) ** ((m - 1) / 2) *
                                     sympy.tan(a*symbol) *
                                     sympy.sec(b*symbol) ** n ))

tan_tansquared_condition = uncurry(lambda a, b, m, n, i, s: m == 2 and n == 0)
tan_tansquared = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( sympy.sec(a*symbol)**2 - 1))

cotcsc_csceven_condition = uncurry(lambda a, b, m, n, i, s: n.is_even and n >= 4)
cotcsc_csceven = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (1 + sympy.cot(b*symbol)**2) ** (n/2 - 1) *
                                    sympy.csc(b*symbol)**2 *
                                    sympy.cot(a*symbol) ** m ))

cotcsc_cotodd_condition = uncurry(lambda a, b, m, n, i, s: m.is_odd)
cotcsc_cotodd = trig_rewriter(
    lambda a, b, m, n, i, symbol: ( (sympy.csc(a*symbol)**2 - 1) ** ((m - 1) / 2) *
                                    sympy.cot(a*symbol) *
                                    sympy.csc(b*symbol) ** n ))

def trig_sincos_rule(integral):
    integrand, symbol = integral

    if any(integrand.has(f) for f in (sympy.sin, sympy.cos)):
        pattern, a, b, m, n = sincos_pattern(symbol)
        match = integrand.match(pattern)
        if not match:
            return

        return multiplexer({
            sincos_botheven_condition: sincos_botheven,
            sincos_sinodd_condition: sincos_sinodd,
            sincos_cosodd_condition: sincos_cosodd
        })(tuple(
            [match.get(i, ZERO) for i in (a, b, m, n)] +
            [integrand, symbol]))

def trig_tansec_rule(integral):
    integrand, symbol = integral

    integrand = integrand.subs({
        1 / sympy.cos(symbol): sympy.sec(symbol)
    })

    if any(integrand.has(f) for f in (sympy.tan, sympy.sec)):
        pattern, a, b, m, n = tansec_pattern(symbol)
        match = integrand.match(pattern)
        if not match:
            return

        return multiplexer({
            tansec_tanodd_condition: tansec_tanodd,
            tansec_seceven_condition: tansec_seceven,
            tan_tansquared_condition: tan_tansquared
        })(tuple(
            [match.get(i, ZERO) for i in (a, b, m, n)] +
            [integrand, symbol]))

def trig_cotcsc_rule(integral):
    integrand, symbol = integral
    integrand = integrand.subs({
        1 / sympy.sin(symbol): sympy.csc(symbol),
        1 / sympy.tan(symbol): sympy.cot(symbol),
        sympy.cos(symbol) / sympy.tan(symbol): sympy.cot(symbol)
    })

    if any(integrand.has(f) for f in (sympy.cot, sympy.csc)):
        pattern, a, b, m, n = cotcsc_pattern(symbol)
        match = integrand.match(pattern)
        if not match:
            return

        return multiplexer({
            cotcsc_cotodd_condition: cotcsc_cotodd,
            cotcsc_csceven_condition: cotcsc_csceven
        })(tuple(
            [match.get(i, ZERO) for i in (a, b, m, n)] +
            [integrand, symbol]))

def trig_sindouble_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[sympy.sin(2*symbol)])
    match = integrand.match(sympy.sin(2*symbol)*a)
    if match:
        sin_double = 2*sympy.sin(symbol)*sympy.cos(symbol)/sympy.sin(2*symbol)
        return integral_steps(integrand * sin_double, symbol)

def trig_powers_products_rule(integral):
    return do_one(null_safe(trig_sincos_rule),
                  null_safe(trig_tansec_rule),
                  null_safe(trig_cotcsc_rule),
                  null_safe(trig_sindouble_rule))(integral)

def trig_substitution_rule(integral):
    integrand, symbol = integral
    A = sympy.Wild('a', exclude=[0, symbol])
    B = sympy.Wild('b', exclude=[0, symbol])
    theta = sympy.Dummy("theta")
    target_pattern = A + B*symbol**2

    matches = integrand.find(target_pattern)
    for expr in matches:
        match = expr.match(target_pattern)
        a = match.get(A, ZERO)
        b = match.get(B, ZERO)

        a_positive = ((a.is_number and a > 0) or a.is_positive)
        b_positive = ((b.is_number and b > 0) or b.is_positive)
        a_negative = ((a.is_number and a < 0) or a.is_negative)
        b_negative = ((b.is_number and b < 0) or b.is_negative)
        x_func = None
        if a_positive and b_positive:
            # a**2 + b*x**2. Assume sec(theta) > 0, -pi/2 < theta < pi/2
            x_func = (sympy.sqrt(a)/sympy.sqrt(b)) * sympy.tan(theta)
            # Do not restrict the domain: tan(theta) takes on any real
            # value on the interval -pi/2 < theta < pi/2 so x takes on
            # any value
            restriction = True
        elif a_positive and b_negative:
            # a**2 - b*x**2. Assume cos(theta) > 0, -pi/2 < theta < pi/2
            constant = sympy.sqrt(a)/sympy.sqrt(-b)
            x_func = constant * sympy.sin(theta)
            restriction = sympy.And(symbol > -constant, symbol < constant)
        elif a_negative and b_positive:
            # b*x**2 - a**2. Assume sin(theta) > 0, 0 < theta < pi
            constant = sympy.sqrt(-a)/sympy.sqrt(b)
            x_func = constant * sympy.sec(theta)
            restriction = sympy.And(symbol > -constant, symbol < constant)
        if x_func:
            # Manually simplify sqrt(trig(theta)**2) to trig(theta)
            # Valid due to assumed domain restriction
            substitutions = {}
            for f in [sympy.sin, sympy.cos, sympy.tan,
                      sympy.sec, sympy.csc, sympy.cot]:
                substitutions[sympy.sqrt(f(theta)**2)] = f(theta)
                substitutions[sympy.sqrt(f(theta)**(-2))] = 1/f(theta)

            replaced = integrand.subs(symbol, x_func).trigsimp()
            replaced = manual_subs(replaced, substitutions)
            if not replaced.has(symbol):
                replaced *= manual_diff(x_func, theta)
                replaced = replaced.trigsimp()
                secants = replaced.find(1/sympy.cos(theta))
                if secants:
                    replaced = replaced.xreplace({
                        1/sympy.cos(theta): sympy.sec(theta)
                    })

                substep = integral_steps(replaced, theta)
                if not contains_dont_know(substep):
                    return TrigSubstitutionRule(
                        theta, x_func, replaced, substep, restriction,
                        integrand, symbol)

def heaviside_rule(integral):
    integrand, symbol = integral
    pattern, m, b, g = heaviside_pattern(symbol)
    match = integrand.match(pattern)
    if match and 0 != match[g]:
        # f = Heaviside(m*x + b)*g
        v_step = integral_steps(match[g], symbol)
        result = _manualintegrate(v_step)
        m, b = match[m], match[b]
        return HeavisideRule(m*symbol + b, -b/m, result, integrand, symbol)

def substitution_rule(integral):
    integrand, symbol = integral

    u_var = sympy.Dummy("u")
    substitutions = find_substitutions(integrand, symbol, u_var)
    count = 0
    if substitutions:
        debug("List of Substitution Rules")
        ways = []
        for u_func, c, substituted in substitutions:
            subrule = integral_steps(substituted, u_var)
            count = count + 1
            debug("Rule {}: {}".format(count, subrule))

            if contains_dont_know(subrule):
                continue

            if sympy.simplify(c - 1) != 0:
                _, denom = c.as_numer_denom()
                if subrule:
                    subrule = ConstantTimesRule(c, substituted, subrule, substituted, u_var)

                if denom.free_symbols:
                    piecewise = []
                    could_be_zero = []

                    if isinstance(denom, sympy.Mul):
                        could_be_zero = denom.args
                    else:
                        could_be_zero.append(denom)

                    for expr in could_be_zero:
                        if not fuzzy_not(expr.is_zero):
                            substep = integral_steps(manual_subs(integrand, expr, 0), symbol)

                            if substep:
                                piecewise.append((
                                    substep,
                                    sympy.Eq(expr, 0)
                                ))
                    piecewise.append((subrule, True))
                    subrule = PiecewiseRule(piecewise, substituted, symbol)

            ways.append(URule(u_var, u_func, c,
                              subrule,
                              integrand, symbol))

        if len(ways) > 1:
            return AlternativeRule(ways, integrand, symbol)
        elif ways:
            return ways[0]

    elif integrand.has(sympy.exp):
        u_func = sympy.exp(symbol)
        c = 1
        substituted = integrand / u_func.diff(symbol)
        substituted = substituted.subs(u_func, u_var)

        if symbol not in substituted.free_symbols:
            return URule(u_var, u_func, c,
                         integral_steps(substituted, u_var),
                         integrand, symbol)

partial_fractions_rule = rewriter(
    lambda integrand, symbol: integrand.is_rational_function(),
    lambda integrand, symbol: integrand.apart(symbol))

cancel_rule = rewriter(
    # lambda integrand, symbol: integrand.is_algebraic_expr(),
    # lambda integrand, symbol: isinstance(integrand, sympy.Mul),
    lambda integrand, symbol: True,
    lambda integrand, symbol: integrand.cancel())

distribute_expand_rule = rewriter(
    lambda integrand, symbol: (
        all(arg.is_Pow or arg.is_polynomial(symbol) for arg in integrand.args)
        or isinstance(integrand, sympy.Pow)
        or isinstance(integrand, sympy.Mul)),
    lambda integrand, symbol: integrand.expand())

trig_expand_rule = rewriter(
    # If there are trig functions with different arguments, expand them
    lambda integrand, symbol: (
        len({a.args[0] for a in integrand.atoms(TrigonometricFunction)}) > 1),
    lambda integrand, symbol: integrand.expand(trig=True))

def derivative_rule(integral):
    integrand = integral[0]
    diff_variables = integrand.variables
    undifferentiated_function = integrand.expr
    integrand_variables = undifferentiated_function.free_symbols

    if integral.symbol in integrand_variables:
        if integral.symbol in diff_variables:
            return DerivativeRule(*integral)
        else:
            return DontKnowRule(integrand, integral.symbol)
    else:
        return ConstantRule(integral.integrand, *integral)

def rewrites_rule(integral):
    integrand, symbol = integral

    if integrand.match(1/sympy.cos(symbol)):
        rewritten = integrand.subs(1/sympy.cos(symbol), sympy.sec(symbol))
        return RewriteRule(rewritten, integral_steps(rewritten, symbol), integrand, symbol)

def fallback_rule(integral):
    return DontKnowRule(*integral)

# Cache is used to break cyclic integrals.
# Need to use the same dummy variable in cached expressions for them to match.
# Also record "u" of integration by parts, to avoid infinite repetition.
_integral_cache = {}  # type: tDict[Expr, Optional[Expr]]
_parts_u_cache = defaultdict(int)  # type: tDict[Expr, int]
_cache_dummy = sympy.Dummy("z")

def integral_steps(integrand, symbol, **options):
    """Returns the steps needed to compute an integral.

    This function attempts to mirror what a student would do by hand as
    closely as possible.

    SymPy Gamma uses this to provide a step-by-step explanation of an
    integral. The code it uses to format the results of this function can be
    found at
    https://github.com/sympy/sympy_gamma/blob/master/app/logic/intsteps.py.

    Examples
    ========

    >>> from sympy import exp, sin, cos
    >>> from sympy.integrals.manualintegrate import integral_steps
    >>> from sympy.abc import x
    >>> print(repr(integral_steps(exp(x) / (1 + exp(2 * x)), x))) \
    # doctest: +NORMALIZE_WHITESPACE
    URule(u_var=_u, u_func=exp(x), constant=1,
    substep=PiecewiseRule(subfunctions=[(ArctanRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), True),
        (ArccothRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), False),
        (ArctanhRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), False)],
    context=1/(_u**2 + 1), symbol=_u), context=exp(x)/(exp(2*x) + 1), symbol=x)
    >>> print(repr(integral_steps(sin(x), x))) \
    # doctest: +NORMALIZE_WHITESPACE
    TrigRule(func='sin', arg=x, context=sin(x), symbol=x)
    >>> print(repr(integral_steps((x**2 + 3)**2 , x))) \
    # doctest: +NORMALIZE_WHITESPACE
    RewriteRule(rewritten=x**4 + 6*x**2 + 9,
    substep=AddRule(substeps=[PowerRule(base=x, exp=4, context=x**4, symbol=x),
        ConstantTimesRule(constant=6, other=x**2,
            substep=PowerRule(base=x, exp=2, context=x**2, symbol=x),
                context=6*x**2, symbol=x),
        ConstantRule(constant=9, context=9, symbol=x)],
    context=x**4 + 6*x**2 + 9, symbol=x), context=(x**2 + 3)**2, symbol=x)

    Returns
    =======
    rule : namedtuple
        The first step; most rules have substeps that must also be
        considered. These substeps can be evaluated using ``manualintegrate``
        to obtain a result.

    """
    cachekey = integrand.xreplace({symbol: _cache_dummy})
    if cachekey in _integral_cache:
        if _integral_cache[cachekey] is None:
            # Stop this attempt, because it leads around in a loop
            return DontKnowRule(integrand, symbol)
        else:
            # TODO: This is for future development, as currently
            # _integral_cache gets no values other than None
            return (_integral_cache[cachekey].xreplace(_cache_dummy, symbol),
                symbol)
    else:
        _integral_cache[cachekey] = None

    integral = IntegralInfo(integrand, symbol)

    def key(integral):
        integrand = integral.integrand

        if isinstance(integrand, TrigonometricFunction):
            return TrigonometricFunction
        elif isinstance(integrand, sympy.Derivative):
            return sympy.Derivative
        elif symbol not in integrand.free_symbols:
            return sympy.Number
        else:
            for cls in (sympy.Pow, sympy.Symbol, sympy.exp, sympy.log,
                        sympy.Add, sympy.Mul, sympy.atan, sympy.asin,
                        sympy.acos, sympy.Heaviside, OrthogonalPolynomial):
                if isinstance(integrand, cls):
                    return cls

    def integral_is_subclass(*klasses):
        def _integral_is_subclass(integral):
            k = key(integral)
            return k and issubclass(k, klasses)
        return _integral_is_subclass

    result = do_one(
        null_safe(special_function_rule),
        null_safe(switch(key, {
            sympy.Pow: do_one(null_safe(power_rule), null_safe(inverse_trig_rule), \
                              null_safe(quadratic_denom_rule)),
            sympy.Symbol: power_rule,
            sympy.exp: exp_rule,
            sympy.Add: add_rule,
            sympy.Mul: do_one(null_safe(mul_rule), null_safe(trig_product_rule), \
                              null_safe(heaviside_rule), null_safe(quadratic_denom_rule), \
                              null_safe(root_mul_rule)),
            sympy.Derivative: derivative_rule,
            TrigonometricFunction: trig_rule,
            sympy.Heaviside: heaviside_rule,
            OrthogonalPolynomial: orthogonal_poly_rule,
            sympy.Number: constant_rule
        })),
        do_one(
            null_safe(trig_rule),
            null_safe(alternatives(
                rewrites_rule,
                substitution_rule,
                condition(
                    integral_is_subclass(sympy.Mul, sympy.Pow),
                    partial_fractions_rule),
                condition(
                    integral_is_subclass(sympy.Mul, sympy.Pow),
                    cancel_rule),
                condition(
                    integral_is_subclass(sympy.Mul, sympy.log, sympy.atan, sympy.asin, sympy.acos),
                    parts_rule),
                condition(
                    integral_is_subclass(sympy.Mul, sympy.Pow),
                    distribute_expand_rule),
                trig_powers_products_rule,
                trig_expand_rule
            )),
            null_safe(trig_substitution_rule)
        ),
        fallback_rule)(integral)
    del _integral_cache[cachekey]
    return result

@evaluates(ConstantRule)
def eval_constant(constant, integrand, symbol):
    return constant * symbol

@evaluates(ConstantTimesRule)
def eval_constanttimes(constant, other, substep, integrand, symbol):
    return constant * _manualintegrate(substep)

@evaluates(PowerRule)
def eval_power(base, exp, integrand, symbol):
    return sympy.Piecewise(
        ((base**(exp + 1))/(exp + 1), sympy.Ne(exp, -1)),
        (sympy.log(base), True),
        )

@evaluates(ExpRule)
def eval_exp(base, exp, integrand, symbol):
    return integrand / sympy.ln(base)

@evaluates(AddRule)
def eval_add(substeps, integrand, symbol):
    return sum(map(_manualintegrate, substeps))

@evaluates(URule)
def eval_u(u_var, u_func, constant, substep, integrand, symbol):
    result = _manualintegrate(substep)
    if u_func.is_Pow and u_func.exp == -1:
        # avoid needless -log(1/x) from substitution
        result = result.subs(sympy.log(u_var), -sympy.log(u_func.base))
    return result.subs(u_var, u_func)

@evaluates(PartsRule)
def eval_parts(u, dv, v_step, second_step, integrand, symbol):
    v = _manualintegrate(v_step)

    return u * v - _manualintegrate(second_step)

@evaluates(CyclicPartsRule)
def eval_cyclicparts(parts_rules, coefficient, integrand, symbol):
    coefficient = 1 - coefficient
    result = []

    sign = 1
    for rule in parts_rules:
        result.append(sign * rule.u * _manualintegrate(rule.v_step))
        sign *= -1

    return sympy.Add(*result) / coefficient

@evaluates(TrigRule)
def eval_trig(func, arg, integrand, symbol):
    if func == 'sin':
        return -sympy.cos(arg)
    elif func == 'cos':
        return sympy.sin(arg)
    elif func == 'sec*tan':
        return sympy.sec(arg)
    elif func == 'csc*cot':
        return sympy.csc(arg)
    elif func == 'sec**2':
        return sympy.tan(arg)
    elif func == 'csc**2':
        return -sympy.cot(arg)

@evaluates(ArctanRule)
def eval_arctan(a, b, c, integrand, symbol):
    return a / b * 1 / sympy.sqrt(c / b) * sympy.atan(symbol / sympy.sqrt(c / b))

@evaluates(ArccothRule)
def eval_arccoth(a, b, c, integrand, symbol):
    return - a / b * 1 / sympy.sqrt(-c / b) * sympy.acoth(symbol / sympy.sqrt(-c / b))

@evaluates(ArctanhRule)
def eval_arctanh(a, b, c, integrand, symbol):
    return - a / b * 1 / sympy.sqrt(-c / b) * sympy.atanh(symbol / sympy.sqrt(-c / b))

@evaluates(ReciprocalRule)
def eval_reciprocal(func, integrand, symbol):
    return sympy.ln(func)

@evaluates(ArcsinRule)
def eval_arcsin(integrand, symbol):
    return sympy.asin(symbol)

@evaluates(InverseHyperbolicRule)
def eval_inversehyperbolic(func, integrand, symbol):
    return func(symbol)

@evaluates(AlternativeRule)
def eval_alternative(alternatives, integrand, symbol):
    return _manualintegrate(alternatives[0])

@evaluates(RewriteRule)
def eval_rewrite(rewritten, substep, integrand, symbol):
    return _manualintegrate(substep)

@evaluates(PiecewiseRule)
def eval_piecewise(substeps, integrand, symbol):
    return sympy.Piecewise(*[(_manualintegrate(substep), cond)
                             for substep, cond in substeps])

@evaluates(TrigSubstitutionRule)
def eval_trigsubstitution(theta, func, rewritten, substep, restriction, integrand, symbol):
    func = func.subs(sympy.sec(theta), 1/sympy.cos(theta))

    trig_function = list(func.find(TrigonometricFunction))
    assert len(trig_function) == 1
    trig_function = trig_function[0]
    relation = sympy.solve(symbol - func, trig_function)
    assert len(relation) == 1
    numer, denom = sympy.fraction(relation[0])

    if isinstance(trig_function, sympy.sin):
        opposite = numer
        hypotenuse = denom
        adjacent = sympy.sqrt(denom**2 - numer**2)
        inverse = sympy.asin(relation[0])
    elif isinstance(trig_function, sympy.cos):
        adjacent = numer
        hypotenuse = denom
        opposite = sympy.sqrt(denom**2 - numer**2)
        inverse = sympy.acos(relation[0])
    elif isinstance(trig_function, sympy.tan):
        opposite = numer
        adjacent = denom
        hypotenuse = sympy.sqrt(denom**2 + numer**2)
        inverse = sympy.atan(relation[0])

    substitution = [
        (sympy.sin(theta), opposite/hypotenuse),
        (sympy.cos(theta), adjacent/hypotenuse),
        (sympy.tan(theta), opposite/adjacent),
        (theta, inverse)
    ]
    return sympy.Piecewise(
        (_manualintegrate(substep).subs(substitution).trigsimp(), restriction)
    )

@evaluates(DerivativeRule)
def eval_derivativerule(integrand, symbol):
    # isinstance(integrand, Derivative) should be True
    variable_count = list(integrand.variable_count)
    for i, (var, count) in enumerate(variable_count):
        if var == symbol:
            variable_count[i] = (var, count-1)
            break
    return sympy.Derivative(integrand.expr, *variable_count)

@evaluates(HeavisideRule)
def eval_heaviside(harg, ibnd, substep, integrand, symbol):
    # If we are integrating over x and the integrand has the form
    #       Heaviside(m*x+b)*g(x) == Heaviside(harg)*g(symbol)
    # then there needs to be continuity at -b/m == ibnd,
    # so we subtract the appropriate term.
    return sympy.Heaviside(harg)*(substep - substep.subs(symbol, ibnd))

@evaluates(JacobiRule)
def eval_jacobi(n, a, b, integrand, symbol):
    return Piecewise(
        (2*sympy.jacobi(n + 1, a - 1, b - 1, symbol)/(n + a + b), Ne(n + a + b, 0)),
        (symbol, Eq(n, 0)),
        ((a + b + 2)*symbol**2/4 + (a - b)*symbol/2, Eq(n, 1)))

@evaluates(GegenbauerRule)
def eval_gegenbauer(n, a, integrand, symbol):
    return Piecewise(
        (sympy.gegenbauer(n + 1, a - 1, symbol)/(2*(a - 1)), Ne(a, 1)),
        (sympy.chebyshevt(n + 1, symbol)/(n + 1), Ne(n, -1)),
        (sympy.S.Zero, True))

@evaluates(ChebyshevTRule)
def eval_chebyshevt(n, integrand, symbol):
    return Piecewise(((sympy.chebyshevt(n + 1, symbol)/(n + 1) -
        sympy.chebyshevt(n - 1, symbol)/(n - 1))/2, Ne(sympy.Abs(n), 1)),
        (symbol**2/2, True))

@evaluates(ChebyshevURule)
def eval_chebyshevu(n, integrand, symbol):
    return Piecewise(
        (sympy.chebyshevt(n + 1, symbol)/(n + 1), Ne(n, -1)),
        (sympy.S.Zero, True))

@evaluates(LegendreRule)
def eval_legendre(n, integrand, symbol):
    return (sympy.legendre(n + 1, symbol) - sympy.legendre(n - 1, symbol))/(2*n + 1)

@evaluates(HermiteRule)
def eval_hermite(n, integrand, symbol):
    return sympy.hermite(n + 1, symbol)/(2*(n + 1))

@evaluates(LaguerreRule)
def eval_laguerre(n, integrand, symbol):
    return sympy.laguerre(n, symbol) - sympy.laguerre(n + 1, symbol)

@evaluates(AssocLaguerreRule)
def eval_assoclaguerre(n, a, integrand, symbol):
    return -sympy.assoc_laguerre(n + 1, a - 1, symbol)

@evaluates(CiRule)
def eval_ci(a, b, integrand, symbol):
    return sympy.cos(b)*sympy.Ci(a*symbol) - sympy.sin(b)*sympy.Si(a*symbol)

@evaluates(ChiRule)
def eval_chi(a, b, integrand, symbol):
    return sympy.cosh(b)*sympy.Chi(a*symbol) + sympy.sinh(b)*sympy.Shi(a*symbol)

@evaluates(EiRule)
def eval_ei(a, b, integrand, symbol):
    return sympy.exp(b)*sympy.Ei(a*symbol)

@evaluates(SiRule)
def eval_si(a, b, integrand, symbol):
    return sympy.sin(b)*sympy.Ci(a*symbol) + sympy.cos(b)*sympy.Si(a*symbol)

@evaluates(ShiRule)
def eval_shi(a, b, integrand, symbol):
    return sympy.sinh(b)*sympy.Chi(a*symbol) + sympy.cosh(b)*sympy.Shi(a*symbol)

@evaluates(ErfRule)
def eval_erf(a, b, c, integrand, symbol):
    if a.is_extended_real:
        return Piecewise(
            (sympy.sqrt(sympy.pi/(-a))/2 * sympy.exp(c - b**2/(4*a)) *
                sympy.erf((-2*a*symbol - b)/(2*sympy.sqrt(-a))), a < 0),
            (sympy.sqrt(sympy.pi/a)/2 * sympy.exp(c - b**2/(4*a)) *
                sympy.erfi((2*a*symbol + b)/(2*sympy.sqrt(a))), True))
    else:
        return sympy.sqrt(sympy.pi/a)/2 * sympy.exp(c - b**2/(4*a)) * \
                sympy.erfi((2*a*symbol + b)/(2*sympy.sqrt(a)))

@evaluates(FresnelCRule)
def eval_fresnelc(a, b, c, integrand, symbol):
    return sympy.sqrt(sympy.pi/(2*a)) * (
        sympy.cos(b**2/(4*a) - c)*sympy.fresnelc((2*a*symbol + b)/sympy.sqrt(2*a*sympy.pi)) +
        sympy.sin(b**2/(4*a) - c)*sympy.fresnels((2*a*symbol + b)/sympy.sqrt(2*a*sympy.pi)))

@evaluates(FresnelSRule)
def eval_fresnels(a, b, c, integrand, symbol):
    return sympy.sqrt(sympy.pi/(2*a)) * (
        sympy.cos(b**2/(4*a) - c)*sympy.fresnels((2*a*symbol + b)/sympy.sqrt(2*a*sympy.pi)) -
        sympy.sin(b**2/(4*a) - c)*sympy.fresnelc((2*a*symbol + b)/sympy.sqrt(2*a*sympy.pi)))

@evaluates(LiRule)
def eval_li(a, b, integrand, symbol):
    return sympy.li(a*symbol + b)/a

@evaluates(PolylogRule)
def eval_polylog(a, b, integrand, symbol):
    return sympy.polylog(b + 1, a*symbol)

@evaluates(UpperGammaRule)
def eval_uppergamma(a, e, integrand, symbol):
    return symbol**e * (-a*symbol)**(-e) * sympy.uppergamma(e + 1, -a*symbol)/a

@evaluates(EllipticFRule)
def eval_elliptic_f(a, d, integrand, symbol):
    return sympy.elliptic_f(symbol, d/a)/sympy.sqrt(a)

@evaluates(EllipticERule)
def eval_elliptic_e(a, d, integrand, symbol):
    return sympy.elliptic_e(symbol, d/a)*sympy.sqrt(a)

@evaluates(DontKnowRule)
def eval_dontknowrule(integrand, symbol):
    return sympy.Integral(integrand, symbol)

def _manualintegrate(rule):
    evaluator = evaluators.get(rule.__class__)
    if not evaluator:

        raise ValueError("Cannot evaluate rule %s" % repr(rule))
    return evaluator(*rule)

def manualintegrate(f, var):
    """manualintegrate(f, var)

    Compute indefinite integral of a single variable using an algorithm that
    resembles what a student would do by hand.

    Unlike :func:`~.integrate`, var can only be a single symbol.

    Examples
    ========

    >>> from sympy import sin, cos, tan, exp, log, integrate
    >>> from sympy.integrals.manualintegrate import manualintegrate
    >>> from sympy.abc import x
    >>> manualintegrate(1 / x, x)
    log(x)
    >>> integrate(1/x)
    log(x)
    >>> manualintegrate(log(x), x)
    x*log(x) - x
    >>> integrate(log(x))
    x*log(x) - x
    >>> manualintegrate(exp(x) / (1 + exp(2 * x)), x)
    atan(exp(x))
    >>> integrate(exp(x) / (1 + exp(2 * x)))
    RootSum(4*_z**2 + 1, Lambda(_i, _i*log(2*_i + exp(x))))
    >>> manualintegrate(cos(x)**4 * sin(x), x)
    -cos(x)**5/5
    >>> integrate(cos(x)**4 * sin(x), x)
    -cos(x)**5/5
    >>> manualintegrate(cos(x)**4 * sin(x)**3, x)
    cos(x)**7/7 - cos(x)**5/5
    >>> integrate(cos(x)**4 * sin(x)**3, x)
    cos(x)**7/7 - cos(x)**5/5
    >>> manualintegrate(tan(x), x)
    -log(cos(x))
    >>> integrate(tan(x), x)
    -log(cos(x))

    See Also
    ========

    sympy.integrals.integrals.integrate
    sympy.integrals.integrals.Integral.doit
    sympy.integrals.integrals.Integral
    """
    result = _manualintegrate(integral_steps(f, var))
    # Clear the cache of u-parts
    _parts_u_cache.clear()
    # If we got Piecewise with two parts, put generic first
    if isinstance(result, Piecewise) and len(result.args) == 2:
        cond = result.args[0][1]
        if isinstance(cond, Eq) and result.args[1][1] == True:
            result = result.func(
                (result.args[1][0], sympy.Ne(*cond.args)),
                (result.args[0][0], True))
    return result

max_stars_repo_name: Abhishek-IOT/sympy

max_issues_repo_name: mmelotti/sympy

max_forks_repo_name: mmelotti/sympy

reason: import sympy,from sympy


text:
import argparse
import logging

import numpy as np
import pandas as pd

from sklearn.preprocessing import OneHotEncoder

def check_nans(df):
    """ Auxiliary function for data wrangling logs """
    n_rows = len(df)

    check_df = {'col': [], 'dtype': [], 'nan_prc': []}
    for col in df.columns:
        check_df['col'].append(col)
        check_df['dtype'].append(df[col].dtype)
        check_df['nan_prc'].append(df[col].isna().sum()/n_rows)

    check_df = pd.DataFrame(check_df)
    print("\n")
    print(f"dataframe n_rows {n_rows}")
    print(check_df)
    print("\n")

def one_hot_encoding(df, unique_id):
    """
    Creates a new dataframe with one hot encoded variables
    Arguments
    ---------
    df: Pandas DataFrame
        Original data with categorical or object columns to encode
    unique_id: str
        String index that identifies each unique observation in df

    Returns
    -------
    one_hot_concat_df: Pandas DataFrame
        Processed data with one hot encoded variables.
        The column names identify each category and its levels.
         i.e.  category_[level1], category_[level2] ...
    """
    encoder = OneHotEncoder()
    columns = list(df.columns)
    columns.remove(unique_id)
    one_hot_concat_df = pd.DataFrame(df[unique_id].values, columns=[unique_id])
    for col in columns:
        dummy_columns = [f'{col}_[{x}]' for x in list(df[col].unique())]
        dummy_values  = encoder.fit_transform(df[col].values.reshape(-1,1)).toarray()
        one_hot_df    = pd.DataFrame(dummy_values, columns=dummy_columns)
        one_hot_concat_df = pd.concat([one_hot_concat_df, one_hot_df], axis=1)
    return one_hot_concat_df

def numpy_balance(*arrs):
    N = len(arrs)
    out =  np.transpose(np.meshgrid(*arrs, indexing='ij'),
                        np.roll(np.arange(N + 1), -1)).reshape(-1, N)
    return out

def numpy_ffill(arr):
    mask = np.isnan(arr)
    idx = np.where(~mask, np.arange(mask.shape[1]), 0)
    np.maximum.accumulate(idx, axis=1, out=idx)
    out = arr[np.arange(idx.shape[0])[:,None], idx]
    return out

def numpy_bfill(arr):
    mask = np.isnan(arr)
    idx = np.where(~mask, np.arange(mask.shape[1]), mask.shape[1] - 1)
    idx = np.minimum.accumulate(idx[:, ::-1], axis=1)[:, ::-1]
    out = arr[np.arange(idx.shape[0])[:,None], idx]
    return out

def temporal_preprocessing(temporal, unique_id, ds,
                           zfill_cols=[], ffill_cols=[],
                           original_date_range=True):
    """
    Creates a new panel dataframe with balanced temporal data.
    Arguments
    ---------
    temporal: Pandas DataFrame
        Original data with temporal observations to process
    unique_id: str
        String index that identifies each unique trajectory in df
    ds: str
        String index that identifies dates for each trajectory.
    zfill_cols: str list
        String list with columns to be filled with zeros after balance.
    ffill_cols: str list
        String list with columns to be filled with forward fill ('ffill')
        after balance.
    original_date_range: bool
        Boolean with option to filter the trajectories to original date range.
        If false completely balanced panel is returned.

    Returns
    -------
    balanced_df: Pandas DataFrame
        Preprocessed data balanced and filled nans.
    """
    df = temporal.copy()
    UIDS  = temporal[unique_id].unique()
    DATES = temporal[ds].unique()

    # Balance panel (fixed UIDS)
    balanced_prod = numpy_balance(UIDS, DATES)
    balanced_df   = pd.DataFrame(balanced_prod, columns=[unique_id, ds])
    balanced_df[ds] = balanced_df[ds].astype(DATES.dtype)

    df.set_index([unique_id, ds], inplace=True)
    balanced_df.set_index([unique_id, ds], inplace=True)
    balanced_df = balanced_df.merge(df, how='left',
                                    left_on=[unique_id, ds],
                                    right_index=True).reset_index()

    # FFill and ZFill
    for col in zfill_cols:
        balanced_df[col] = balanced_df[col].fillna(0)

    for col in ffill_cols:
        col_values = balanced_df[col].astype('float32').values
        col_values = col_values.reshape(len(UIDS), len(DATES))
        col_values = numpy_ffill(col_values)
        #col_values = numpy_bfill(col_values)
        balanced_df[col] = col_values.flatten()
        #balanced_df[col] = balanced_df[col].fillna(0)

    # Match original date interval through filter
    if original_date_range:
        date_range_df = temporal.groupby(unique_id).agg({ds: ['min', 'max']})
        date_range_df = date_range_df.droplevel(1, axis=1).reset_index()
        date_range_df.columns = [unique_id, 'min_ds', 'max_ds']

        date_range_df.set_index([unique_id], inplace=True)
        balanced_df.set_index([unique_id], inplace=True)

        balanced_df = balanced_df.merge(date_range_df, how='left',
                                        left_on=[unique_id],
                                        right_index=True).reset_index()
        balanced_df['ds_in_range'] = (balanced_df[ds] >= balanced_df['min_ds']) & \
                                     (balanced_df[ds] <= balanced_df['max_ds'])
        balanced_df = balanced_df[balanced_df['ds_in_range']]
        balanced_df.drop(['ds_in_range', 'min_ds', 'max_ds'], axis=1, inplace=True)

    return balanced_df

class TSPreprocess:
    """Preprocess time series."""

    def __init__(self, filename: str,
                 filename_output: str,
                 kind: str,
                 unique_id_column: str,
                 ds_column: str, y_column: str) -> 'TSPreprocess':
        self.filename = filename
        if filename_output is None:
            self.filename_output = f'{kind}-preprocessed.csv'
        else:
            self.filename_output = filename_output
        self.kind = kind
        self.unique_id_column = unique_id_column
        self.ds_column = ds_column
        self.y_column = y_column
        self.df: pd.DataFrame

        self.df = self._read_file()

    def _read_file(self) -> pd.DataFrame:
        logger.info('Reading file...')
        df = pd.read_csv(f'/opt/ml/processing/input/{self.filename}')
        logger.info('File read.')
        renamer = {self.unique_id_column: 'unique_id',
                   self.ds_column: 'ds',
                   self.y_column: 'y'}

        df.rename(columns=renamer, inplace=True)

        if self.kind == 'balance':
            df['ds'] = pd.to_datetime(df['ds'])

        return df

    def get_one_hot_encoded(self) -> None:
        """One-hot encodes."""
        logger.info('One hot encoding...')
        df_ohe = one_hot_encoding(self.df, 'unique_id')
        logger.info('OHE finished.')

        logger.info('Writing file...')
        df_ohe.to_csv(f'/opt/ml/processing/output/{self.filename_output}',
                        index=False)
        logger.info('File written...')

    def get_balanced_data(self) -> None:
        """Balance data."""
        logger.info('Balancing data...')
        balanced_data = temporal_preprocessing(self.df, 'unique_id', 'ds',
                                               ['y'])
        logger.info('Finished.')

        logger.info('Writing file...')
        balanced_data.to_csv(f'/opt/ml/processing/output/{self.filename_output}',
                             index=False)
        logger.info('File written...')

    def preprocess(self) -> None:
        if self.kind == 'onehot':
            self.get_one_hot_encoded()
        elif self.kind == 'balance':
            self.get_balanced_data()
        else:
            raise ValueError(
                '`kind` only accepts "onehot" or "balance"'
                ' as input'
            )

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)

    parser = argparse.ArgumentParser()

    parser.add_argument('--filename', type=str, required=True)
    parser.add_argument('--kind', type=str, required=True,
                        help='onehot or balance')
    parser.add_argument('--filename-output', type=str, default=None)
    parser.add_argument('--unique-id-column', type=str, default='unique_id')
    parser.add_argument('--ds-column', type=str, default='ds')
    parser.add_argument('--y-column', type=str, default='y')

    args = parser.parse_args()
    tspreprocess = TSPreprocess(**vars(args))

    tspreprocess.preprocess()

max_stars_repo_name: KielRodriguez/nixtla

max_issues_repo_name: valeman/nixtla

max_forks_repo_name: valeman/nixtla


text:
#!/usr/bin/python3

import logging
import math
import astropy.units as u

import pyproj

from simtools.layout.telescope_data import TelescopeData

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

def test_input():
    configData = {
        'posX': -70.93 * u.m,
        'posY': -52.07 * u.m,
        'posZ': 43.00 * u.m,
        'altitude': 2.177 * u.km
    }
    tel = TelescopeData(name='L-01', configData=configData)

    assert tel._posX == -70.93
    # Testing default unit convertion
    # altitude should be converted to m
    assert tel._altitude == 2177

def test_coordinate_transformations():
    configData = {
        'posX': 0 * u.m,
        'posY': 0 * u.m,
        'posZ': 43.00 * u.m,
        'altitude': 2.177 * u.km,
    }
    tel = TelescopeData(name='L-01', configData=configData)

    wgs84 = pyproj.CRS('EPSG:4326')

    center_lon = -17.8920302
    center_lat = 28.7621661
    proj4_string = '+proj=tmerc +ellps=WGS84 +datum=WGS84'
    proj4_string += ' +lon_0={} +lat_0={}'.format(center_lon, center_lat)
    proj4_string += ' +axis=nwu +units=m +k_0=1.0'
    crsLocal = pyproj.CRS.from_proj4(proj4_string)

    tel.convertLocalToMercator(wgs84=wgs84, crsLocal=crsLocal)

    assert math.isclose(tel._latitude, center_lat, abs_tol=0.000001)
    assert math.isclose(tel._longitude, center_lon, abs_tol=0.000001)

    crsUtm = pyproj.CRS.from_user_input(32628)

    tel.convertLocalToUtm(crsUtm=crsUtm, crsLocal=crsLocal)

    assert math.isclose(tel._utmEast, 217611, abs_tol=3)
    assert math.isclose(tel._utmNorth, 3185066, abs_tol=5)

    tel._latitude = None
    tel._longitude = None

    tel.convertUtmToMercator(crsUtm=crsUtm, wgs84=wgs84)

    assert math.isclose(tel._latitude, center_lat, abs_tol=0.000001)
    assert math.isclose(tel._longitude, center_lon, abs_tol=0.000001)

    print(tel._latitude, tel._longitude)

def test_corsika_transformations():
    configData = {
        'posX': 0 * u.m,
        'posY': 0 * u.m,
        'altitude': 2.177 * u.km,
    }
    tel = TelescopeData(name='L-01', configData=configData)

    # ASL -> CORSIKA
    tel.convertAslToCorsika(
        corsikaObsLevel=2158 * u.m,
        corsikaSphereCenter=16 * u.m
    )
    assert math.isclose(tel._posZ, 35.0, abs_tol=0.1)

    # CORSIKA -> ASL
    tel._posZ = 35.0
    tel._altitude = None

    tel.convertCorsikaToAsl(
        corsikaObsLevel=2158 * u.m,
        corsikaSphereCenter=16 * u.m
    )
    assert math.isclose(tel._altitude, 2177, abs_tol=0.1)

def test_convert_all():
    configData = {
        'posX': 0 * u.m,
        'posY': 0 * u.m,
        'posZ': 43.00 * u.m,
    }
    tel = TelescopeData(name='L-01', configData=configData)

    wgs84 = pyproj.CRS('EPSG:4326')

    center_lon = -17.8920302
    center_lat = 28.7621661
    proj4_string = '+proj=tmerc +ellps=WGS84 +datum=WGS84'
    proj4_string += ' +lon_0={} +lat_0={}'.format(center_lon, center_lat)
    proj4_string += ' +axis=nwu +units=m +k_0=1.0'
    crsLocal = pyproj.CRS.from_proj4(proj4_string)

    crsUtm = pyproj.CRS.from_user_input(32628)

    tel.convertAll(
        wgs84=wgs84,
        crsLocal=crsLocal,
        crsUtm=crsUtm,
        corsikaObsLevel=2158 * u.m,
        corsikaSphereCenter=16 * u.m
    )

if __name__ == '__main__':

    test_input()
    # test_coordinate_transformations()
    # test_corsika_transformations()
    # test_convert_all()
    pass

max_stars_repo_name: gammasim/gammasim-tools

max_issues_repo_name: gammasim/gammasim-tools

max_forks_repo_name: gammasim/gammasim-tools

reason: import astropy


text:
import os
import cv2
import copy
import numpy as np
import tensorflow as tf
from os import listdir
from pathlib import Path
from os.path import isfile, join
from tqdm import tqdm
from sklearn.datasets import load_sample_image
from sklearn.feature_extraction import image

import matplotlib.pyplot as plt

def create(pp, img, p):

    img_ = np.zeros((p, 128, 128, 1), dtype=np.float32)

    for i in range(len(img)):
        mask = np.random.choice([0, 1], size=(128, 128), p=[1-pp, pp])
        idx_w, idx_h = np.where(mask ==  1)

        for j in range(len(idx_w)):
            img[i, idx_w[j],idx_h[j],0] = 0

        img_[i,:,:,0] = img[i,:,:,0]
    return img_

def curate(path, lt,  x, y):

    cnt = 0
    for idx, j in tqdm(enumerate(lt)):
        onlyfiles   = [f for f in listdir(lt[idx]) if isfile(join(lt[idx], f))]
        onlyfiles.remove('Thumbs.db')

        for _, i in enumerate(onlyfiles):
            p = join(str(lt[idx]),i)
            img = cv2.imread(p, 0)
            y_patches = image.extract_patches_2d(img, (128,128), max_patches = 8)

            y_patches = np.reshape(y_patches,(8, 128,128,-1))

            y_patch = copy.deepcopy(y_patches)
            x_patches = create(0.85, y_patch, 8)

            for k in range(len(x_patches)):
                x[cnt] = x_patches[k]
                y[cnt] = y_patches[k]
                cnt += 1

def curate_(path, lt,  x, y):

    cnt = 0
    for idx, j in tqdm(enumerate(lt)):
        onlyfiles   = [f for f in listdir(lt[idx]) if isfile(join(lt[idx], f))]

        for _, i in enumerate(onlyfiles):
            p = join(str(lt[idx]),i)
            img = cv2.imread(p, 0)
            y_patches = image.extract_patches_2d(img, (128,128), max_patches = 2)

            y_patches = np.reshape(y_patches,(2, 128,128,-1))

            y_patch = copy.deepcopy(y_patches)
            x_patches = create(0.85, y_patch, 2)

            for k in range(len(x_patches)):
                x[cnt] = x_patches[k]
                y[cnt] = y_patches[k]
                cnt += 1

def imgSave():

    x_ = np.zeros((10, 128, 128, 1), dtype=np.uint8)
    y_ = np.zeros((10, 128, 128, 1), dtype=np.uint8)

    data = Path('/workspace/storage/cnn-cs/data/test')
    lst = os.listdir(data)
    lst.sort()

    count = 0

    for _, i in enumerate(lst):
        p = join(data,i)
        img = cv2.imread(p, 0)

        y_patches = image.extract_patches_2d(img, (128, 128), max_patches = 1)
        y_patches = np.reshape(y_patches,(1, 128, 128,-1))
        y_patch = copy.deepcopy(y_patches)
        x_patches = create(0.10, y_patch, 1)

        for k in range(len(x_patches)):
            x_[count] = x_patches[k]
            y_[count] = y_patches[k]
            count += 1

    x_ = x_ / 255.
    y_ = y_ / 255.

    fig = plt.figure(figsize=(25, 25))
    columns = 10
    rows = 1
    for i in range(1, columns*rows + 1):
        img_x = x_[i-1]
        ax = fig.add_subplot(rows, columns, i)
        ax.set_xticks([])
        ax.set_yticks([])
        plt.imshow(np.reshape(img_x,(128,128)),cmap='gray')

    plt.savefig('/workspace/data/image_sparse.png')

    model = tf.keras.models.load_model('/workspace/data/cs-simple-model-1000.h5', compile =False)

    predict = model.predict(x_[:10,:,:,:])

    fig = plt.figure(figsize=(25, 25))
    columns = 10
    rows = 1
    for i in range(1, columns*rows + 1):
        img_x = predict[i-1]
        ax = fig.add_subplot(rows, columns, i)
        ax.set_xticks([])
        ax.set_yticks([])
        plt.imshow(np.reshape(img_x,(128,128)), cmap='gray')

    plt.savefig('/workspace/data/image_recons.png')
    psnr_ = tf.image.psnr(y_[:10,:,:,:], predict, max_val=1.0)
    print(psnr_)

def printResult(X, Y):

    fig = plt.figure(figsize=(9, 4))
    columns = 10
    rows = 1
    for i in range(1, columns*rows + 1):
        img_x = X[i-1]
        ax = fig.add_subplot(rows, columns, i)
        ax.set_xticks([])
        ax.set_yticks([])
        plt.imshow(img_x, cmap = 'gray')
    plt.show()
    return None

def saveResult():
    rows = 3
    cols = 3

    fig =  plt.figure(figsize=(12,10))

    for i in range(1,rows+1):
        for j in range(1, cols+1):
            img = cv2.imread(os.path.join(os.getcwd(),onlyfewfiles[((i-1)*rows)+j - 1]), 0)
            patch = image.extract_patches_2d(img, (128,128), max_patches = 1)
            img = np.resize(patch,(128,128))
            ax = fig.add_subplot(rows, cols, ((i-1)*rows)+j)
            ax.set_xticks([])
            ax.set_yticks([])
            ax.set_title('{}\nNewline'.format(onlyfewfiles[((i-1)*rows)+j - 1]), fontsize=8)
            plt.imshow(img, cmap='gray')

    plt.show()

    return None

def convertModel(path):

    lst = [x for x in os.listdir(path) if os.path.isdir(os.path.join(path,x))]

    for idx, val in enumerate(lst):
        converter = tf.lite.TFLiteConverter.from_saved_model(path+'/'+val)
        tflite_model = converter.convert()
        with open('/home/wilfred/Downloads/github/Python_Projects/cnn-cs/results/constant_85/'+val+'-model.tflite', 'wb') as f:
            f.write(tflite_model)
    return None

def extractWeights(path):

    model = tf.keras.models.load_model(path, compile=False)

    for layer in model.layers:
        if len(layer.weights) > 0:
            print(layer.name, layer.weights[0].shape)
            print(np.where(layer.weights[0] == 0))

    return None

if __name__ == "__main__":

    '''
    count_n = 0
    IMG_WIDTH = 128
    IMG_HEIGHT = 128

    Path1 = Path('/workspace/storage/cnn-cs/data/images')
    Path2 = Path('/workspace/storage/cnn-cs/data/train')

    lst  = [x for x in Path1.iterdir() if Path1.is_dir()]
    lst_ = [x for x in Path2.iterdir() if Path2.is_dir()]

    for i in range(len(lst)):
        count_n += len(os.listdir(os.path.join(Path1,lst[i]))) - 1

    x_train = np.zeros((count_n * 8, IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.uint8)
    y_train = np.zeros((count_n * 8, IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.uint8)

    curate(Path1, lst, x_train, y_train)

    count_n = 0

    for i in range(len(lst_)):
        count_n += len(os.listdir(os.path.join(Path2,lst_[i])))

    X_train = np.zeros((count_n * 2, IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.uint8)
    Y_train = np.zeros((count_n * 2, IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.uint8)

    curate_(Path2, lst_, X_train, Y_train)

    convertModel()
    '''

    #p_hi = '/home/wilfred/Downloads/github/Python_Projects/cnn-cs/results/constant_85/hi-model/cs-hi-model-500.h5'
    p_simple = '/home/wilfred/Downloads/github/Python_Projects/cnn-cs/results/constant_85/simple-model/cs-simple-model-500.h5'
    p_sq = '/home/wilfred/Downloads/github/Python_Projects/cnn-cs/results/constant_85/sq-model/cs-sq-model-500.h5'
    extractWeights(p_sq)

max_stars_repo_name: wilfredkisku/cnn-cs

max_issues_repo_name: wilfredkisku/cnn-cs

max_forks_repo_name: wilfredkisku/cnn-cs