import os

import torch
import torch.nn as nn
import torch.nn.functional as F

from modelscope.metainfo import Models
from modelscope.models import MODELS, TorchModel
from modelscope.utils.constant import ModelFile, Tasks
from .mossformer_block import MossformerBlockGFSMN, ScaledSinuEmbedding

EPS = 1e-8

class GlobalLayerNorm(nn.Module):
    """Calculate Global Layer Normalization.

    Args:
       dim : (int or list or torch.Size)
           Input shape from an expected input of size.
       eps : float
           A value added to the denominator for numerical stability.
       elementwise_affine : bool
          A boolean value that when set to True,
          this module has learnable per-element affine parameters
          initialized to ones (for weights) and zeros (for biases).

    Example:
    >>> x = torch.randn(5, 10, 20)
    >>> GLN = GlobalLayerNorm(10, 3)
    >>> x_norm = GLN(x)
    """

    def __init__(self, dim, shape, eps=1e-8, elementwise_affine=True):
        super(GlobalLayerNorm, self).__init__()
        self.dim = dim
        self.eps = eps
        self.elementwise_affine = elementwise_affine

        if self.elementwise_affine:
            if shape == 3:
                self.weight = nn.Parameter(torch.ones(self.dim, 1))
                self.bias = nn.Parameter(torch.zeros(self.dim, 1))
            if shape == 4:
                self.weight = nn.Parameter(torch.ones(self.dim, 1, 1))
                self.bias = nn.Parameter(torch.zeros(self.dim, 1, 1))
        else:
            self.register_parameter('weight', None)
            self.register_parameter('bias', None)

    def forward(self, x):
        """Returns the normalized tensor.

        Args:
            x : torch.Tensor
                Tensor of size [N, C, K, S] or [N, C, L].
        """
        # x = N x C x K x S or N x C x L
        # N x 1 x 1
        # cln: mean,var N x 1 x K x S
        # gln: mean,var N x 1 x 1
        if x.dim() == 3:
            mean = torch.mean(x, (1, 2), keepdim=True)
            var = torch.mean((x - mean)**2, (1, 2), keepdim=True)
            if self.elementwise_affine:
                # yapf: disable
                x = (self.weight * (x - mean) / torch.sqrt(var + self.eps)
                     + self.bias)
                # yapf: enable
            else:
                x = (x - mean) / torch.sqrt(var + self.eps)

        if x.dim() == 4:
            mean = torch.mean(x, (1, 2, 3), keepdim=True)
            var = torch.mean((x - mean)**2, (1, 2, 3), keepdim=True)
            if self.elementwise_affine:
                # yapf: disable
                x = (self.weight * (x - mean) / torch.sqrt(var + self.eps)
                     + self.bias)
                # yapf: enable
            else:
                x = (x - mean) / torch.sqrt(var + self.eps)
        return x

class CumulativeLayerNorm(nn.LayerNorm):
    """Calculate Cumulative Layer Normalization.

    Args:
       dim : int
        Dimension that you want to normalize.
       elementwise_affine : True
        Learnable per-element affine parameters.

    Example
    -------
    >>> x = torch.randn(5, 10, 20)
    >>> CLN = CumulativeLayerNorm(10)
    >>> x_norm = CLN(x)
    """

    def __init__(self, dim, elementwise_affine=True):
        super(CumulativeLayerNorm, self).__init__(
            dim, elementwise_affine=elementwise_affine, eps=1e-8)

    def forward(self, x):
        """Returns the normalized tensor.

        Arguments
        ---------
        x : torch.Tensor
            Tensor size [N, C, K, S] or [N, C, L]
        """
        # x: N x C x K x S or N x C x L
        # N x K x S x C
        if x.dim() == 4:
            x = x.permute(0, 2, 3, 1).contiguous()
            # N x K x S x C == only channel norm
            x = super().forward(x)
            # N x C x K x S
            x = x.permute(0, 3, 1, 2).contiguous()
        if x.dim() == 3:
            x = torch.transpose(x, 1, 2)
            # N x L x C == only channel norm
            x = super().forward(x)
            # N x C x L
            x = torch.transpose(x, 1, 2)
        return x

def select_norm(norm, dim, shape):
    """Just a wrapper to select the normalization type.
    """

    if norm == 'gln':
        return GlobalLayerNorm(dim, shape, elementwise_affine=True)
    if norm == 'cln':
        return CumulativeLayerNorm(dim, elementwise_affine=True)
    if norm == 'ln':
        return nn.GroupNorm(1, dim, eps=1e-8)
    else:
        return nn.BatchNorm1d(dim)

class Encoder(nn.Module):
    """Convolutional Encoder Layer.

    Args:
        kernel_size : int
            Length of filters.
        in_channels : int
            Number of  input channels.
        out_channels : int
            Number of output channels.

    Example:
    >>> x = torch.randn(2, 1000)
    >>> encoder = Encoder(kernel_size=4, out_channels=64)
    >>> h = encoder(x)
    >>> h.shape
    torch.Size([2, 64, 499])
    """

    def __init__(self, kernel_size=2, out_channels=64, in_channels=1):
        super(Encoder, self).__init__()
        self.conv1d = nn.Conv1d(
            in_channels=in_channels,
            out_channels=out_channels,
            kernel_size=kernel_size,
            stride=kernel_size // 2,
            groups=1,
            bias=False,
        )
        self.in_channels = in_channels

    def forward(self, x):
        """Return the encoded output.

        Args:
            x : torch.Tensor
                Input tensor with dimensionality [B, L].

        Returns:
            x : torch.Tensor
                Encoded tensor with dimensionality [B, N, T_out].
                where B = Batchsize
                      L = Number of timepoints
                      N = Number of filters
                      T_out = Number of timepoints at the output of the encoder
        """
        # B x L -> B x 1 x L
        if self.in_channels == 1:
            x = torch.unsqueeze(x, dim=1)
        # B x 1 x L -> B x N x T_out
        x = self.conv1d(x)
        x = F.relu(x)

        return x

class Decoder(nn.ConvTranspose1d):
    """A decoder layer that consists of ConvTranspose1d.

    Args:
    kernel_size : int
        Length of filters.
    in_channels : int
        Number of  input channels.
    out_channels : int
        Number of output channels.

    Example:
    ---------
    >>> x = torch.randn(2, 100, 1000)
    >>> decoder = Decoder(kernel_size=4, in_channels=100, out_channels=1)
    >>> h = decoder(x)
    >>> h.shape
    torch.Size([2, 1003])
    """

    def __init__(self, *args, **kwargs):
        super(Decoder, self).__init__(*args, **kwargs)

    def forward(self, x):
        """Return the decoded output.

        Args:
            x : torch.Tensor
                Input tensor with dimensionality [B, N, L].
                    where, B = Batchsize,
                           N = number of filters
                           L = time points
        """

        if x.dim() not in [2, 3]:
            raise RuntimeError('{} accept 3/4D tensor as input'.format(
                self.__name__))
        x = super().forward(x if x.dim() == 3 else torch.unsqueeze(x, 1))

        if torch.squeeze(x).dim() == 1:
            x = torch.squeeze(x, dim=1)
        else:
            x = torch.squeeze(x)
        return x

class MossFormerM(nn.Module):
    """This class implements the transformer encoder.

    Args:
        num_blocks : int
            Number of mossformer blocks to include.
        d_model : int
            The dimension of the input embedding.
        attn_dropout : float
            Dropout for the self-attention (Optional).
        group_size: int
            the chunk size
        query_key_dim: int
            the attention vector dimension
        expansion_factor: int
            the expansion factor for the linear projection in conv module
        causal: bool
            true for causal / false for non causal

    Example:
    -------
    >>> import torch
    >>> x = torch.rand((8, 60, 512))
    >>> net = TransformerEncoder_MossFormerM(num_blocks=8, d_model=512)
    >>> output, _ = net(x)
    >>> output.shape
    torch.Size([8, 60, 512])
    """

    def __init__(self,
                 num_blocks,
                 d_model=None,
                 causal=False,
                 group_size=256,
                 query_key_dim=128,
                 expansion_factor=4.,
                 attn_dropout=0.1):
        super().__init__()

        self.mossformerM = MossformerBlockGFSMN(
            dim=d_model,
            depth=num_blocks,
            group_size=group_size,
            query_key_dim=query_key_dim,
            expansion_factor=expansion_factor,
            causal=causal,
            attn_dropout=attn_dropout)
        self.norm = nn.LayerNorm(d_model, eps=1e-6)

    def forward(self, src):
        """
        Args:
            src : torch.Tensor
                Tensor shape [B, L, N],
                where, B = Batchsize,
                       L = time points
                       N = number of filters
                The sequence to the encoder layer (required).
        """
        output = self.mossformerM(src)
        output = self.norm(output)

        return output

class ComputationBlock(nn.Module):
    """Computation block for dual-path processing.

    Args:
        num_blocks : int
            Number of mossformer blocks to include.
         out_channels : int
            Dimensionality of inter/intra model.
         norm : str
            Normalization type.
         skip_around_intra : bool
            Skip connection around the intra layer.

    Example:
    ---------
        >>> comp_block = ComputationBlock(64)
        >>> x = torch.randn(10, 64, 100)
        >>> x = comp_block(x)
        >>> x.shape
        torch.Size([10, 64, 100])
    """

    def __init__(
        self,
        num_blocks,
        out_channels,
        norm='ln',
        skip_around_intra=True,
    ):
        super(ComputationBlock, self).__init__()

        # MossFormer+: MossFormer with recurrence
        self.intra_mdl = MossFormerM(
            num_blocks=num_blocks, d_model=out_channels)
        self.skip_around_intra = skip_around_intra

        # Norm
        self.norm = norm
        if norm is not None:
            self.intra_norm = select_norm(norm, out_channels, 3)

    def forward(self, x):
        """Returns the output tensor.

        Args:
            x : torch.Tensor
                Input tensor of dimension [B, N, S].

        Returns:
            out: torch.Tensor
                Output tensor of dimension [B, N, S].
                where, B = Batchsize,
                   N = number of filters
                   S = sequence time index
        """
        B, N, S = x.shape
        # intra RNN
        # [B, S, N]
        intra = x.permute(0, 2, 1).contiguous()

        intra = self.intra_mdl(intra)

        # [B, N, S]
        intra = intra.permute(0, 2, 1).contiguous()
        if self.norm is not None:
            intra = self.intra_norm(intra)

        # [B, N, S]
        if self.skip_around_intra:
            intra = intra + x

        out = intra
        return out

class MossFormerMaskNet(nn.Module):
    """The dual path model which is the basis for dualpathrnn, sepformer, dptnet.

    Args:
        in_channels : int
            Number of channels at the output of the encoder.
        out_channels : int
            Number of channels that would be inputted to the intra and inter blocks.
        norm : str
            Normalization type.
        num_spks : int
            Number of sources (speakers).
        skip_around_intra : bool
            Skip connection around intra.
        use_global_pos_enc : bool
            Global positional encodings.
        max_length : int
            Maximum sequence length.

    Example:
    ---------
    >>> mossformer_block = MossFormerM(1, 64, 8)
    >>> mossformer_masknet = MossFormerMaskNet(64, 64, intra_block, num_spks=2)
    >>> x = torch.randn(10, 64, 2000)
    >>> x = mossformer_masknet(x)
    >>> x.shape
    torch.Size([2, 10, 64, 2000])
    """

    def __init__(
        self,
        in_channels,
        out_channels,
        num_blocks=24,
        norm='ln',
        num_spks=2,
        skip_around_intra=True,
        use_global_pos_enc=True,
        max_length=20000,
    ):
        super(MossFormerMaskNet, self).__init__()
        self.num_spks = num_spks
        self.num_blocks = num_blocks
        self.norm = select_norm(norm, in_channels, 3)
        self.conv1d_encoder = nn.Conv1d(
            in_channels, out_channels, 1, bias=False)
        self.use_global_pos_enc = use_global_pos_enc

        if self.use_global_pos_enc:
            self.pos_enc = ScaledSinuEmbedding(out_channels)

        self.mdl = ComputationBlock(
            num_blocks,
            out_channels,
            norm,
            skip_around_intra=skip_around_intra,
        )

        self.conv1d_out = nn.Conv1d(
            out_channels, out_channels * num_spks, kernel_size=1)
        self.conv1_decoder = nn.Conv1d(
            out_channels, in_channels, 1, bias=False)
        self.prelu = nn.PReLU()
        self.activation = nn.ReLU()
        # gated output layer
        self.output = nn.Sequential(
            nn.Conv1d(out_channels, out_channels, 1), nn.Tanh())
        self.output_gate = nn.Sequential(
            nn.Conv1d(out_channels, out_channels, 1), nn.Sigmoid())

    def forward(self, x):
        """Returns the output tensor.

        Args:
            x : torch.Tensor
                Input tensor of dimension [B, N, S].

        Returns:
            out : torch.Tensor
                Output tensor of dimension [spks, B, N, S]
                where, spks = Number of speakers
                   B = Batchsize,
                   N = number of filters
                   S = the number of time frames
        """
        # before each line we indicate the shape after executing the line
        # [B, N, L]
        x = self.norm(x)

        # [B, N, L]
        x = self.conv1d_encoder(x)
        if self.use_global_pos_enc:
            base = x
            x = x.transpose(1, -1)
            emb = self.pos_enc(x)
            emb = emb.transpose(0, -1)
            x = base + emb

        # [B, N, S]
        x = self.mdl(x)
        x = self.prelu(x)

        # [B, N*spks, S]
        x = self.conv1d_out(x)
        B, _, S = x.shape

        # [B*spks, N, S]
        x = x.view(B * self.num_spks, -1, S)

        # [B*spks, N, S]
        x = self.output(x) * self.output_gate(x)

        # [B*spks, N, S]
        x = self.conv1_decoder(x)

        # [B, spks, N, S]
        _, N, L = x.shape
        x = x.view(B, self.num_spks, N, L)
        x = self.activation(x)

        # [spks, B, N, S]
        x = x.transpose(0, 1)

        return x

@MODELS.register_module(
    Tasks.speech_separation,
    module_name=Models.speech_mossformer2_separation_temporal_8k)
class MossFormer2(TorchModel):
    """Library to support MossFormer speech separation.

    Args:
        model_dir (str): the model path.
    """

    def __init__(self,
                 model_dir: str,
                 in_channels=512,
                 out_channels=512,
                 num_blocks=24,
                 kernel_size=16,
                 norm='ln',
                 num_spks=2,
                 skip_around_intra=True,
                 use_global_pos_enc=True,
                 max_length=20000,
                 *args,
                 **kwargs):
        super().__init__(model_dir, *args, **kwargs)
        self.num_spks = num_spks
        self.enc = Encoder(
            kernel_size=kernel_size, out_channels=in_channels, in_channels=1)
        self.mask_net = MossFormerMaskNet(
            in_channels=in_channels,
            out_channels=out_channels,
            num_blocks=num_blocks,
            norm=norm,
            num_spks=num_spks,
            skip_around_intra=skip_around_intra,
            use_global_pos_enc=use_global_pos_enc,
            max_length=max_length,
        )
        self.dec = Decoder(
            in_channels=out_channels,
            out_channels=1,
            kernel_size=kernel_size,
            stride=kernel_size // 2,
            bias=False)

    def forward(self, input):
        x = self.enc(input)
        mask = self.mask_net(x)
        x = torch.stack([x] * self.num_spks)
        sep_x = x * mask

        # Decoding
        est_source = torch.cat(
            [self.dec(sep_x[i]).unsqueeze(-1) for i in range(self.num_spks)],
            dim=-1,
        )
        T_origin = input.size(1)
        T_est = est_source.size(1)
        if T_origin > T_est:
            est_source = F.pad(est_source, (0, 0, 0, T_origin - T_est))
        else:
            est_source = est_source[:, :T_origin, :]
        return est_source

    def load_check_point(self, load_path=None, device=None):
        if not load_path:
            load_path = self.model_dir
        if not device:
            device = torch.device('cpu')
        self.load_state_dict(
            torch.load(
                os.path.join(load_path, ModelFile.TORCH_MODEL_FILE),
                map_location=device),
            strict=False)


from django.contrib import admin
from django.urls import path, include
import post.views

urlpatterns = [
    path('', post.views.home, name = "home"),
    path('admin/', admin.site.urls),
	path('account/', include('account.urls')),
    path('post/', include('post.urls')),
    path('comment/', include('comment.urls')),
]


from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required
from jogos import bp
from jogos.forms import NovoJogoForm
from models import Jogo, Time
from brasileirao import db
from sqlalchemy.exc import IntegrityError

@bp.route('/')
@login_required
def index():
    jogos = Jogo.jogos_rodada()
    return render_template('listarjogos.html', title='Jogos', jogos=jogos)

@bp.route('/new', methods=['GET', 'POST'])
@login_required
def create():
    form = NovoJogoForm()
    times = list(Time.query.with_entities(Time.id, Time.nome))
    form.mandante.choices = times
    form.visitante.choices = times
    if form.validate_on_submit():
        jogo = Jogo(rodada=form.rodada.data, data=form.data.data,
                    time_mandante_id=form.mandante.data,
                    gols_mandante=form.gols_mandante.data,
                    amarelos_mandante=form.amarelos_mandante.data,
                    vermelhos_mandante=form.vermelhos_mandante.data,
                    time_visitante_id=form.visitante.data,
                    gols_visitante=form.gols_visitante.data,
                    amarelos_visitante=form.amarelos_visitante.data,
                    vermelhos_visitante=form.vermelhos_visitante.data)
        try:
            db.session.add(jogo)
            db.session.commit()
        except IntegrityError:
            db.session.rollback()
            e = {'Duplicidade': ["Esta partida já ocorrreu"]}
            return render_template('novojogo.html', title='Novo Jogo',
                                   form=form, jogo=None, errors=e)
        else:
            return redirect(url_for('jogos.index'))
    return render_template('novojogo.html', title='Novo Jogo', form=form,
                           jogo=None, errors=form.errors)

@bp.route('/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def update(id):
    jogo = Jogo.query.get_or_404(id)
    form = NovoJogoForm()
    times = list(Time.query.with_entities(Time.id, Time.nome))
    form.mandante.choices = times
    form.visitante.choices = times
    if form.validate_on_submit():
        jogo.rodada = form.rodada.data
        jogo.data = form.data.data
        jogo.time_mandante_id = form.mandante.data
        jogo.gols_mandante = form.gols_mandante.data
        jogo.amarelos_mandante = form.amarelos_mandante.data
        jogo.vermelhos_mandante = form.vermelhos_mandante.data
        jogo.time_visitante_id = form.visitante.data
        jogo.gols_visitante = form.gols_visitante.data
        jogo.amarelos_visitante = form.amarelos_visitante.data
        jogo.vermelhos_visitante = form.vermelhos_visitante.data
        db.session.add(jogo)
        db.session.commit()
        flash('As alterações foram atualizadas com sucesso.')
        return redirect(url_for('jogos.index'))
    elif request.method == 'GET':
        form.rodada.data = jogo.rodada
        form.data.data = jogo.data
        form.mandante.data = jogo.time_mandante_id
        form.gols_mandante.data = jogo.gols_mandante
        form.amarelos_mandante.data = jogo.amarelos_mandante
        form.vermelhos_mandante.data = jogo.vermelhos_mandante
        form.visitante.data = jogo.time_visitante_id
        form.gols_visitante.data = jogo.gols_visitante
        form.amarelos_visitante.data = jogo.amarelos_visitante
        form.vermelhos_visitante.data = jogo.vermelhos_visitante
    return render_template('novojogo.html', form=form, title="Editar Jogo",
                           jogo=jogo, errors=form.errors)

@bp.route('/<int:id>/delete')
@login_required
def delete(id):
    jogo = Jogo.query.get_or_404(id)
    db.session.delete(jogo)
    db.session.commit()
    return redirect(url_for('jogos.index'))


import pandas as pd

#原路径和保存路径，可以根据自己要求修改
readpath = 'E:/grep/LX/len.txt'
savepath = 'E:/grep/LX/xue.txt'

pd.set_option('expand_frame_repr', False)
data = pd.read_csv(readpath, sep='\t')
for i in range(1,len(data)+1):
    data['sku'].loc[i-1] = data['sku'].loc[i-1] + '-' + str(i)
data.to_csv(savepath,sep = '\t', index=False)
print(data)


from django.urls import path
from . import views

urlpatterns = [
    path('accounts/login/', views.sign_in, name='sign_in'),
    path('create_account', views.create_account, name='create_account'),
    path('', views.home, name='index'),
    path('export_salesreport', views.export_salesreport, name='export_salesreport'),
    path('logout', views.logout_view, name='logout'),
]


# DP + Binary Searchclass Solution:
class Solution:
    def maximizeWin(self, prizePositions: List[int], k: int) -> int:
        n = len(prizePositions)
        dp = [0] * (n + 1) # dp[i]: the maximum number of covered prize for prizePositions[i:]

        res = 0
        for i in range(n - 1, -1, -1):
            j = bisect.bisect_right(prizePositions, prizePositions[i] + k)
            dist = j - i
            res = max(res, dist+dp[j]) # dist is maximum number of prize for [i:j),  dp[j] covered [j:]
            dp[i] = max(dist, dp[i + 1])
        return res

# DP + Sliding Window
class Solution:
    def maximizeWin(self, positions: List[int], k: int) -> int:
        n = len(positions)
        dp = [0] * (n+1)

        res = l = r = 0
        while r < n:
            num = positions[r]
            r += 1

            while l < r and num-positions[l] > k:
                l += 1

            dp[r] = max(dp[r-1], r-l)
            res = max(res, r-l + dp[l])
        return res

# 3-Pass
# 遍歷一個分界點，找出分界點左邊最大區間及分界點右邊最大區間
# 遍歷全部後找最大區間即可
# 有個算是Greedy的思想是，這兩個區間當然不重合才是最好的，所以是`pre[k]+post[k+1]`
class Solution:
    def maximizeWin(self, positions: List[int], k: int) -> int:
        n = len(positions)
        if positions[-1]-positions[0] <= 2*k: return n

        pre = [0] * n
        post = [0] * n

        res = l = r = 0
        while r < n:
            num = positions[r]
            r += 1
            while l < r and num-positions[l] > k:
                l += 1
            res = max(res, r-l)
            pre[r-1] = res

        l = r = n-1
        res = 0
        while l >= 0:
            num = positions[l]
            l -= 1

            while l < r and positions[r]-num > k:
                r -= 1
            res = max(res, r-l)
            post[l+1] = res

        res = 0
        for k in range(n-1):
            res = max(res, pre[k] + post[k+1])
        return res

1-D Dynamic Programming/3Pass/2555. Maximize Win From Two Segments/solution.py


"""
Module for handling user-related routes in the admin panel.
"""

from flask import redirect, url_for
from flask_admin import BaseView, expose

from website.decorators import admin_login_required
from website.admin.views.users import users_page, remove_user

class Users(BaseView):
    @expose("/")
    @admin_login_required
    def index(self):
        """
        Display a list of users.

        Returns:
            str: Rendered HTML content.
        """
        users = users_page()

        return self.render("admin/users.html", users=users)

    @expose("/delete_user/<int:user_id>", methods=["POST"])
    @admin_login_required
    def delete_user(self, user_id):
        """
        Delete a user.

        Keyword arguments:
            user_id (int): The ID of the user to be deleted.

        Returns:
            str: Redirect URL.
        """
        remove_user(user_id)

        return redirect(url_for("users.index"))


class Solution:
    def minDeletions(self, s: str) -> int:
        freqMap = {i: 0 for i in s}
        maxFreq = 0
        for i in s:
            freqMap[i] += 1
            maxFreq = max(maxFreq, freqMap[i])

        freqs = [0] * (maxFreq + 1)
        for i in freqMap:
            freqs[freqMap[i]] += 1

        freqs.reverse()
        freqs.pop()
        carry = 0
        dels = 0

        for i in range(len(freqs)):
            freqs[i] += carry
            carry = freqs[i] - 1 if freqs[i] else 0
            dels += carry
            if not freqs[i] and carry:
                carry -= 1
        return dels


from itertools import combinations
'''
FEP is the Fragile Exchange Property
I learned about this in Discrete Math 1
my Freshman year of college.
After finishing this project for
extra credit, I was still looking into
this topic and found out that it is
actually called Matroid Theory, and
the prof made up FEP so that we couldn't
go to google for answers...
'''

k = 3
n = 2

comb = list(map(set, combinations(range(1, k + 1), n)))
sets = []
for i in range(len(comb) + 1):
    sets += (list(map(list, combinations(comb, i))))

def checkFEP(A, B, C):
    for a in A:
        for b in B:
            if (b in A) or (a in B):
                continue
            test = A.difference(set([a])).union(set([b]))
            if test in C:
                return True
    return False

def checkFEPTotal(C):
    for A in C:
        for B in C:
            if not B == A:
                test = checkFEP(A, B, C)
                if not test:
                    return False
    return True

FEPSets = list(filter(checkFEPTotal, sets))
print(FEPSets)

def checkMaximalFEP(C):
    for add in comb:
        if add in C:
            continue
        for A in C:
            test1 = checkFEPTotal(A, add, C)
            test2 = checkFEPTotal(add, A, C)
            if (not test1) or (not test2):
                break
            return False
    return True

def findMaximalFEP():
    for C in FEPSets:
        doesCWork = checkMaximalFEP(C)
        if doesCWork:
            return C
        if not doesCWork:
            print("FEP always works")

findMaximalFEP()


from tkinter import Toplevel
import cv2
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
import imutils
protopath = "MobileNetSSD_deploy.prototxt"
modelpath = "MobileNetSSD_deploy.caffemodel"
#caffe = Convolution Architecture for Fast Feature Embedding used for creating image clasfication and alsoimage segementation models
detector = cv2.dnn.readNetFromCaffe(prototxt=protopath, caffeModel=modelpath)
#load the model from disk and since we are using caffe model
#prototxt = this include network layers model contain,each layer parameters ie name,type,input dimension ad output dimensions and also specificaton for connection between layers
#caffemodel =contains weights of the model (weight = are parameters within a NN that transform input data within the netwotk hidden layers)

CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
           "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
           "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
           "sofa", "train", "tvmonitor"]

idx = 0

def PIL_img2CV_img(PILimg):
    CVimg = cv2.cvtColor(np.asarray(PILimg), cv2.COLOR_RGB2BGR)
    return CVimg

def CV_img2PIL_img(CVimg):
    PILimg = Image.fromarray(cv2.cvtColor(CVimg, cv2.COLOR_BGR2RGB))
    return PILimg

def greyscale(PIL_img):
    if CLASSES[idx]=='person':
        PIL_img = detectedImage(PIL_img)
        CV_img = PIL_img2CV_img(PIL_img)
        CV_gray = cv2.cvtColor(CV_img, cv2.COLOR_BGR2GRAY)

        return CV_img2PIL_img(CV_gray)

def edge_detect(PIL_img):
    if CLASSES[idx]=='person':
        PIL_img = detectedImage(PIL_img)
        CV_img = PIL_img2CV_img(PIL_img)
        CV_gray = cv2.cvtColor(CV_img, cv2.COLOR_BGR2GRAY)

        CV_detected = cv2.Canny(CV_gray, 100, 300)
        return CV_img2PIL_img(cv2.cvtColor(CV_detected, cv2.COLOR_GRAY2BGR))

def detectedImage(PIL_img):

    image = PIL_img2CV_img(PIL_img)

    image = imutils.resize(image, width=600)

    (H, W) = image.shape[:2]

    #dnn - deep neural network
    #blob perform function
      #1. image substraction
      #2. scalling
      #3. And Optionally channel swapping
    blob = cv2.dnn.blobFromImage(image, 1/255, (W, H),(0,0,0),True,crop=False)
    #image = input image want to process before passing it through our deeep neural network for classfiation
    #scalefactor =scale the image by some factor,basically multiplies(scales) the image channels. it scales it down by factor of 1/n
    #where n is the scalefactor you provide 255
    #where normally our input model we scalled down the image pixel values between 0-1 instead of 0-255
    # how much an image size is reduced at each image scale)
    #Size - target size that we want our image to become = (H,W)
    #mean - mean substraction value
    #swapRB - opencv by default read an image iBGR format but the mean always takes argument in RGB
    # for b in blob:
    #     for n,img_blog in enumerate(b):
    #         cv2.imshow(str(n),img_blog)

    detector.setInput(blob) #pass blog into the algorithm
    person_detections = detector.forward()  #contain all dectection from model files
    #generate prediction where it return a 4-dimension list
    #the 3rd dimension is our predictions, and each prediction is a list of 7 floating values, At 1 index we have class_id
    #2=confidence/probability
    # 3-6 coordinate of object detected

    for i in np.arange(0, person_detections.shape[2]): #iterate all over thedetection
        confidence = person_detections[0, 0, i, 2]   #confidence is found at index 2

        if confidence > 0.5:
            global idx
            idx = int(person_detections[0, 0, i, 1]) #confidence is found at index 1

            if CLASSES[idx] != "person":
                continue

            person_box = person_detections[0, 0, i, 3:7] * np.array([W, H, W, H]) #coordinates are found at index 3-6, scale the coordinate to our scale image
            (startX, startY, endX, endY) = person_box.astype("int") #calculate the person boundng box

            cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) #draw rectange with (BGR) with red color with 2 thickness

    blue,green,red = cv2.split(image)
    img = cv2.merge((red,green,blue))
    img = Image.fromarray(img)

    return img

def blur(PIL_img):
    if CLASSES[idx]=='person':
        PIL_img = detectedImage(PIL_img)
        image = PIL_img2CV_img(PIL_img)

        img=cv2.blur(image,(50,50))
        blue,green,red = cv2.split(img)
        img = cv2.merge((red,green,blue))
        img = Image.fromarray(img)

        return img


# -*- coding: utf-8 -*-
"""Module providing a json data storage api for categories"""
from builtins import str
from builtins import object
import datetime
import json
import time
import uuid as uuid_tool
from Products.CMFPlone.utils import safe_unicode
from collective.beaker.interfaces import ISession
from plone import api
from plone.memoize.view import memoize
from zope.globalrequest import getRequest
from zope.lifecycleevent import modified

class TaxonomyTool(object):
    """ Factory providing CRUD operations for blog category management """

    def create(self, uuid, data=None):
        item = api.content.get(UID=uuid)
        start = time.time()
        initial_data = self._create_record(uuid, item, data)
        end = time.time()
        initial_data.update(dict(_runtime=str(end-start)))
        json_data = json.dumps(initial_data)
        api.portal.set_registry_record(
            'meetshaus.blog.interfaces.IBlogToolSettings.blog_categories',
            self.safe_unicode(json_data))
        return json_data

    # @memoize
    def read(self, uuid, key=None):
        records = api.portal.get_registry_record(
            'meetshaus.blog.interfaces.IBlogToolSettings.blog_categories')
        return json.loads(records)

    def update(self, uuid, data, key=None):
        stored = self.read(uuid)
        start = time.time()
        if key is not None:
            records = stored['items']
            records[key] = data
        else:
            records = data
        end = time.time()
        stored['items'] = records
        stored.update(dict(_runtime=str(end-start),
                           timestamp=str(int(time.time())),
                           updated=str(datetime.datetime.now())))
        updated = json.dumps(stored)
        api.portal.set_registry_record(
            'meetshaus.blog.interfaces.IBlogToolSettings.blog_categories',
            self.safe_unicode(updated))
        return uuid

    def delete(self, uuid, key=None):
        stored = self.read(uuid)
        if key is not None:
            stored[key] = dict()
            updated = json.dumps(stored)
            item = api.content.get(UID=uuid)
            setattr(item, 'moduleInformation', updated)
            modified(item)
            item.reindexObject(idxs='modified')
        return uuid

    def get_record(self, uuid):
        data = dict()
        stored_data = self.read(uuid)
        if stored_data:
            for item in stored_data['items']:
                if 'degree-course' in item:
                    course_identifier = item['degree-course']
                    try:
                        course_module = item['module']
                    except KeyError:
                        course_module = None
                    course_theme = None
                    if 'course-theme' in item:
                        course_theme = item['course-theme']
                    if course_identifier in data:
                        course_data = data[course_identifier]
                    else:
                        # Add empty dictionary if course identifier
                        # does not yet exist
                        course_data = {}
                    if course_module:
                        if course_module in course_data:
                            module_info = course_data[course_module]
                        else:
                            module_info = list()
                        if course_theme:
                            module_info.append(course_theme)
                        course_data[course_module] = module_info
                    data[course_identifier] = course_data
        return data

    def get_record_index(self, uuid):
        stored_data = self.get_record(uuid)
        storage_blacklist = ('degree', 'info', 'theme')
        data = list()
        for course_key, course_value in list(stored_data.items()):
            course_title = self.get_degree_course_title(course_key)
            course_name = str(course_title)
            if course_value:
                module_titles = list()
                for module_name, module_theme in list(course_value.items()):
                    module_name_rendered = self.get_learning_modules(
                        course_key,
                        module_name
                    )
                    module_title = module_name_rendered
                    module_titles.append(module_title)
                    if module_theme:
                        for theme in module_theme:
                            module_title_and_theme = '{0} ({1})'.format(
                                module_title,
                                theme
                            )
                            module_titles.append(module_title_and_theme)
                if module_titles:
                    for title in module_titles:
                        course_name_item = '{0}: {1}'.format(
                            course_name,
                            str(title.encode('utf-8'))
                        )
                        data.append(course_name_item)
            data.append(course_name)
        module_data = list(set(sorted(data)))
        return module_data

    def _create_record(self, uuid, item, data):
        records = {
            "id": str(uuid_tool.uuid4()),
            "uid": str(uuid),
            "timestamp": str(int(time.time())),
            "_runtime": "0.0000059604644775390625",
            "created": datetime.datetime.now().isoformat(),
            "title": item.Title(),
            "items": []
        }
        # Add potential initial data
        if data:
            records['items'].append(data)
        return records

    def safe_encode(self, value):
        """Return safe unicode version of value.
        """
        su = safe_unicode(value)
        return su.encode('utf-8')

class CategoryManagementTool(object):
    """ Category management session storage tool

        Store selected filter configuration inside anonymous session
        to provide dynamically constructed filter forms
    """

    @staticmethod
    def get(key=None):
        """ Create module filter session """
        portal = api.portal.get()
        session_id = 'meetshaus.blog.category.{0}'.format(
            '.'.join(portal.getPhysicalPath())
        )
        if key:
            session_id = 'meetshaus.blog.category.{0}'.format(key)
        session = ISession(getRequest())
        if session_id not in session:
            session[session_id] = dict()
            session.save()
        return session[session_id]

    @staticmethod
    def destroy(key=None):
        """ Destroy module filter session """
        portal = api.portal.get()
        session_id = 'meetshaus.blog.category.{0}'.format(
            '.'.join(portal.getPhysicalPath())
        )
        if key:
            session_id = 'meetshaus.blog.category.{0}'.format(key)
        session = ISession(getRequest())
        if session_id in session:
            del session[session_id]
            session.save()

    def add(self, key, data=None):
        """
            Add item to survey session
        """
        records = self.get()
        record = self.update(key, data)
        if not record:
            records[key] = data
            return records[key]

    def update(self, key, data):
        records = self.get()
        record_id = key
        if record_id in records:
            records[record_id] = data
            return records[record_id]
        return None

    def remove(self, key):
        records = self.get()
        if key in records:
            del records[key]
            return key

    @staticmethod
    def create_record(token, data):
        records = {
            "id": str(uuid_tool.uuid4()),
            "timestamp": str(int(time.time())),
            "_runtime": "0.00000000000000000001",
            "created": datetime.datetime.now().isoformat(),
            "token": token,
            "filter": dict()
        }
        # Add potential initial data
        if data:
            records['filter'] = data
        return records

class CourseFilterUpdater(object):
    """ Factory providing CRUD operations for course module filters """
    @staticmethod
    def _create_record(data):
        records = {
            "id": str(uuid_tool.uuid4()),
            "timestamp": str(int(time.time())),
            "_runtime": "0.00000000000000000001",
            "created": datetime.datetime.now().isoformat(),
            "filter": dict()
        }
        # Add potential initial data
        if data:
            records['filter'].append(data)
        return records


import json
import csv
import os.path

months = ["01", "02", "03", "04",
          "05", "06", "07", "08",
          "09", "10", "11", "12"]

# top5 avg AQI, AQI, CO, Ozone, SO2, PM10, PM2.5, NO2

fields = ['Overall AQI Value', 'CO', 'Ozone', 'SO2', 'PM10', 'PM25', 'NO2']

COUNTY_FIPS = []
f = open("../fire_data/st06_ca_cou.txt", "r")
for line in f:
    code = line.strip().split(',')
    COUNTY_FIPS.append(code[2])

def process():
    daily_objects = {}
    for year in range(2009, 2019):
        for month in months:
            time = str(year) + month
            daily_objects[time] = {}
            for county_id in COUNTY_FIPS:
                daily_objects[time][county_id] = {}
                for field in fields:
                    field_cnt = '{}_cnt'.format(field)
                    daily_objects[time][county_id][field] = []
                    # daily_objects[time][county_id][field_cnt] = 0
    for year in range(2009, 2019):
        for county_id in COUNTY_FIPS:
            read(daily_objects, year, county_id)

    file_path = '../AQI_data/daily_objects.json'
    with open(file_path, 'w') as outfile:
        json.dump(daily_objects, outfile, indent=2)

def read(daily_objects, year, county_id):
    file_path = "../AQI_data/AQI_for_county/{}/{}_{}.csv".format(year, year, county_id)
    if not os.path.exists(file_path):
        print("no data for this county: {} in {}".format(county_id, year))
        return
    reader = csv.DictReader(open(file_path))

    for row in reader:
        month = row['Date'].split('/')[0]
        time = str(year) + month
        for field in fields:
            field_cnt = '{}_cnt'.format(field)
            index = row.get(field, None)
            if index is not None and index != '.':
                daily_objects[time][county_id][field].append(int(index))
                # daily_objects[time][county_id][field_cnt] += 1

def test(year, county_id):
    file_path = "../AQI_data/AQI_for_county/{}/{}_{}.csv".format(year, year, county_id)
    if not os.path.exists(file_path):
        print("no data for this county: {} in {}".format(county_id, year))
        return
    reader = csv.DictReader(open(file_path))

    for row in reader:
        month = row['Date'].split('/')[0]
        print(row['Date'])
        if row['Overall AQI Value']:
            AQI = int(row['Overall AQI Value'])
            print("AQI: {}".format(AQI))
            for pollutant in fields:
                index = row.get(pollutant, None)
                if index is not None:
                    print("{}: {}".format(pollutant, index))

def calculate():
    final_objects = {}
    file_path = '../AQI_data/daily_objects.json'
    with open(file_path) as f:
        daily_objects = json.load(f)
    for year in range(2009, 2019):
        for month in months:
            time = str(year) + month
            final_objects[time] = {}
            for county_id in COUNTY_FIPS:
                final_objects[time][county_id] = []
                if len(daily_objects[time][county_id][fields[0]]) == 0:
                    final_objects[time][county_id].append(-1)
                else:
                    num = 5
                    top = sorted(daily_objects[time][county_id][fields[0]], reverse=True)[:num]
                    final_objects[time][county_id].append(int(sum(top) / len(top)))
                for field in fields:
                    # field_cnt = '{}_cnt'.format(field)
                    field_cnt = len(daily_objects[time][county_id][field])
                    if field_cnt == 0:
                        final_objects[time][county_id].append(-1)
                    else:
                        value = sum(daily_objects[time][county_id][field]) / field_cnt
                        final_objects[time][county_id].append(int(value))

    file_path = '../AQI_data/AQI_for_county.json'
    with open(file_path, 'w') as outfile:
        json.dump(final_objects, outfile, indent=2)

if __name__ == '__main__':
    #process()
    calculate()


#Akinola Daramola Jr
#Programming Exercise 6.7
#Due Date: 07/27/2022

"""
Random Number File Writer
Write a program that writes a series of random numbers to a file.
Each random number should be in the range of 1 through 500.
The application should let the user specify how many random numbers the file will hold.

"""

#Import random library
import random

#Defining mainline() function to run numberGenerator() function
def main():
    #Invoking numberGenerator() function
    numberGenerator()

#Defining numberGenerator() function
def numberGenerator():
        #try block to test for errors
        try:
            #Initializing value of number_count variable
            number_count= 0
            #Specifying amount of numbers file can hold
            specified = int(input("How many numbers will this file contain? "))

            #Iterating through range of numbers specified
            for numbers in range(specified):

                #Setting range of random number
                random_number = random.randint(1,501)

                #Number count increments 1 unit for ever random number generated
                number_count += 1

                #Displays number of random numbers generated between 1 - 500
                print(str(f"{number_count}. {random_number}"))

                #Declaring value of file as open("write_file.txt", "a")
                file = open("write_file.txt", "a")

                #Keeps count of random numbers specified
                number = file.write(str(number_count))

                #Adds dot for number list formatting - example (1. 33) (10. 47) (100. 88)
                dot = file.write(". ")

                #Declaring value of each line in file
                numbers = file.write(str(random_number))

                #Adding line break to each iteration of random number generated
                newline = file.write("\n")

                #Closing file
                file.close()

        #Specifying file name and extention type of errors
        except IOError:

            #Display message associated with error type
            print("Error: File does not exist")

        #Specifying value entry errors
        except ValueError:

            #Display message associated with error type
            print('Error: Invalid entry, please enter a number!')

        #Runs to determine if code was executed
        finally:
            #Display program status message
            print("Program finished executing")

#Invoking main() function to start program
main()


from menu import Menu, scan_input, menulayout
import mydisplay
from rainbowio import colorwheel
stopped = False

class MainMenu(Menu):

    entries = [
        menulayout.MenuEntry("2022", 0xFFFFFF,scale=2),
        menulayout.MenuEntry("05", 0xFF0000, scale=2),
        menulayout.MenuEntry("22", 0x00FF00,scale=2),
#        menulayout.MenuEntry("D", 0x0000FF),
#        menulayout.MenuEntry("E", 0xFFFF00),
#        menulayout.MenuEntry("F", 0x7FD000),
#        menulayout.MenuEntry("G", 0x00FFFF),
    ]

    def up(self):
        print("up")
        self.selected_index -= 1

    def down(self):
        print("down")
        self.selected_index += 1

    actions = {
        Menu.Inputs.up: up,
        Menu.Inputs.down: down
    }

    def default_action(self, inp):
        print("unknown input {}".format(inp))

    def __init__(self, target):
        cells = 3
        entries = []
        n=0
        for i in range(0,256,4):
            color = colorwheel(i)
            entries.append(menulayout.MenuEntry(hex(color), color,scale=2),)
            n += 1
        orientation = menulayout.MenuLayout.Orientation.VERTICAL
        super().__init__(target, "main", entries, actions=MainMenu.actions, default_action=self.default_action, orientation=orientation, display_entries=cells)

def run():
    global now
    global stopped
    inp = None
    column = 0
    main_menu = MainMenu(mydisplay.display)
    main_menu.show_menu()
    while not stopped:
        inp = scan_input()
        if inp is not None:
            main_menu.update(inp)

run()


# USAGE
# python blur_face.py --image examples/adrian.jpg --face face_detector --method simple
# python blur_face.py --image examples/adrian.jpg --face face_detector --method pixelated

# import the necessary packages
from pyimagesearch.face_blurring import anonymize_face_pixelate
from pyimagesearch.face_blurring import anonymize_face_simple
import numpy as np
import argparse
import cv2
import os

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
	help="path to input image")
ap.add_argument("-f", "--face", required=True,
	help="path to face detector model directory")
ap.add_argument("-m", "--method", type=str, default="simple",
	choices=["simple", "pixelated"],
	help="face blurring/anonymizing method")
ap.add_argument("-b", "--blocks", type=int, default=20,
	help="# of blocks for the pixelated blurring method")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
	help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

print("Confidence threshold: " + str(args["confidence"]))
# load our serialized face detector model from disk
print("[INFO] loading face detector model...")
prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"])
weightsPath = os.path.sep.join([args["face"],
	"res10_300x300_ssd_iter_140000.caffemodel"])
net = cv2.dnn.readNet(prototxtPath, weightsPath)

# load the input image from disk, clone it, and grab the image spatial
# dimensions
image = cv2.imread(args["image"])
orig = image.copy()
(h, w) = image.shape[:2]

# construct a blob from the image
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300),
	(104.0, 177.0, 123.0))

# pass the blob through the network and obtain the face detections
print("[INFO] computing face detections...")
net.setInput(blob)
detections = net.forward()

# loop over the detections
for i in range(0, detections.shape[2]):
	# extract the confidence (i.e., probability) associated with the
	# detection
	confidence = detections[0, 0, i, 2]

	# if a detection with a high enough confidence value is detected,
	# stop iterating and exit with code 0
	if confidence > args["confidence"]:
		exit(0)

# if there was no detection with a high enough confidence value
# exit with code 738
exit(738)


from astropy.time import Time
from astropy.coordinates import SkyCoord, CartesianRepresentation
import astropy.coordinates as coords
import astropy.units as u
import astropy.constants as const

from heliopy import spice
from heliopy.data import ace

import numpy as np
from scipy.io import readsav
import sunpy.map
import sunpy.coordinates.frames as sunframes
import sunpy.io.fits
import pfsspy

from datetime import datetime

ace_dates = (datetime(2013, 1, 13), datetime(2013, 1, 31))
rss = 2.3

def get_B_map():
    """
    Return the synoptic map used for the PFSS model.

    Returns
    -------
    sunpy.map.GenericMap
    """
    [[br, header]] = sunpy.io.fits.read('maps/mrzqs130120t0304c2132_015.fits')
    br = br - np.mean(br)
    br = np.roll(br, header['CRVAL1'], axis=1)
    br = np.roll(br, 180, axis=1)
    header['crval1'] = 180

    return sunpy.map.Map((br, header))

def get_aia_map():
    aia_disk = sunpy.map.Map('maps/AIA20130121_1206_0193.fits')
    aia = sunpy.map.Map('maps/carrington_aia.fits')
    aia.plot_settings = aia_disk.plot_settings
    # Rotate to get 0deg on the edge
    aia.meta['crval1'] = 180
    aia._data = np.roll(aia._data, aia._data.shape[1] // 2, 1)
    return aia

def get_gong_map():
    return read_gong_adapt('maps/adapt40311_03k012_201301200200_i00020100n1.fts', 0)

def read_gong_adapt(file, i):
    """
    Read in a single GONG-ADAPT map realisation.

    Parameters
    ----------
    file : path-like
        The .fits file to read.
    i : int
        The realisation number to read in. Must be between 0 and 11.

    Returns
    -------
    sunpy.map.GenericMap
    """
    file_data = sunpy.io.fits.read('maps/adapt40311_03k012_201301200200_i00020100n1.fts')
    [data, header] = file_data[0]
    data = data[i, ...]
    print(data.shape)
    data = np.roll(data, int(header['CRVAL1']), axis=1)
    m = sunpy.map.Map((data, header))
    # Fix some FITS entries...
    m.meta['date-obs'] = m.meta['maptime']
    m.meta['ctype1'] = 'CRLN-CEA'
    m.meta['ctype2'] = 'CRLT-CEA'
    m.meta.pop('naxis3')
    return m

def get_L1_flines():
    starttime = ace_dates[0]
    endtime = ace_dates[1]

    data = ace.swi_h3b(starttime, endtime)
    v_alpha = data.quantity('vHe2')

    B_map = get_B_map()

    flines, input, output = footpoints(data.index, v_alpha, B_map)
    return flines, input, output

def earth_trajectory(times):
    traj = spice.Trajectory('earth')
    traj.generate_positions(times, 'Sun', 'IAU_SUN')
    return traj

def project_to_ss(seeds, vsw, obstime):
    """
    Project a set of abitrary coordinates in the heliosphere on to the source
    surface.

    Parameters
    ----------
    seeds : astropy.coordinates.SkyCoord
        Seed points to be projected onto the source surface
    vsw : Quantity
        Solar wind velocity used to ballistically project backwards
    obstime : datetime
        Observation time of the map that the seeds will be traced through

    Returns
    -------
    seeds_ss : astropy.coordinates.SkyCoord
        Seed points projected on to the source surface.
    """
    seeds.representation_type = 'spherical'
    # Calculate the time it takes for the solar wind to travel radially to
    # the source surface
    dt =  (seeds.radius - rss * const.R_sun) / vsw
    # Construct the Carrington frame that existed when the plasma left th
    # source surface
    ss_frame = sunframes.HeliographicCarrington(obstime=seeds.obstime - dt)
    # Transform to this frame
    seeds_ss = seeds.transform_to(ss_frame)
    # Finally, set the radius to the source surface
    seeds_ss = SkyCoord(
        seeds_ss.lon,
        seeds_ss.lat,
        rss * 0.99 * const.R_sun,
        obstime = obstime,
        frame='heliographic_carrington')
    return seeds_ss

def trace_to_surface(seeds, synoptic_map, rss=rss, nrho=60):
    """
    seeds : astropy.coordinates.SkyCoord
        Seed coordinates on the source surface.
    synoptic_map : sunpy.map.GenericMap
        Input synoptic magnetogram.
    rss : scalar
        Source surface radius.
    nrho : int
        Number of grid points in the radial direciton
        of the PFSS model.

    Returns
    -------
    flines : pfsspy.flines.field_lines
        Traced field lines.
    pfss_input : pfsspy.Input
        PFSS input.
    pfss_output : pfsspy.Output
        PFSS output.
    """
    pfss_input = pfsspy.Input(synoptic_map, nrho, rss)
    print('Computing PFSS...')
    pfss_output = pfsspy.pfss(pfss_input)

    tracer = pfsspy.tracing.FortranTracer(max_steps=2000)
    print('Tracing field lines...')
    flines = tracer.trace(seeds, pfss_output)
    return flines, pfss_input, pfss_output

def footpoints(times, vsw, synoptic_map):
    """
    Given a set of times at L1, trace back to the Sun and return
    a set of magnetic field footpoints.

    Parameters
    ----------
    times :
    vsw : Quantity
    synoptic_map : sunpy.map.GenericMap

    Returns
    -------
    flines : pfsspy.flines.field_lines
        Traced field lines.
    pfss_input : pfsspy.Input
        PFSS input.
    pfss_output : pfsspy.Output
        PFSS output.
    """
    traj = earth_trajectory(times)
    seeds = project_to_ss(traj.coords, vsw, synoptic_map.date).T
    flines, input, output = trace_to_surface(seeds, synoptic_map)
    return flines, input, output

def map_interp_carrington(m, fpoints):
    """
    Given a SunPy map, and a series of footpoints, interpolate
    the map data on to the footpoints.
    """
    fpoints = sunframes.HeliographicCarrington(fpoints.lon, fpoints.lat, fpoints.radius, obstime=m.date)
    pixels = m.world_to_pixel(fpoints)
    x, y = (pixels.x / u.pix).astype(int), (pixels.y / u.pix).astype(int)
    trace = m.data[y, x]
    # Remove points that are behind the Sun
    # trace = trace.astype(float)
    # trace[fpoints.distance > m.dsun] = np.nan
    return trace

def read_fipdata(fip_file):
    """
    Clean up the raw full sun scan data, and return a series
    of SunPy maps with coordinate system information.
    """
    eis_map = readsav(fip_file)
    new_maps = {}
    for key in eis_map:
        new_map = eis_map[key].copy()
        new_map[new_map == 0] = np.nan
        obstime = Time('2013-01-17')
        shape = new_map.shape
        scale = 0.5356 / 1938  # deg / pix
        header = sunpy.map.make_fitswcs_header(np.empty(shape),
                                               SkyCoord(0, 0, unit=u.deg,
                                                        frame="helioprojective",
                                                        obstime=obstime),
                                               scale=[scale, scale] * u.deg / u.pix)
        new_maps[key] = sunpy.map.Map(new_map, header)

    return new_maps

def parker_angle(v, r=const.au, lat=0*u.deg):
    omega_sun = 450 * u.km / u.s / const.au
    return np.arctan(omega_sun * r * np.cos(lat) / v).to(u.deg)

def carrington_header(time, shape_out):
    """
    Create the header for a Heliographic Carrington coordinate frame
    at a given *time*, with a given data *shape_in*.
    """
    return sunpy.map.make_fitswcs_header(
        np.zeros(shape_out),
        SkyCoord(0, 0, unit=u.deg,
                 frame="heliographic_carrington",
                 obstime=time),
        scale=[180 / shape_out[0],
               360 / shape_out[1]] * u.deg / u.pix,
        projection_code="CAR")

def wrap_field_line(coords):
    """
    Insert NaNs into a set of coordinates when they wrap, so that
    lines don't jump from 0 to 360 degrees on a plot.
    """
    lon = coords.lon.to_value(u.deg)
    # We want to wrap when lon gos from > 0 to < 360
    lon[lon > 360] -= 360
    jumps = np.where(np.abs(np.diff(lon) > 180))[0]
    if jumps.size > 0:
        jumps += 1
        lon = coords.lon
        lon = np.insert(lon, jumps, np.nan * u.deg)
        lat = coords.lat
        lat = np.insert(lat, jumps, np.nan * u.deg)
        r = coords.radius
        r = np.insert(r, jumps, np.nan * u.m)
        coords = SkyCoord(lon, lat, r, frame=coords.frame)

    return coords


def Debug(*obj, **kwargs):
    print(f"Debug: {obj}")
    if len(list(kwargs.keys())):
        for key, val in kwargs.items():
            print(f"{key} : {val}\n")

def add_noise(input, intensity : float = 0.01, spread : float = 0.1):
    try: import numpy as np
    except: raise Exception('Failed to import numpy or the module is missing.')

    assert intensity <= 1 and spread <= 1

    copy_input = np.copy(input)
    shape = copy_input.shape
    copy_input = copy_input.ravel()
    for _ in range(int(spread*copy_input.size)):
        copy_input[np.random.randint(0, copy_input.size)] = np.random.randint(0, 255)*intensity/255
    return copy_input.reshape(shape).astype('float32')

def gauss_noise(image, intensity: float = 0.1, *, max_var: int = 30):
    try: import numpy as np
    except: raise Exception('Failed to import numpy or the module is missing.')

    assert 0.0 <= intensity <= 1.0 and 0 <= max_var <= 255

    if len(image.shape) == 3: row,col,ch= image.shape
    else: row, col = image.shape

    mean = 0
    var = np.random.randint(0, max_var)
    sigma = var**0.5
    gauss = np.random.normal(mean,sigma,((row,col,ch) if len(image.shape) == 3 else (row,col)))
    gauss = gauss.reshape(*((row,col,ch) if len(image.shape) == 3 else (row,col)))
    noisy = image + gauss*intensity
    return noisy

def salt_and_pepper_noise(image, intensity : float = 0.1, sparseness : float = 0.1):
    try: import numpy as np
    except: raise Exception("Failed to import numpy or module is missing.")
    for _ in range(int(sparseness*image.shape[0]*image.shape[1])):
        image[int(np.random.randint(0,len(image))), int(np.random.randint(0,len(image[0])))] += np.random.uniform(-255.0,255.0)*intensity
    return image

def rand_zoom(image, variance : int = 3):
    try:
        import numpy as np
        from skimage.transform import resize
    except: raise Exception('Failed to import numpy or skimage, or module(s) is missing.')

    assert 0 < variance <= 5
    assert type(image) == np.ndarray and len(image) > 0

    image_shape = image.shape
    x = np.random.randint(0, variance)
    y = len(image) - x
    if variance == 0:
        return image
    return resize(image[x:y, x:y], image_shape)

def augment(images, labels, noise_intensity : float = 0.2, max_rotation : int = 10, max_shift : int = 10, max_zoom : int = 3, outputs : int = 5, *, fill : int = 0, invert_colors : bool = False):
    """
    Generate augmented data.

    Parameters
    ----------
    - `images` : `NDArray`
    - `labels` : `NDArray | list`
    - `noise_intensity` : `float` (Default `0.2`)
    - `max_rotation` : `int` (Default `10`)
    - `max_shift` : `int` (Default `10`)
    - `max_zoom` : `int` (Default 3)
    - `outputs` : `int` (Default 5)
        - This parameter indicates the number of augmented outputs per image.

    Returns
    -------
    `tuple[NDArray, NDArray] | tuple[NDArray, list]`
        Returns a tuple containing the augmented images and the associated labels.
    """
    try:
        from scipy.ndimage import rotate
        import numpy as np
    except: raise Exception('Failed to import scipy or numpy, or the module(s) is missing.')

    assert -360 <= max_rotation <= 360 and -14 <= max_shift <= 14 and 0 <= max_zoom <= 5 and 0 <= noise_intensity <= 1, "Out of bounds."

    results = []

    # A single image's shape is (28, 28). If it comes in an array of length N, it will be (N, 28, 28)
    if len(images.shape) < 3:
        for _ in range(outputs):
            x, y = np.random.randint(-max_shift, max_shift, size = (1,2)).flatten()
            shifted = shift(images, int(x), int(y), fill_value=255-fill)
            zoomed = rand_zoom(shifted, np.random.randint(1, max_zoom))
            rotated = rotate(zoomed, np.random.randint(-max_rotation, max_rotation), reshape = False, cval=255-fill)
            noisy = salt_and_pepper_noise(rotated, noise_intensity, sparseness = 0.2)
            if invert_colors: noisy = invert(noisy)
            results.append(noisy)

        return np.array(results), labels

    else:
        assert len(images) == len(labels), "Must have the same amount of images and labels."
        label_list = []
        for image, label in zip(images, labels):
            temp = []
            for _ in range(outputs):
                x, y = np.random.randint(-max_shift, max_shift, size = (1,2)).flatten()
                shifted = shift(image, int(x), int(y), fill_value=255-fill)
                zoomed = rand_zoom(shifted, np.random.randint(1, max_zoom))
                rotated = rotate(zoomed, np.random.randint(-max_rotation, max_rotation), reshape = False, cval=255-fill)
                noisy = salt_and_pepper_noise(rotated, noise_intensity, sparseness = 0.2)
                if invert_colors: noisy = invert(noisy)
                temp.append(noisy)
                label_list.append(label)
            results.extend(temp)

        assert len(results) == len(label_list)

        return np.array(results), np.array(label_list)

def add_white_bg(filename : str, new_filename : str, *, output_path: str = None):
    try:
        from subprocess import run
        import os
    except: raise Exception('Failed to import subprocess, or module(s) is missing.')
    if output_path is not None:
        run("convert {} -background white -alpha remove -alpha off {}/{}".format(filename, output_path, new_filename).split(" "))
    else:
        run("convert {} -background white -alpha remove -alpha off {}".format(filename, new_filename).split(" "))

def shift(image, x : int = 0, y : int = 0, *, output_shape : tuple = (28, 28), fill_value : float = 255.0, dtype : str = "float32"):
    """
    Parameters
    ----------

    - `image` : `NDArray`
    - `x` : `int`
        - Positive `x` shifts to the right.
        - Negative `x` shifts to the left.
    - `y` : `int`
        - Positive `y` shifts to the bottom.
        - Negative `y` shifts to the top.
    - `output_shape` : `tuple[int, int]`
    - `fill_value` : `float`
    - `dtype` : `str`

    Returns
    -------
    Shifted image as a `NDArray`.
    """

    try: import numpy as np
    except: raise Exception("Failed to import numpy or the module is missing.")

    assert len(image.shape) >= 2 and type(x) == int and type(y) == int and type(output_shape) == tuple

    image_shape = image.shape[:2]
    res = image
    col = np.array([[fill_value]]*image_shape[0])
    row = np.array([fill_value]*image_shape[1])

    if x < 0:
        for _ in range(np.abs(x)):
            res = np.hstack((col, res))
            res = res[:, :-1]
    elif x > 0:
        for _ in range(x):
            res = np.hstack((res, col))
            res = res[:, 1:]

    if y < 0:
        for _ in range(np.abs(y)):
            res = np.vstack((row, res))
            res = res[:-1, :]
    elif y > 0:
        for _ in range(y):
            res = np.vstack((res, row))
            res = res[1:, :]

    return res.reshape(output_shape).astype(dtype)

def find_bounding_box(image):
    try: import numpy as np
    except: raise Exception("Failed to import numpy or the module is missing.")

    white = 255
    max_row_index = 0
    max_col_index = 0
    min_row_index = len(image)
    min_col_index = len(image[0])

    transposed_image = image.T

    for row in image:
        (non_white, ) = np.where(row != white)
        if len(non_white) > 0:
            if min(min(non_white), min_row_index) == min(non_white):
                min_row_index = min(non_white)
            if max(max(non_white), max_row_index) == max(non_white):
                max_row_index = max(non_white)
        continue

    for row in transposed_image:
        (non_white, ) = np.where(row != white)
        if len(non_white) > 0:
            if min(min(non_white), min_col_index) == min(non_white):
                min_col_index = min(non_white)
            if max(max(non_white), max_col_index) == max(non_white):
                max_col_index = max(non_white)
        continue

    return min_row_index, min_col_index, max_row_index, max_col_index,

def center_image(image, approx = "ceil"):
    """
    Center a black and white image to the overall image center point.

    Parameters
    ----------

    - `image` : `NDArray`
    - `approx` : `str`
        - Approximation type: Either `ceil` or `floor`.

    Returns
    -------

    The centered image as an `NDArray`.
    """
    try: import numpy as np
    except: raise Exception("Failed to import numpy or the module is missing.")

    assert type(image) == np.ndarray and approx.lower() in ("ceil", "floor")

    image_width = len(image[0])
    image_height = len(image)
    approx = np.ceil if approx.lower() == "ceil" else np.floor
    xmin, ymin, xmax, ymax = find_bounding_box(image.reshape(28, 28))
    dx, dy = ((xmax + xmin - image_width)/2), ((ymax + ymin - image_height)/2)
    shifted_img = shift(image.reshape(28, 28), int(approx(dx)), int(approx(dy)))

    return shifted_img

def load_image(filename : str, output_shape : tuple = (28, 28)):
    try: from keras.utils import load_img, img_to_array
    except: raise Exception('Failed to import keras or module is missing.')

    img = load_img(filename, color_mode="grayscale", target_size=(28, 28))
    img = img_to_array(img)
    img = img.reshape(output_shape).astype('float32')
    return img

def invert(image):
    try: import numpy as np
    except: raise Exception("Failed to import numpy or module is missing.")

    temp = np.full(image.shape, 255)
    inverted = temp - image

    return inverted.astype("float32")


import pymssql
import pandas as pd
import logging
import datetime
from dailyEmail import daily_email
import json
import os

# Set Status of File
Stage = os.environ.get("PYENV_HOME")
print(Stage)

# Open config.json file and load data
with open("config.json") as json_data_file:
    my_config = json.load(json_data_file)

# Determine status and access values for correct config file
if Stage == "DEV":
    config = my_config["uat"]
else:
    config = my_config["prod"]

# Create Logging File with configs
LOG_FORMAT = "%(levelname)s %(asctime)s - %(message)s"
logging.basicConfig(filename="dailykit_log.log", level=logging.INFO, format=LOG_FORMAT)
logger = logging.getLogger()

# Create Connection to Database
cnxn = pymssql.connect(
    config["Server"], config["uid"], config["password"], config["Database"]
)

# Create a list of OnHand Finished Product
QtyOnHand = pd.read_sql(
    "Select * FROM BenchmadeDB.dbo.VU_DailyKitTopSKUQtyOnHand", cnxn
)
QtyOnHand_OG = QtyOnHand.copy(deep=True)

# Create a list of Priority items
priority_items = pd.read_sql(
    "Select * FROM BenchmadeDB.dbo.VU_DailyKitPriorityList", cnxn
)
priority_items = priority_items.sort_values("Priority")
priority_items = priority_items.reset_index()
priority_items.drop(labels=["index"], axis=1, inplace=True)

# Create List of items
items_p = pd.read_sql("Select * From BenchmadeDB.dbo.VU_DailyKitItemsP", cnxn)

# Create List of active skus
active_skus = pd.read_sql("Select * From BenchmadeDB.dbo.VU_DailyKitActiveSKU", cnxn)
active_skus_max = pd.read_sql(
    "Select * From BenchmadeDB.dbo.VU_DailyKitActiveSKU", cnxn
)

# Reduce list of need to make based on what is avilable in the warehouse
logging.info("Creating new Priority_Items List")
for index, row in priority_items.iterrows():
    try:
        QtyOnHand_item = QtyOnHand.loc[
            QtyOnHand["StockCode"] == row["StockCode"], "TotalOnHand"
        ].item()
        if QtyOnHand_item >= row["Total"]:
            QtyOnHand.loc[
                QtyOnHand["StockCode"] == row["StockCode"], "TotalOnHand"
            ] -= row["Total"]
            priority_items.iat[index, 2] = 0
        else:
            priority_items.iat[index, 2] -= QtyOnHand_item
            QtyOnHand.at[QtyOnHand["StockCode"] == row["StockCode"], "TotalOnHand"] = 0
    except:
        logging.error(
            "{} has none on hand in warehouses F, G or H".format(row["StockCode"])
        )
logging.info("New Prioirty List Completed.")

# Create List of All Parent Components
bom_list = pd.read_sql("Select * From BenchmadeDB.dbo.VU_DailyKitCompList", cnxn)

# Find BOM Structure
def bomStructure(stockCode):
    global bom_list
    comp_list = bom_list.query("ParentPart == '{}'".format(stockCode))

    return comp_list

# Creates dict of Components and min one
def leastOfThese(comp_list, items_list):

    n = 100000
    c = ""

    for comp in comp_list["Component"].unique():
        y = (
            items_list.loc[items_list["StockCode"] == comp, "QtyOnHand"].item()
            // comp_list.loc[comp_list["Component"] == comp, "QtyPer"].item()
        )
        if y < n:
            n = y
            c = comp

    return (n, c)

# Loop though all active skus, build dataframe of available to kit and save to csv
def main():

    kit_items = pd.DataFrame(
        columns=[
            "StockCode",
            "LimitComponent",
            "Description",
            "BuildQty",
            "QtyNeeded",
            # "QtyOrdered", # Simplifying Visability
            "InWIP",
            # "QtyOnHand", # Simplifying Visability
            "Priority",
            "MakeBuy",
        ]
    )

    # Loop for priority items first
    for index, row in priority_items.iterrows():
        item = row["StockCode"]

        comp_list = bomStructure(item)

        try:
            n, c = leastOfThese(comp_list, items_p)

            if n >= 10 and n > row["Total"]:
                buildqty = (row["Total"] // 10) * 10

            elif n >= 10 and n < row["Total"]:
                buildqty = (n // 10) * 10

            else:
                buildqty = 0

            if buildqty > 0:
                for comp in comp_list["Component"].unique():
                    try:
                        items_p.loc[items_p["StockCode"] == comp, "QtyOnHand"] -= (
                            buildqty
                            * comp_list.loc[
                                comp_list["Component"] == comp, "QtyPer"
                            ].item()
                        )

                    except Exception as e:
                        logger.error("{} : {}".format(item, e))

                kit_items = kit_items.append(
                    {
                        "StockCode": item,
                        "LimitComponent": c,
                        "Description": items_p.loc[
                            items_p["StockCode"] == c, "Description"
                        ].item(),
                        "BuildQty": buildqty,
                        "QtyNeeded": row["Total"],
                        # "QtyOrdered": row["TotalOrdered"], # Simplifying Visability
                        "InWIP": row["OnOrder"],
                        # "QtyOnHand": QtyOnHand_OG.loc[
                        #     QtyOnHand_OG["StockCode"] == row["StockCode"], "TotalOnHand"
                        # ].item(), # Simplifying Visability
                        "Priority": row["Priority"],
                        "MakeBuy": items_p.loc[
                            items_p["StockCode"] == c, "PartCategory"
                        ].item(),
                    },
                    ignore_index=True,
                )
        except Exception as e:

            logger.error("{} : {}".format(item, e))

    # Loop for items in active List
    for item in active_skus["StockCode"].unique():
        # Run bomStructure Function for each StockCode
        comp_list = bomStructure(item)

        try:
            n, c = leastOfThese(comp_list, items_p)

            if n >= 10:
                for comp in comp_list["Component"].unique():
                    buildqty = n // 10 * 10
                    try:
                        items_p.loc[items_p["StockCode"] == comp, "QtyOnHand"] -= (
                            buildqty
                            * comp_list.loc[
                                comp_list["Component"] == comp, "QtyPer"
                            ].item()
                        )

                    except Exception as e:
                        logger.error("{} : {}".format(item, e))

                kit_items = kit_items.append(
                    {
                        "StockCode": item,
                        "LimitComponent": c,
                        "Description": items_p.loc[
                            items_p["StockCode"] == c, "Description"
                        ].item(),
                        "BuildQty": buildqty,
                        "MakeBuy": items_p.loc[
                            items_p["StockCode"] == c, "PartCategory"
                        ].item(),
                    },
                    ignore_index=True,
                )

        except Exception as e:

            logger.error("{} : {}".format(item, e))

    filename = (
        "DailyKittable"
        + str(datetime.datetime.now())
        .replace(".", " ")
        .replace(":", "_")
        .replace(" ", "_")
        + ".xlsx"
    )
    with pd.ExcelWriter(
        filename,
        engine="xlsxwriter",
    ) as writer:
        kit_items.to_excel(writer, sheet_name="kittable", index=False)

    logger.info("DailyKittable.xlsx file has been created.")

    try:
        daily_email(filename)

    except Exception as e:

        logger.critical("FAILED TO SEND EMAIL : {}".format(e))

if __name__ == "__main__":
    try:
        logger.info("Running dailyKittable_live.py file")
        main()
        logger.info("Closing Connection to database")
        cnxn.close()
    except Exception as e:
        logging.critical("FAILLED TO EXECUTE : {}".format(e))


a = ["E=E+T","E=T","T=T*F","T=F","F=(E)","F=i"]
rules = {}
terms = []
for i in a:
    temp = i.split("=")

    terms.append(temp[0])
    try:
        rules[temp[0]] += [temp[1]]
    except:
         rules[temp[0]] = [temp[1]]
terms = list(set(terms))

#========================================================#
x = list(rules.values())
prod_rules = []
for i in x:
    for j in i:
        prod_rules.append(j)
opr = []
list_oprs = ["+","-","*","/","(",")","i"]
for i in prod_rules:
    for x in range(0,len(i)):
        if  i[x] in list_oprs:
            opr.append(i[x])

opm= []
for i in range(0,len(opr)+1):
    x = []
    for j in range(0,len(opr)+1):
        x.append("0")
    opm.append(x)

#========================================================#
def leading(gram, rules, term, start):
    s = []
    if gram[0] not in terms:
        return gram[0]
    elif len(gram) == 1:
        return [0]
    elif gram[1] not in terms and gram[-1] is not start:
        for i in rules[gram[-1]]:
            s+= leading(i, rules, gram[-1], start)
            s+= [gram[1]]
        return s

def trailing(gram, rules, term, start):
    s = []
    if gram[-1] not in terms:
        return gram[-1]
    elif len(gram) == 1:
        return [0]
    elif gram[-2] not in terms and gram[-1] is not start:
        for i in rules[gram[-1]]:
            s+= trailing(i, rules, gram[-1], start)
            s+= [gram[-2]]
    return s

leads = {}
trails = {}
for i in terms:
    s = [0]
    for j in rules[i]:
        s+=leading(j,rules,i,i)
    s = set(s)
    s.remove(0)
    leads[i] = s
    s = [0]
    for j in rules[i]:
        s+=trailing(j,rules,i,i)
    s = set(s)
    s.remove(0)
    trails[i] = s

for i in terms:
    print("LEADING("+i+"):",leads[i])
for i in terms:
    print("TRAILING("+i+"):",trails[i])

print("\nOperator Precedance Matrix")
opr = sorted(opr)

opm[0][0] = "`"

for i in range(1,len(opm)):
    opm[0][i] = opr[i-1]
    opm[i][0] = opr[i-1]

for i in a:
    temp = i.split("=")
    cur_prod = temp[1]
    for j in range (0,len(cur_prod)-1):
        if cur_prod[j] in opr and cur_prod[j+1] in opr:
            opm[opr.index(cur_prod[j]) +1][opr.index(cur_prod[j+1])+1] = "="
        if j < (len(cur_prod)-2):
            if cur_prod[j] in opr and cur_prod[j+2] in opr:
                if cur_prod[j+1] in terms:
                    opm[opr.index(cur_prod[j])+1][opr.index(cur_prod[j+2])+1] = "="
        if cur_prod[j] in opr and cur_prod[j+1] in terms:
            for k in leads[temp[0]]:
                opm[opr.index(cur_prod[j])+1][opr.index(k)+1] = "<"
        if cur_prod[j] in terms and cur_prod[j+1] in opr:
            for k in trails[cur_prod[j]]:
                opm[opr.index(k)+1][opr.index(cur_prod[j+1])+1] = ">"

for i in opm:
    print ('  '.join(map(str, i)))

Semester II/Compiler Programming/7. OPM/opm.py


import pickle
import numpy as np
import matplotlib.pylab as plt
import os
from scipy import interpolate
import torch

from model import CNN_Model, LSTM_Model_RUL, CNN_Model_RUL, Net, Net_new, Autoencoder, LSTM_Model
from util_FPC import EarlyStopping, get_fpc,plot_RUL, get_data, get_change_indices
from train_model import train_model,perform_n_folds
from import_file import *
from dataloader import get_RUL_dataloader
from torch.utils.data import Dataset, DataLoader
from dataloader import battery_dataloader
from load_data import get_discharge_capacities_HUST

fea_num =1
discharge_capacities_HUST = get_discharge_capacities_HUST(fea_num)

name_start_train = 0
name_start_test = 70

percentage  = 0.10  # 10 percent data
window_size = 50    # window size
stride = 1          # stride
channels  =[0] # channels

train_data_HUST, FPC_data_HUST, FPC_data_dict_HUST= get_data(discharge_capacities_HUST[0:70],
                                                              percentage, window_size , stride, channels, "train" , name_start = name_start_train)
test_data_HUST,test_data_dict_HUST  = get_data(discharge_capacities_HUST[70:],None,window_size,stride,channels,type= "test",name_start = name_start_test)

obj_train_HUST  = battery_dataloader(train_data_HUST)
obj_FPC_HUST  = battery_dataloader(FPC_data_HUST)
obj_test_HUST  = battery_dataloader(test_data_HUST)

train_dataloader_HUST = DataLoader(obj_train_HUST, batch_size=8,shuffle=True)
FPC_dataloader_HUST   = DataLoader(obj_FPC_HUST,batch_size=1,shuffle=False)
test_dataloader_HUST = DataLoader(obj_test_HUST, batch_size=1,shuffle=False)

print("Shape of a batch    :",next(iter(train_dataloader_HUST))[0].shape)

device = 'cuda' if torch.cuda.is_available() else 'cpu'
print("Training on ", device)
epochs = 10
learning_rate = 0.0001

pretrained = True
load_pretrained = False
version = 1

ch = ''.join(map(str,channels))

# model = CNN_Model(window_size,len(channels))
dataset = "HUST"
print("Dataset :",dataset)
model = LSTM_Model(window_size,len(channels))
fld = 1
model_dir = "./Weights/FPC/"
model_path = f'{model_dir}/{dataset}_{model.name}_FPC_Channels={ch}_WindowSize={window_size}_Version={version}.pth'

if(load_pretrained):
    model.load_state_dict(torch.load(model_path, map_location=device ))

model.to(device)

optimizer = torch.optim.Adam(model.parameters(), lr = learning_rate, betas= (0.9, 0.99))
criterion = nn.BCELoss()

early_stopping = EarlyStopping(patience=20)

if(pretrained):

    model.load_state_dict(torch.load(model_path, map_location=device ))
    model.to(device)
else:
    model = train_model(model, optimizer, criterion, early_stopping,train_dataloader_HUST,epochs,learning_rate,load_pretrained,model_path,version)

version = 2
# Get Change Indices

change_indices_train,change_indices_test, _, _ = get_change_indices(model,discharge_capacities_HUST,
                                                                    channels,get_saved_indices = False, version = 1, name_start_train=name_start_train, name_start_test= name_start_test, dataset = "HUST")
change_indices_all = np.concatenate((change_indices_train,change_indices_test))

exit()
# RUL Code Start from here

channels_RUL = [0]
window_size_RUL = 50
stride_RUL =1
c_RUL = ''.join(map(str,channels_RUL))

n_folds = 5
scenario = 1
epochs = 600

parameters = {
    "window_size" : window_size,
    "stride": stride,
    "channels": channels_RUL,
    "epochs": epochs,
    "learning_rate": learning_rate
}

# model_RUL = LSTM_Model_RUL(window_size,len(channels))  # LSTM Model
model_RUL = Net(len(channels))    # Transformer Model
#model_RUL = CNN_Model_RUL(window_size,channels)    # CNN Model
print("Training RUL on :", model_RUL.name)

if(model_RUL.name == "LSTM"):
    learning_rate = 0.0001
else:
    learning_rate = 0.0001
print("Learning Rate :", learning_rate)
optimizer = torch.optim.Adam(model_RUL.parameters(), lr = learning_rate, betas= (0.9, 0.99))
# criterion = nn.L1Loss()
criterion = nn.MSELoss()
early_stopping = EarlyStopping(patience=50)

version = 1
pretrained_RUL_scenario1 = False
load_pretrained_scenario1  = False

model_dir_scenario1 = "./Weights/Scenario1/"
model_path_scenario1 = f'{model_dir_scenario1}/{dataset}_f{model_RUL.name}_RUL_Channels={c_RUL}_WindowSize={window_size_RUL}_Version={version}_Fold={fld}.pth'

if(pretrained_RUL_scenario1):
    print("Loading a Pre-trained Model")
    model_RUL.load_state_dict(torch.load(model_path_scenario1,map_location= device))
    test_batteries = np.load("./Test_data/test_batteries_HUST.npy",allow_pickle=True)
    train_batteries = np.load("./Test_data/train_batteries_HUST.npy",allow_pickle=True)

else:
    if(load_pretrained_scenario1):
        print("Training further on already trained model")
        model_RUL.load_state_dict(torch.load(model_path_scenario1,map_location= device))
        model_RUL, test_dataloader_RUL, test_batteries = perform_n_folds(model_RUL,n_folds,discharge_capacities_HUST,change_indices_all,criterion, optimizer, early_stopping,
                    pretrained_RUL_scenario1, model_path_scenario1,scenario,parameters, version,dataset)
    else:
        print("Training a new Model")
        model_RUL, test_dataloader_RUL, test_batteries, train_batteries = perform_n_folds(model_RUL,n_folds,discharge_capacities_HUST,change_indices_all,criterion, optimizer, early_stopping,
                    pretrained_RUL_scenario1, model_path_scenario1,scenario,parameters, version,dataset)
        np.save(f"./Test_data/test_batteries_HUST.npy", test_batteries, allow_pickle=True)
        np.save(f"./Test_data/train_batteries_HUST.npy", train_batteries, allow_pickle=True)

_, _, test_dataloader_RUL = get_RUL_dataloader(discharge_capacities_HUST, train_batteries, test_batteries,
                                              change_indices_all, parameters["window_size"],
                                              parameters["stride"],parameters["channels"] ,scenario)

plot_RUL(model_RUL,discharge_capacities_HUST,test_batteries,test_dataloader_RUL,
         change_indices_all,"Outputs/scenario1_RUL_prediction_test_HUST")