from django.urls import path
from django.contrib import admin
from rest_framework import (
  filters, permissions, generics, mixins,
  status, decorators, serializers, pagination,
)
from posts.models import Post
from django.db.models import Q

# pagination
class PostLimitOffsetPagination(pagination.LimitOffsetPagination):
  default_limit = 2
  max_limit = 10

class PostPageNumberPagination(pagination.PageNumberPagination):
  page_size = 3

# permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
  message = 'You must be owner of this object.'
  def has_permission(self, request, view):
    if request.method in permissions.SAFE_METHODS:
      return True
    return False
  def has_object_permission(self, request, view, obj):
    return obj.user == request.user

post_detail_url = serializers.HyperlinkedIdentityField(
  view_name='posts-api:detail',
  lookup_field='slug',
)

# serializers
class PostListSerializer(serializers.ModelSerializer):
  url = serializers.HyperlinkedIdentityField(
    view_name='posts-api:detail',
    lookup_field='slug'
  )
  delete_url = serializers.HyperlinkedIdentityField(
    view_name='posts-api:delete',
    lookup_field='slug'
  )
  user_field = serializers.SerializerMethodField()
  class Meta:
    model = Post
    fields = [
      'url',
      'user_field',
      'delete_url',
      'title',
      'content',
      'publish']
  def get_user_field(self, obj):
    return str(obj.user.username)

class PostRetrieveSerializer(serializers.ModelSerializer):
  url = post_detail_url
  user_field = serializers.SerializerMethodField()
  image = serializers.ImageField()
  markdown = serializers.SerializerMethodField()
  class Meta:
    model = Post
    # fields = '__all__'
    fields = [
      'id',
      'url',
      'title',
      'markdown',
      'image',
      'user_field',
      'slug',
      'content',
      'publish',
    ]
  def get_markdown(self, obj):
    return obj.get_markdown()
  def get_user_field(self, obj):
    return str(obj.user.username)
  def get_image(self, obj):
    try:
      image = obj.image.url
    except:
      image = None
    return image

class PostCreateUpdateSerializer(serializers.ModelSerializer):
  class Meta:
    model = Post
    # fields = '__all__'
    fields = [
      'title',
      'content',
      'publish'
    ]

# views
class PostListAPIView(generics.ListAPIView):
  serializer_class = PostListSerializer
  filter_backends = [filters.SearchFilter, filters.OrderingFilter]
  search_fields = ['title', 'content', 'user__first_name']
  queryset = Post.objects.all()
  # pagination_class = pagination.PageNumberPagination
  # pagination_class = pagination.LimitOffsetPagination
  # pagination_class = PostLimitOffsetPagination
  pagination_class = PostPageNumberPagination

  def get_queryset(self, *args, **kwargs):
    # queryset_list = super().get_queryset(self, *args, **kwargs)
    queryset_list = Post.objects.all()#.filter(user=self.request.user)
    query = self.request.GET.get("q")
    if query:
      queryset_list = queryset_list.filter(
        Q(title__icontains=query)|
        Q(content__icontains=query)|
        Q(user__first_name__icontains=query) |
        Q(user__last_name__icontains=query)
      ).distinct()
    return queryset_list

class PostCreateAPIView(generics.CreateAPIView):
  queryset = Post.objects.all()
  serializer_class = PostCreateUpdateSerializer
  lookup_field = 'slug'
  permission_classes = [permissions.IsAuthenticated, permissions.IsAdminUser]
  # def perform_update(self, serializer):
  def perform_create(self, serializer):
    serializer.save(
      user=self.request.user,
      # title='my title'
    )

class PostRetrieveAPIView(generics.RetrieveAPIView):
  queryset = Post.objects.all()
  serializer_class = PostRetrieveSerializer
  lookup_field = 'slug'

class PostUpdateAPIView(generics.RetrieveUpdateAPIView):
  queryset = Post.objects.all()
  serializer_class = PostCreateUpdateSerializer
  lookup_field = 'slug'
  permission_classes = [permissions.IsAuthenticated,
    permissions.IsAdminUser, IsOwnerOrReadOnly
  ]

class PostDestroyAPIView(generics.DestroyAPIView):
  queryset = Post.objects.all()
  serializer_class = PostRetrieveSerializer
  lookup_field = 'slug'
  permission_classes = [permissions.IsAuthenticated, permissions.IsAdminUser]

# urls
app_name = 'posts-api'

urlpatterns = [
	path('', PostListAPIView.as_view(), name='list'),
  path('create/', PostCreateAPIView.as_view(), name='create'),
  path('<slug>/', PostRetrieveAPIView.as_view(), name='detail'),
  path('<slug>/edit/', PostUpdateAPIView.as_view(), name='update'),
  path('<slug>/delete/', PostDestroyAPIView.as_view(), name='delete'),

]


# initial code for fitting neural network models in scikit-learn environment

# import
from sklearn.neural_network import MLPClassifier
#from sklearn.linear_model import Perceptron
#from sklearn.linear_model import LogisticRegression
import numpy as np

# initialize
X = np.array([[0., 0.], [0., 1.], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 0])
clf1 = MLPClassifier(hidden_layer_sizes=(7),momentum=0,max_iter=20000)
#clf2 = LogisticRegression(C=100)
clf1.fit(X, y)
#clf2.fit(X, y)
print(clf1.coefs_,"\n",clf1.predict(X))
#print(clf2.intercept_, clf2.coef_)
#print(clf2.predict_proba(X), "\n", clf2.predict(X))


import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
import os
import glob

input_path = "/home/nemo/Audio/hat_jakub_raw/*.wav"
output_path = "/home/nemo/Audio/hat_jakub/"
print(glob.glob(input_path))

counter = 0;
for x in range(1):
    for i in glob.glob(input_path):
        fs, x = wavfile.read(i)
        if x.ndim ==2:
            x_clip = x[1100:17100, 1]
            print(x_clip.shape)
            print("2d fixed")
        else:
            x_clip = x[1100:17100]
            print(x_clip.shape)
        wavfile.write(output_path+'recording_j_'+str(counter)+'.wav', fs, x_clip)
        counter = counter+1
#files = os.listdir('*.wav')
#print(len(files))
fs, x = wavfile.read('/home/nemo/Audio/biscuit_jakub/recording_j_0.wav')
print(x.shape)
x = x[1100:17100, 1]
print(fs)
## ==> 16000
print(x.shape)
   ## ==> (16000,)
#plt.plot(x)
#plt.grid(True)


"""Postgres query client.

Adds the convinience methods for loading csv data using copy_expert,
which is more performant than using sql alchemy functions.
"""

import io
from typing import Sequence

import pandas as pd

from tentaclio import protocols

from . import decorators, sqla_client

__all__ = ["PostgresClient"]

class PostgresClient(sqla_client.SQLAlchemyClient):
    """Postgres client, backed by a SQLAlchemy connection."""

    allowed_schemes = ["postgresql"]

    # Postgres Copy Expert methods:

    @decorators.check_conn
    def dump_df(self, df: pd.DataFrame, dest_table: str) -> None:
        """Dump a data frame into an existing Postgres table."""
        buff = io.StringIO()
        df.to_csv(buff, index=False)
        buff.seek(0)
        self._copy_expert_csv(buff, df.columns, dest_table)

    @decorators.check_conn
    def dump_csv(
        self, csv_reader: protocols.Reader, columns: Sequence[str], dest_table: str
    ) -> None:
        """Dump a csv reader into the database."""
        self._copy_expert_csv(csv_reader, columns, dest_table)

    def _copy_expert_csv(
        self, csv_reader: protocols.Reader, columns: Sequence[str], dest_table: str
    ) -> None:
        """Dump a csv reader into the given table."""
        sql_columns = ",".join(columns)
        sql_query = f"""COPY {dest_table} ({sql_columns}) FROM STDIN
                        WITH CSV HEADER DELIMITER AS ','
                        NULL AS 'NULL';"""
        raw_conn = self.conn.engine.raw_connection()
        try:
            raw_conn.cursor().copy_expert(sql_query, csv_reader)
        except Exception:
            raw_conn.rollback()
            raise
        else:
            raw_conn.commit()


#!/usr/bin/env python3

""" Contact tracing beacon transmitter """

__copyright__ = """
    Copyright 2020 Diomidis Spinellis

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""
__license__ = "Apache 2.0"

import argparse
import bluetooth._bluetooth as bluez
from datetime import datetime
from dp3t.protocols.unlinkable_db import ContactTracer
from epidose.common import logging
import struct
import sys

OGF_LE_CTL = 0x08
OCF_LE_SET_SCAN_ENABLE = 0x000C

def set_receive(socket):
    """Setup to receive contact tracing packets."""
    # Enable scanning
    enable_scanning = struct.pack("<BB", 0x01, 0x00)
    bluez.hci_send_cmd(socket, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, enable_scanning)

    # Obtain Bluetooth advertisement packets
    socket.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14)
    listen_filter = bluez.hci_filter_new()
    bluez.hci_filter_all_events(listen_filter)
    bluez.hci_filter_set_ptype(listen_filter, bluez.HCI_EVENT_PKT)
    socket.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, listen_filter)

def unpack_byte(b):
    """Return b unpacked from a byte value"""
    return struct.unpack("b", bytes([b]))

def process_packet(socket):
    """Read and process a single broadcast packet."""
    packet = socket.recv(255)

    # TODO: This is both too frequent (it triggers for every packet) and
    # can also be too infrequent (if no packets are received)
    now = datetime.now()
    receiver.check_advance_day(now)

    # Early exit for other packets
    (packet_length,) = unpack_byte(packet[2])
    if packet_length != 42:
        return
    if packet[17:18] != bytes([0x1B]):
        return
    # Ensure the packet is     AltBeacon,  cntct-trc,  v1,   app 1
    if packet[21:27] != bytes([0xBE, 0xAC, 0xED, 0x05, 0x01, 0x01]):
        return

    # This is a contact tracing packet
    ephid = packet[27:43]
    (rssi,) = unpack_byte(packet[-1])
    logger.info(f"Got ephid {ephid.hex()} RSSI {rssi}")

    receiver.add_observation(ephid, now, rssi)

def main():
    parser = argparse.ArgumentParser(description="Contact tracing beacon receiver")
    parser.add_argument(
        "-d", "--debug", help="Run in debug mode logging to stderr", action="store_true"
    )
    parser.add_argument(
        "-D",
        "--database",
        help="Specify the database location",
        default="/var/lib/epidose/client-database.db",
    )
    parser.add_argument(
        "-i",
        "--iface",
        help="Listen on the specified interface number, not [hci]0",
        type=int,
        default=0,
    )
    parser.add_argument("-t", "--test", help="Test script", action="store_true")
    parser.add_argument(
        "-v", "--verbose", help="Set verbose logging", action="store_true"
    )
    args = parser.parse_args()

    if args.test:
        args.debug = True
        args.database = ":memory:"

    # Setup logging
    global logger
    logger = logging.getLogger("beacon_rx", args)

    # Receive and process beacon packets
    global receiver
    receiver = ContactTracer(None, args.database, transmitter=False)
    if args.test:
        sys.exit(0)
    socket = bluez.hci_open_dev(args.iface)
    set_receive(socket)
    while True:
        process_packet(socket)

if __name__ == "__main__":
    main()


import re
import os
import itertools
from tqdm.auto import tqdm

print("Do not open any of the output files until the process is finished!")

print("Deleting old results...")
for file in tqdm(os.listdir()):
	if re.match(r'result_', file):
		os.remove(file)

with open ('.\\list_of_lists.txt', 'r', encoding = 'cp1251') as file:
    file = file.readlines()
    list_of_lists = [re.search(r'[A-Z].*\.xlsx', l).group(0) for l in file]

print("Permutation test for each pair of the given languages...")

for file1, file2 in tqdm(itertools.combinations(list_of_lists, 2)):
    print(f'Comparing {file1} and {file2}...')
    os.system(f'.\\bin\\spt_win_x86-64.exe --weights=.\\data\\weights.xlsx --set_a=.\\data\\{file1} --set_b=.\\data\\{file2} --output result.txt --consonants consonant.txt --cost_groups_plot=plot.svg')


import numpy as np
import random
import matplotlib.pyplot as plt
from matplotlib import cm
import math
from matplotlib.patches import Circle
import mpl_toolkits.mplot3d.art3d as art3d
from tqdm import tqdm
from watermaze import watermaze, RMWTask, DMPTask

## Maybe add a FeatureEncoding super class for which PlaceCellEncoding, GridCellEncoding, TileCoding etc. can be subclasses

class PlaceCellEncoding():
    def __init__(self,env,N=493,sigma=16):
        '''
        Args
            env: environment (watermaze) object where place fields are to be randomly distributed
            N: number of place cells
            sigma: breadth of field of each place cell
        '''
        self.env = env
        if N is not None:
            self.N = N
        else:
             self.N = 493
        self.sigma = sigma
        # uniformly distribute the place fields in ploar coordinates
        r_loc = self.env.radius*np.random.uniform(0,1,(self.N,1))
        theta_loc = 2*np.pi*np.random.uniform(0,1,(self.N,1))
        X_loc = r_loc*np.cos(theta_loc)
        Y_loc = r_loc*np.sin(theta_loc)
        self.pos = np.hstack((X_loc,Y_loc))

    def getEncoding(self,loc):
        # this should be the super class function common to all feature encoders
        return self.getPlaceEncoding(loc)

    def getPlaceEncoding(self,loc):
        '''
        Args
            loc: a tuple (x,y) representing the x and y axis position of the point to be encoded
        '''
        diff = self.pos - loc
        rates = np.exp(-np.sum(diff**2,axis=1)/(2*self.sigma*self.sigma))
        return rates

    def plotPlaceCells(self):
        '''
        Creates a visualization of how place cell centers are distributed in the environment
        '''
        # create the figure
        fig = plt.figure()
        ax = fig.gca()

        # create the pool perimeter
        pool_perimeter = plt.Circle((0, 0), self.env.radius, fill=False, color='b', ls='-')
        ax.add_artist(pool_perimeter)

        # create theplatform
        platform = plt.Circle(self.env.platform_location, self.env.platform_radius, fill=False, color='r', ls='-')
        ax.add_artist(platform)

        # plot place cell centers
        placeCells = plt.scatter(self.pos[:,0],self.pos[:,1],s=self.sigma)
        ax.add_artist(placeCells)

        # turn on the grid
        plt.grid(True)
        plt.tight_layout()
        ax.axis('equal')
        ax.set_xlim((-self.env.radius-50, self.env.radius+50))
        ax.set_ylim((-self.env.radius-50, self.env.radius+50))
        plt.xticks(np.arange(-self.env.radius, self.env.radius+20, step=20))
        plt.yticks(np.arange(-self.env.radius, self.env.radius+20, step=20))
        ax.set_xlabel('X Position (cm)')
        ax.set_ylabel('Y Position (cm)')
        plt.show()

    def plotPlaceCellActivations(self,loc):
        '''
        Creates a visualization of how place cell activations vary as the agent (denoted by 'X') moves in the environment
        Note: this should generate a live plot which shows the agent moving in the env and the place cell activations changing
        '''
        placeCodes = self.getPlaceEncoding(loc)
        # create the figure
        fig = plt.figure('PlaceCellEncoding')
        ax = fig.gca()

        # create the pool perimeter
        pool_perimeter = plt.Circle((0, 0), self.env.radius, fill=False, color='b', ls='-')
        ax.add_artist(pool_perimeter)

        # create theplatform
        platform = plt.Circle(self.env.platform_location, self.env.platform_radius, fill=False, color='r', ls='-')
        ax.add_artist(platform)

        # plot place cell centers
        placeCells = plt.scatter(self.pos[:,0],self.pos[:,1],s=self.sigma,c=placeCodes)
        ax.add_artist(placeCells)
        plt.scatter(loc[0],loc[1],marker='x',c='k',s=50)
        # turn on the grid
        plt.grid(True)
        plt.tight_layout()
        ax.axis('equal')
        ax.set_xlim((-self.env.radius-50, self.env.radius+50))
        ax.set_ylim((-self.env.radius-50, self.env.radius+50))
        plt.xticks(np.arange(-self.env.radius, self.env.radius+20, step=20))
        plt.yticks(np.arange(-self.env.radius, self.env.radius+20, step=20))
        ax.set_xlabel('X Position (cm)')
        ax.set_ylabel('Y Position (cm)')
        plt.colorbar()
        plt.title('Place cell activations')
        plt.show(block=False)
        plt.pause(0.2)
        plt.clf()


import numpy as np
import matplotlib.pyplot as plt

poses = np.genfromtxt("../build/robot_pose.csv", delimiter=",")
plt.plot(poses[:, 0], poses[:, 1], 'bo')
plt.xlabel('X (mm)')
plt.ylabel('Y (mm)')
plt.title('Position of Robot')
plt.show()


"""
Converts yolo labels to sloth json format.
"""
import sys
import os
import logging
import argparse
import utils
import json
import numpy as np

def processArgs():
    """ Processes command line arguments     """
    parser = argparse.ArgumentParser(description='List of files to use for training.')
    parser.add_argument('--train_list', type=str, required=True,
                        help='List of files to use for training.')
    parser.add_argument('--val_list', type=str, required=True,
                        help='List of files to use for val.')
    parser.add_argument('--root_json', type=str, required=True,
                        help='dir where labels are stored.')
    parser.add_argument('--train_json', type=str, required=True,
                        help='json file to use for training.')
    parser.add_argument('--val_json', type=str, required=True,
                        help='json file to use for val.')
    parser.add_argument('--image_dir', type=str, required=True,
                        help='directory where images are located.')

    args, unknown = parser.parse_known_args()
    return args

if __name__ == "__main__":
    utils.setupLogging('split_json_train_val')

    args = processArgs()

    train_labels = []
    val_labels = []

    with open(args.root_json, "r") as read_file:
        labels = json.load(read_file)

    if len(labels) <= 0:
        raise RuntimeError("Labels were empty.")

    with open(args.train_list, "r") as read_file:
        train_files = read_file.readlines()

    if len(train_files) <= 0:
        raise RuntimeError("Train files were empty.")

    with open(args.val_list, "r") as read_file:
        val_files = read_file.readlines()

    if len(val_files) <= 0:
        raise RuntimeError("Val files were empty.")

    # Go through the labels and put them in the correct bin
    for l in labels:

        file = l['filename']
        orig_filename = str(os.path.basename(file))
        # orig_basename = os.path.splitext(orig_filename)[0] + '.jpg'

        if any(orig_filename in s for s in train_files):
            logging.info("Adding {} to the train json.".format(orig_filename))
            train_labels.append(l.copy())
        elif any(orig_filename in s for s in val_files):
            logging.info("Adding {} to the val json.".format(orig_filename))
            val_labels.append(l.copy())
        else:
            logging.info("file {} was not in either the train or val lists.".format(orig_filename))
            if os.path.exists(args.image_dir + '/' + file):
                flip_val = np.random.randint(0, 100)
                if flip_val < 50:
                    logging.info("  Adding to training list")
                    train_labels.append(l.copy())
                else:
                    logging.info("  Adding to val list")
                    val_labels.append(l.copy())
            else:
                logging.info("  File does not really exist so skipping it.")

    logging.info("Saving train json to: {}".format(args.train_json))
    json_txt = json.dumps(train_labels)
    with open(args.train_json, 'w') as f:
        f.write(json_txt)

    logging.info("Saving val json to: {}".format(args.train_json))
    json_txt = json.dumps(val_labels)
    with open(args.val_json, 'w') as f:
        f.write(json_txt)

    logging.info("Finished splitting labels.")


from glob import glob
from collections import defaultdict
import os
import math
from random import Random

import numpy as np
import tensorflow as tf
from tensorflow.keras.utils import Sequence
from tensorflow.keras.layers import Input, Conv2D
from tensorflow.keras.models import Model
from tensorflow.keras.losses import MeanSquaredError, BinaryCrossentropy
import imageio
from skimage import transform
import matplotlib.pyplot as plt

import config
import init
import stardist_blocks as sd
import tiled_copy

class AZSequence(Sequence):

    def __init__(self, X, y, batch_size, sample_per_image=1, train_=True, random_subsample_input=True, seed=None, resetseed=False):
        self.rand_instance = Random()
        self.seed = seed
        self.resetseed = resetseed

        if self.seed is not None:
            self.rand_instance.seed(self.seed)

        self.x, self.y = X, y
        self.batch_size = batch_size
        self.sample_per_image = sample_per_image
        self.train = train_
        self.random_subsample_input = random_subsample_input

    def __len__(self):
        return math.ceil(len(self.x)*self.sample_per_image / self.batch_size)

    def on_epoch_end(self):
        if self.resetseed is True:
            self.rand_instance.seed(self.seed)

    def get_random_crop(self, image_shape, crop_shape):
        randmax = image_shape-np.array(list(crop_shape))
        topleft = np.array([self.rand_instance.randrange(r) for r in randmax])
        return tuple(slice(s, e) for (s, e) in zip(topleft, topleft+crop_shape))

    @staticmethod
    def read_stack(slice_paths, train_, normalize=False, random_subsample=None):
        # The same x-y crop will be applied to each brightflield slice and even on the fluo targets.
        for idx, im_path in enumerate(slice_paths):
            slice_ = imageio.imread(im_path).astype(np.float32)

            if normalize:
                slice_ = slice_/np.max(slice_)

            if config.target_size is not None and np.shape(slice_) != config.target_size:
                # Resize
                #slice_ = transform.resize(slice_, config.target_size)

                # Crop from top-left
                global_crop = tuple(slice(None, s) for s in config.target_size)
                slice_ = slice_[global_crop]

            """
            if train_:
                slice_ = slice_[:config.splity, :]
            else:
                slice_ = slice_[config.splity:, :]
            """

            if random_subsample is not None:
                slice_ = slice_[random_subsample]

            if idx == 0:
                xy_shape = (len(slice_paths),) + np.shape(slice_)
                image = np.zeros(xy_shape, slice_.dtype)

            image[idx] = slice_
        return image

    @staticmethod
    def augment(image, rotate_angle: int, fliplr_tf: bool, flipud_tf: bool) -> np.ndarray:
        # AZSequence.count += 1
        # print(f"{AZSequence.count} - rotate={rotate_angle}, flip LR={fliplr_tf}, flip UD={flipud_tf}")
        if rotate_angle != 0:
            image = transform.rotate(image, angle=rotate_angle)
        if fliplr_tf:
            image = np.fliplr(image)
        if flipud_tf:
            image = np.flipud(image)

        # if image_in.shape[-1] > 3:
        #     visualize(image_in[..., 3], image[..., 3])
        # else:
        #     visualize(image_in, image)

        return image

    def __getitem__(self, idx):
        image_idx = idx // self.sample_per_image
        batch_x = self.x[image_idx * self.batch_size:(image_idx + 1) *
        self.batch_size]
        batch_y = self.y[image_idx * self.batch_size:(image_idx + 1) *
        self.batch_size]

        #print('Constructing batch:')

        batch_x_images = []
        batch_y_images = []

        """
        if self.train:
            random_subsample = self.get_random_crop((config.splity, 2554), config.sample_crop[:2])
        else:
            random_subsample = self.get_random_crop((2154-config.splity, 2554), config.sample_crop[:2])
        """

        random_subsample = self.get_random_crop((2154, 2554), config.sample_crop[:2])

        if not self.random_subsample_input:
            random_subsample = None

        rotate_tf = np.random.uniform() < config.rotate_p
        if rotate_tf and config.augment:
            rotate_angle = self.rand_instance.choice([90, 180, 270])
        else:
            rotate_angle = 0
        fliplr_tf = np.random.uniform() < config.fliplr_p
        flipud_tf = np.random.uniform() < config.flipud_p

        import pprint
        pp = pprint.PrettyPrinter(indent=4)

        #print('..............')
        #pp.pprint(batch_x)

        for batch_elem in batch_x:
            image = self.read_stack(batch_elem, self.train, True, random_subsample)
            image = np.transpose(image, (1, 2, 0))
            if config.augment and self.train:
                image = self.augment(image, rotate_angle, fliplr_tf, flipud_tf)
            batch_x_images.append(image)
            #print('Batch X shape:', np.shape(image))

        for batch_elem in batch_y:
            image = self.read_stack(batch_elem, self.train, True, random_subsample)
            image = np.transpose(image, (1, 2, 0))

            if config.augment and self.train:
                image = self.augment(image, rotate_angle, fliplr_tf, flipud_tf)
            batch_y_images.append(image)
            #print('Batch y shape:', np.shape(image))

        return np.array(batch_x_images), np.array(batch_y_images)

def get_images_list(data_dir):
    if config.local_run:
        image_paths_ = glob('%s/*/input/*' % data_dir)
        label_paths_ = glob('%s/*/targets/*' % data_dir)
    else:
        image_paths_ = []
        label_paths_ = []
        magnifications = ['20x', '40x', '60x']

        magnifications = [magnifications[0]]

        for magnification in magnifications:
            glob_im = '%s/%s/*A04*' % (data_dir, magnification)
            print(glob_im)
            image_paths_ += glob(glob_im)
            for ch in ['1', '2', '3']:
                glob_lab = '%s/%s/*A0%s*' % (data_dir, magnification, ch)
                label_paths_ += glob(glob_lab)

    return image_paths_, label_paths_

def info(im_name):
    im_bname = os.path.basename(im_name)
    experiment = im_bname[:len('AssayPlate_Greiner_#655090')]
    well = im_bname[len('AssayPlate_Greiner_#655090_'):len('AssayPlate_Greiner_#655090_')+3]
    field = im_bname[len('AssayPlate_Greiner_#655090_D04_T0001F'):len('AssayPlate_Greiner_#655090_D04_T0001F')+3]

    return experiment, well, field

def get_dataset(data_dir, train_, sample_per_image=60, random_subsample_input=True, seed=None, resetseed=None, filter_fun=None):
    image_paths_, label_paths_ = get_images_list(data_dir)
    print('Number of image files discovered:', len(image_paths_))
    print('Number of label files discovered:', len(label_paths_))

    image_paths, label_paths = [], []
    def filter_(paths, filter_fun_):
        result_ = []
        for path_ in paths:
            if filter_fun_(path_):
                result_.append(path_)

        return result_

    image_paths, label_paths = image_paths_, label_paths_

    if filter_fun is not None:
        image_paths = filter_(image_paths_, filter_fun)
        label_paths = filter_(label_paths, filter_fun)

    print('Number of selected files:', len(image_paths))
    print('Number of selected labels:', len(label_paths))

    label_paths.sort()
    image_paths.sort()

    '''
    Image format:   AssayPlate_Greiner_#655090_D04_T0001F006L01A04Z03C04.tif - Only the Z varies
    Label format:   AssayPlate_Greiner_#655090_D04_T0001F006L01A01Z01C01.tif - A and C varies between C01 and C03, Z= 01

    Fluo channels:
    C01=nuclei  (Red)
    C02=lipids  (Green)
    C03=cyto    (Blue)

    D04: well
    T0001: timepoint (irrelevant)
    F006: FOV (site)
    L01: timeline (irrelevant)
    A04: action (fluorescents + brightfield)
    Z03: slice number
    C04: same as action

    20x:    48
    40x:    64
    60x:    96

    '''

    def get_im_id(im_path):
        base = os.path.basename(im_path)
        im_id = base[:len('AssayPlate_Greiner_#655090_D04_T0001F006')]
        return im_id

    def get_res(im_path):
        if config.local_run:
            return os.path.basename(
                os.path.dirname(os.path.dirname(im_path)))[:3]
        else:
            return os.path.basename(
                    os.path.dirname(im_path))[:3]

    images, labels = defaultdict(list), defaultdict(list)

    for image in image_paths:
        k = (get_im_id(image), get_res(image))
        images[k].append(image)

    for label in label_paths:
        k = get_im_id(label), get_res(label)
        labels[k].append(label)

    x, y = [], []

    for k in labels.keys():
        #print('Image found:', k)
        x.append(images[k])
        y.append(labels[k])

    return AZSequence(
        x, y, batch_size=1, sample_per_image=sample_per_image, train_=train_,
        random_subsample_input=random_subsample_input, resetseed=resetseed, seed=seed)

def visualize(original, augmented):
    fig = plt.figure()
    plt.subplot(1,2,1)
    plt.title('Original image')
    plt.imshow(original)

    plt.subplot(1,2,2)
    plt.title('Augmented image')
    plt.imshow(augmented)
    plt.show()

def get_network():
    unet_input = Input(shape=config.net_input_shape)
    unet_out = sd.unet_block(n_filter_base=64)(unet_input)
    fluo_channels = Conv2D(3, (1, 1), name='fluo_channels', activation='sigmoid')(unet_out)

    model = Model(unet_input, fluo_channels)
    model.summary(line_length=130)

    '''

    Weighed loss:

    Network input: (b, h, w, 3)
    b images are in the batch, each of them has hxw pixels and 3 channels

    The default MeanSquaredError will reduce the mean over the whole batch.

    '''
    def channelwise_loss(y_true, y_pred):

        total_loss = 0.

        weights = [.5, .2, .3]
        #weights = [1., 1., 1.]

        for ch in [0, 1, 2]:
            total_loss += weights[ch] * MeanSquaredError()(y_true[..., ch], y_pred[..., ch])
            '''
            total_loss += weights[ch] * BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE)(
                        y_true[..., ch],
                        y_pred[..., ch]
                    )
            '''

        # The first channel is the nuclei
        # Most of the pixels below the intensity 600 are the part of the background and correlates with the cyto.
        # Therefore we concentrate on the >600 ground truth pixels. (600 ~ .1 after normalization)
        #nuclei_weight = .8
        #nuclei_thresh = .1

        #nuclei_weight_tensor = nuclei_weight*tf.cast(y_true[..., 0] > nuclei_thresh, tf.float32) + (1.-tf.cast(y_true[..., 0] <= nuclei_thresh, tf.float32))

        '''
        nuclei_loss = BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE)(
            y_true[..., 0],
            y_pred[..., 0]
        )
        '''

        #total_loss += tf.math.reduce_mean(nuclei_loss * nuclei_weight_tensor)
        #total_loss += tf.math.reduce_mean(nuclei_loss)

        return total_loss

    model.compile(optimizer='adam', loss=channelwise_loss)
    return model

def train(sequences, model):
    train, val = sequences
    mcp_save = tf.keras.callbacks.ModelCheckpoint('%s/model-{epoch:04d}-{val_loss:.4f}.h5' % config.output_dir, save_best_only=True, monitor='val_loss', mode='min')
    callbacks = []

    if not config.readonly:
        callbacks += [mcp_save]

    model.fit(train, validation_data=val, epochs=400, callbacks=callbacks, initial_epoch=config.initial_epoch, steps_per_epoch=200)

    return model

def predict_tiled(x, y_channels, tile_sizes):
    print(np.shape(x))
    ys, xs = np.shape(x)[1], np.shape(x)[2]
    (y_src, y_src_crop, y_target), (x_src, x_src_crop, x_target) = tiled_copy.get_tiles(ys, tile_sizes[0]), tiled_copy.get_tiles(xs, tile_sizes[1])
    y_shape = np.shape(x)[:3] + (y_channels,)
    stitched_y = np.zeros(y_shape, x.dtype)

    for y_idx in range(len(y_src)):
        for x_idx in range(len(x_src)):
            print('Predicting tile: y=%d, x=%d' % (y_idx, x_idx))
            src_crop = (slice(None), slice(*y_src[y_idx]), slice(*x_src[x_idx]), slice(None))
            src_tile_crop = (slice(None), slice(*y_src_crop[y_idx]), slice(*x_src_crop[x_idx]), slice(None))
            target_crop = (slice(None), slice(*y_target[y_idx]), slice(*x_target[x_idx]), slice(None))

            x_tile_predict = model.predict(x[src_crop])
            stitched_y[target_crop] = x_tile_predict[src_tile_crop]

    return stitched_y

def test(sequence, model=None, save=False, tile_sizes=None):
    """
    If the model is set, it predicts the image using the model passed and shows the result.
    """
    for idx, (x, y) in enumerate(sequence):
        batch_element = 0
        plot_layout = 140

        x_sample, y_sample = x[batch_element], y[batch_element]
        z_pos = np.shape(x_sample)[-1]//2
        x_im, y_im = x_sample[..., z_pos], y_sample

        if model is not None:
            plot_layout = 240

            if tile_sizes is not None:
                y_pred = predict_tiled(x, 3, tile_sizes)
            else:
                y_pred = model.predict(x)

            y_pred_sample = y_pred[batch_element]

            y_pred_sample_normalized = np.zeros_like(y_pred_sample)
            for ch in range(np.shape(y_pred_sample)[-1]):
                y_pred_sample_normalized[..., ch] = y_pred_sample[..., ch] / np.max(y_pred_sample[..., ch])

            plt.subplot(plot_layout + 6, title='Predicted fluorescent (red)')
            plt.imshow(y_pred_sample[..., 0])

            plt.subplot(plot_layout + 7, title='Predicted Fluorescent (green)')
            plt.imshow(y_pred_sample[..., 1])

            plt.subplot(plot_layout + 8, title='Predicted Fluorescent (blue)')
            plt.imshow(y_pred_sample[..., 2])

            if save and not config.readonly:
                imageio.imwrite(os.path.join(config.output_dir, '%d_bright.tif' % idx), x_im)
                imageio.imwrite(os.path.join(config.output_dir, '%d_true.tif' % idx), y_sample)
                imageio.imwrite(os.path.join(config.output_dir, '%d_pred.tif' % idx), y_pred_sample)

        plt.subplot(plot_layout + 1, title='Input Brightfield@Z=%d' % z_pos)
        plt.imshow(x_im)

        plt.subplot(plot_layout + 2, title='GT Fluorescent (red)')
        plt.imshow(y_im[..., 0])

        plt.subplot(plot_layout + 3, title='GT Fluorescent (green)')
        plt.imshow(y_im[..., 1])

        plt.subplot(plot_layout + 4, title='GT Fluorescent (blue)')
        plt.imshow(y_im[..., 2])

        plt.show()
        #plt.savefig('%d.png' % idx)

        if save and False:
            bright = (x_sample[..., 1]*255).astype(np.uint8)
            fluo = (y_sample*255).astype(np.uint8)

            imageio.imwrite(os.path.join(config.output_dir, '%d_bright.tif' % idx, bright))
            imageio.imwrite(os.path.join(config.output_dir, '%d_fluo.tif' % idx, fluo))

            imageio.volwrite('%s/pred-%d.tif' % (config.output_dir, idx), y_pred_sample)
            imageio.volwrite('%s/true-%d.tif' % (config.output_dir, idx), y_im)
            imageio.volwrite('%s/input-%d.tif' % (config.output_dir, idx), np.transpose(x_sample, (2, 0, 1)))

if __name__ == '__main__':
    if not config.readonly:
        os.makedirs(config.output_dir, exist_ok=True)

    # Leave out wells for validation
    lo_ws = ['B03']

    train_sequence = get_dataset(config.data_dir, train_=True, sample_per_image=20, random_subsample_input=True, seed=config.seed, filter_fun=lambda im: info(im)[1] not in lo_ws)
    val_sequence = get_dataset(config.data_dir, train_=False, sample_per_image=8, random_subsample_input=True, seed=config.seed, resetseed=True, filter_fun=lambda im: info(im)[1] in lo_ws)

    #test_sequence = get_dataset(config.data_dir, train_=False, sample_per_image=1, random_subsample_input=False)

    model = get_network()

    if config.init_weights is not None:
        print('Loading weights:', config.init_weights)
        model.load_weights(config.init_weights)

    if config.train == True:
        model = train((train_sequence, val_sequence), model)

    #test(test_sequence, model, tile_sizes=tuple(config.sample_crop[:2]), save=config.save)
    #test(train_sequence)


from seaside.Equationlib import *
from seaside.OutputFunctions import *
import os
import pandas as pd
from pyomo.environ import *
from pyomo.opt import SolverFactory

def _(x):
  return ExprM(vars, m = x)

# ----------------------------------------------------------------
# set file paths
# ----------------------------------------------------------------

modelPath = os.path.join(os.getcwd(), 'seaside')
filePath = os.path.join(modelPath, 'seaside')

#filePath = './JOP_small/'

# ----------------------------------------------------------------
# define sets
# ----------------------------------------------------------------

# ALL ACCOUNTS IN SOCIAL ACCOUNTING MATRIX
Z = [
     'CONST1',
     'RETAIL1',
     'SERV1',
     'HC1',
     'ACCOM1',
     'REST1',
     'AG2',
     'CONST2',
     'MANUF2',
     'RETAIL2',
     'SERV2',
     'HC2',
     'ACCOM2',
     'REST2',
     'AG3',
     'UTIL',
     'CONST3',
     'RETAIL3',
     'SERV3',
     'HC3',
     'HS1',
     'HS2',
     'HS3',
     'L1',
     'L2',
     'L3',
     'L4',
     'L5',
     'LAND',
     'KAP',
     'INVES',
     'HH1',
     'HH2',
     'HH3',
     'HH4',
     'HH5',
     'USSOCL1',
     'USSOCL2',
     'USSOCL3',
     'USSOCL4',
     'USSOCL5',
     'STPIT',
     'LOCTAX',
     'PROPTX',
     'ACCTAX',
     'CYGF',
     'FED',
     'ROW']

# FACTORS
F = ['L1', 'L2', 'L3', 'L4', 'L5', 'LAND', 'KAP']

# LABOR
L = ['L1', 'L2', 'L3', 'L4', 'L5']

# LAND
LA = ['LAND']

# CAPITAL
K = ['KAP']

# GOVERNMENTS
G = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5',
     'STPIT', 'LOCTAX', 'PROPTX', 'ACCTAX', 'CYGF', 'FED']

# ENDOGENOUS GOVERNMENTS
GN = ['FED']

# LOCAL ENDOGENOUS GOVERNMENTS
GNL = ['FED']

# EXOGENOUS GOVERMENTS
GX = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5',
      'STPIT', 'LOCTAX', 'PROPTX', 'ACCTAX']

# SALES OR EXCISE TAXES
GS = ['LOCTAX', 'ACCTAX']

# LAND TAXES
GL = ['PROPTX']

# FACTOR TAXES
GF = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5', 'PROPTX']

# SS PAYMENT
GFUS = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5']

USSOCL = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5']

# SS PAYMENT
GFUSC = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5']

# INCOME TAX UNITS
GI = ['STPIT']

# HOUSEHOLD TAX UNITS
GH = ['PROPTX']

# EXOGNOUS TRANSFER PMT
GY = ['USSOCL1', 'USSOCL2', 'USSOCL3', 'USSOCL4', 'USSOCL5',
      'STPIT', 'LOCTAX', 'PROPTX', 'ACCTAX',
      'FED']

# ENDOGENOUS TRANSFER PMT
GT = ['CYGF', 'FED']

# HOUSEHOLDS
H = ['HH1', 'HH2', 'HH3', 'HH4', 'HH5']

# I+G SECTORS
IG = ['CONST1', 'RETAIL1', 'SERV1', 'HC1', 'ACCOM1',
      'REST1', 'AG2', 'CONST2', 'MANUF2', 'RETAIL2', 'SERV2', 'HC2', 'ACCOM2',
      'REST2', 'AG3', 'UTIL', 'CONST3', 'RETAIL3', 'SERV3', 'HC3',
      'HS1', 'HS2', 'HS3', 'FED']

# INDUSTRY SECTORS
I = ['CONST1', 'RETAIL1', 'SERV1', 'HC1', 'ACCOM1',
     'REST1', 'AG2', 'CONST2', 'MANUF2', 'RETAIL2', 'SERV2', 'HC2', 'ACCOM2',
     'REST2', 'AG3', 'UTIL', 'CONST3', 'RETAIL3', 'SERV3', 'HC3',
     'HS1', 'HS2', 'HS3']

# ENDOGENOUS GOVERNMENTS
IG2 = ['FED']

# PRODUCTION SECTORS
IP = ['CONST1', 'RETAIL1', 'SERV1', 'HC1', 'ACCOM1',
      'REST1', 'AG2', 'CONST2', 'MANUF2', 'RETAIL2', 'SERV2', 'HC2', 'ACCOM2',
      'REST2', 'AG3', 'UTIL', 'CONST3', 'RETAIL3', 'SERV3', 'HC3']

# PRODUCTION GOV
FG = ['CONST1', 'RETAIL1', 'SERV1', 'HC1', 'ACCOM1',
      'REST1', 'AG2', 'CONST2', 'MANUF2', 'RETAIL2', 'SERV2', 'HC2', 'ACCOM2',
      'REST2', 'AG3', 'UTIL', 'CONST3', 'RETAIL3', 'SERV3', 'HC3']

# HOUSING SERV.DEMAND
HD = ['HS1', 'HS2', 'HS3']

# SIMMLOOP
SM = ['BASE', 'TODAY', 'SIMM']

# EPORT 1 FOR SCALARS
R1H = ['GFREV', 'SFREV', 'PIT',
       'DGF', 'DSF', 'DDRE', 'PDRE', 'SPI', 'COMM', 'COMMO',
       'GN', 'NKI', 'HH', 'W', 'W1', 'W2', 'W3',
       'R', 'RL', 'L', 'K', 'HN', 'HW', 'GFSAV', 'LD',
       'CMO', 'CMI', 'HC', 'SSC', 'LAND', 'LAS']

# REPORT 2FOR STATUS
R2H = ['M-STAT', 'S-STAT']

# LABELS FOR MODEL STATUS
MS = ['OPTIMAL', 'LOCALOP', 'UNBOUND',
      'INFSBLE', 'INFSLOC', 'INFSINT',
      'NOOPTML', 'MIPSOLN', 'NOINTGR',
      'INFSMIP', 'UNUSED', 'UNKNOWN',
      'NOSOLUT']

# LABELS FOR SOLVER STATUS
SS = ['OK', 'ITERATE', 'RESRCE',
      'SOLVER', 'EVALUATE', 'NOTKNWN',
      'NOTUSED', 'PRE-PROC', 'SETUP',
      'SLVFAIL', 'SLVINTER', 'POST-PROC',
      'METSYS']

#HSSET(I)         HOUSING SERVICES
HSSET = ['HS1', 'HS2', 'HS3']

#HS23SET(I)       HOUSING SERVICES 2 & 3
HS23SET = ['HS2', 'HS3']

#HH1(H)           HOUSEHOLDS (INCOME 1)
HH1 = ['HH1']

#HH2(H)           HOUSEHOLDS (INCOME 2)
HH2 = ['HH2']

#HH3(H)           HOUSEHOLDS (INCOME 3)
HH3 = ['HH3']

#HH4(H)           HOUSEHOLDS (INCOME 4)
HH4 = ['HH4']

#HH5(H)           HOUSEHOLDS (INCOME 5)
HH5 = ['HH5']

#ETA              ELASTICITIES
ETA = ['ETAL1','ETAI1','ETALB1','ETAPIT','ETAPT','ETARA','NRPG','ETAYD','ETAU','ETAM','ETAE','ETAY','ETAOP']

#ETALANDCAP(ETA)  LANDCAP TABLE ELASTICITIES
ETALANDCAP = ['ETAL1', 'ETAI1', 'ETALB1']

#ETAMISCH(ETA)    MISCH TABLE ELASTICITIES
ETAMISCH = ['ETAPIT', 'ETAPT', 'ETARA', 'NRPG', 'ETAYD', 'ETAU']

#ETAMISC(ETA)  MISC TABLE ELASTICITIES
ETAMISC = ['ETAM','ETAE', 'ETAY', 'ETAOP']

#cf(G)
CF = ['CYGF']

# ----------------------------------------------------------------
# SET ALIASES
# ----------------------------------------------------------------

# ALIAS
J = I
I1 = I
Z1 = Z
F1 = F
G1 = G
G2 = G
GI1 = GI
GS1 = GS
GX1 = GX
GN1 = GN
GH1 = GH
GF1 = GF
H1 = H
HD1 = HD
JP = IP
JG = IG
GY1 = GY
GY2 = GY
GT1 = GT
GNL1 = GNL

# ----------------------------------------------------------------
# IMPORT ADDITIONAL DATA FILES
# ----------------------------------------------------------------

# SAM
SAM = pd.read_csv(os.path.join(filePath, 'SAM SeasideKC.csv'), index_col=0)

# CAPITAL COMP
BB = pd.read_csv(os.path.join(filePath, 'SEASIDE Capcom.csv'), index_col=0)

# MISC TABLES
'''

'''

TPC = pd.DataFrame(index=H, columns=G).fillna(0.0)
IGTD= pd.DataFrame(index=G, columns=G1).fillna(0.0)
TAUFF= pd.DataFrame(index=G, columns=F).fillna(0.0)
IOUT = pd.DataFrame(index=G1, columns=G1).fillna(0.0)
LANDCAP= pd.DataFrame(index=IG, columns=ETALANDCAP).fillna(0.0)
MISC = pd.DataFrame(index=Z, columns=ETAMISC).fillna(0.0)
MISCH= pd.DataFrame(index=H, columns=ETAMISCH).fillna(0.0)

miscPath = os.path.join(filePath, 'MiscFile')

#EMPLOY0 = pd.read_csv(os.path.join(miscPath, 'EMPLOY0(Z,F).csv'), index_col=0)
EMPLOY = pd.read_csv(os.path.join(miscPath, 'EMPLOY(Z,F).csv'),index_col=0)
JOBCR = pd.read_csv(os.path.join(miscPath, 'JOBCR(H,L).csv'), index_col=0)
#JOBCR1 = pd.read_csv(os.path.join(miscPath, 'JOBCR1(H,L).csv'), index_col=0)
HHTABLE = pd.read_csv(os.path.join(miscPath, 'HHTABLE(H,).csv'), index_col=0)
#OUTCR = pd.read_csv(os.path.join(miscPath, 'OUTCR(H,CM).csv'), index_col=0)

# ----------------------------------------------------------------
# PARAMETER DECLARATION
# ----------------------------------------------------------------

# these are data frames with zeros to be filled during calibration
A = pd.DataFrame(index=Z, columns=Z).fillna(0.0)
AD = pd.DataFrame(index=Z, columns=Z).fillna(0.0)
AG = pd.DataFrame(index=Z, columns=G).fillna(0.0)
AGFS = pd.DataFrame(index=Z, columns=G).fillna(0.0)
SIGMA = pd.Series(index=I).fillna(0.0)
ALPHA = pd.DataFrame(index=F, columns=I).fillna(0.0)
ALPHA1 = pd.DataFrame(index=F, columns=I).fillna(0.0)
B = pd.DataFrame(index=I, columns=IG).fillna(0.0)
B1 = pd.DataFrame(index=I, columns=I).fillna(0.0)
CMIWAGE = pd.Series(index=L).fillna(0.0)
FCONST = pd.DataFrame(index=F, columns=I).fillna(0.0)
GAMMA = pd.Series(index=I).fillna(0.0)
DELTA = pd.Series(index=I).fillna(0.0)
PIT = pd.DataFrame(index=G, columns=H).fillna(0.0)
PRIVRET = pd.Series(index=H).fillna(0.0)
LFOR = pd.Series(index=LA).fillna(0.0)
KFOR = pd.Series(index=K).fillna(0.0)
GFOR = pd.Series(index=G).fillna(0.0)
out = pd.DataFrame(index=G, columns=G).fillna(0.0)
TAUFH = pd.DataFrame(index=G, columns=F).fillna(0.0)
TAUFL = pd.DataFrame(index=G, columns=L).fillna(0.0)
TAUFLA = pd.DataFrame(index=G, columns=LA).fillna(0.0)
TAUFK = pd.DataFrame(index=G, columns=K).fillna(0.0)
TAUH = pd.DataFrame(index=G, columns=H).fillna(0.0)
TAUH0 = pd.DataFrame(index=G, columns=H).fillna(0.0)
TAUQ = pd.DataFrame(index=G, columns=IG).fillna(0.0)
TAUC = pd.DataFrame(index=G, columns=I).fillna(0.0)
TAUCH = pd.DataFrame(index=G, columns=HD).fillna(0.0)
TAUV = pd.DataFrame(index=G, columns=I).fillna(0.0)
TAUN = pd.DataFrame(index=G, columns=IG).fillna(0.0)
TAUX = pd.DataFrame(index=G, columns=IG).fillna(0.0)
TAUG = pd.DataFrame(index=G, columns=I).fillna(0.0)
TAXS = pd.DataFrame(index=G, columns=G).fillna(0.0)
TAXS1 = pd.Series(index=GNL).fillna(0.0)

# ELASTICITIES AND TAX DATA IMPOSED

BETA = pd.DataFrame(index=I, columns=H).fillna(0.0)
BETAH = pd.DataFrame(index=HD, columns=H).fillna(0.0)
ETAD = pd.Series(index=I).fillna(0.0)
ETAE = pd.Series(index=I).fillna(0.0)
ETAI = pd.Series(index=IG).fillna(0.0)
ETAIX = pd.DataFrame(index=K, columns=IG).fillna(0.0)
ETAL = pd.DataFrame(index=LA, columns=IG).fillna(0.0)
ETAL1 = pd.Series(index=IG).fillna(0.0)
ETALB1 = pd.Series(index=IG).fillna(0.0)
ETALB = pd.DataFrame(index=L, columns=IG).fillna(0.0)
ETAM = pd.Series(index=I).fillna(0.0)
ETAYD = pd.Series(index=H).fillna(0.0)
ETAYDO = pd.Series(index=H).fillna(0.0)
ETAYDI = pd.Series(index=H).fillna(0.0)
ETAU = pd.Series(index=H).fillna(0.0)
ETAUO = pd.Series(index=H).fillna(0.0)
ETAUI = pd.Series(index=H).fillna(0.0)
ETARA = pd.Series(index=H).fillna(0.0)
ETAPT = pd.Series(index=H).fillna(0.0)
ETAPIT = pd.Series(index=H).fillna(0.0)

EXWGEI = pd.Series(index=L).fillna(0.0)
ECOMI = pd.Series(index=L).fillna(0.0)

JOBCOR = pd.DataFrame(index=H, columns=L).fillna(0.0)

LAMBDA = pd.DataFrame(index=I, columns=I).fillna(0.0)
LAMBDAH = pd.DataFrame(index=HD, columns=HD1).fillna(0.0)

NRPG = pd.Series(index=H).fillna(0.0)
depr = pd.Series(index=IG).fillna(0.1)

RHO = pd.Series(index=I).fillna(0.0)

TT = pd.DataFrame(index=F, columns=IG).fillna(0.0)
# ARRAYS BUILT TO EXPORT RESULTS TO SEPARATE FILE

R1 = pd.DataFrame(index=R1H, columns=SM).fillna(0.0)
R2 = pd.DataFrame(index=R2H, columns=SM).fillna(0.0)

# INITIAL VALUES OF ENDOGENOUS VARIABLES

CG0 = pd.DataFrame(index=I, columns=G).fillna(0.0)
CG0T = pd.DataFrame(index=I, columns=G).fillna(0.0)
CH0 = pd.DataFrame(index=I, columns=H).fillna(0.0)
CH0T = pd.DataFrame(index=I, columns=H).fillna(0.0)
CMI0 = pd.Series(index=L).fillna(0.0)
CN0 = pd.Series(index=I).fillna(0.0)
CN0T = pd.Series(index=I).fillna(0.0)
CPI0 = pd.Series(index=H).fillna(0.0)
CPIN0 = pd.Series(index=H).fillna(0.0)
CPIH0 = pd.Series(index=H).fillna(0.0)
CX0 = pd.Series(index=I).fillna(0.0)
D0 = pd.Series(index=I).fillna(0.0)
DD0 = pd.Series(index=Z).fillna(0.0)
DS0 = pd.Series(index=Z).fillna(0.0)
DQ0 = pd.Series(index=Z).fillna(0.0)
FD0 = pd.DataFrame(index=F, columns=Z).fillna(0.0)
IGT0 = pd.DataFrame(index=G, columns=GX).fillna(0.0)
KS0 = pd.DataFrame(index=K, columns=IG).fillna(0.0)
KSNEW = pd.DataFrame(index=K, columns=IG).fillna(0.0)
KSNEW0 = pd.DataFrame(index=K, columns=IG).fillna(0.0)
LAS0 = pd.DataFrame(index=LA, columns=IG).fillna(0.0)
HH0 = pd.Series(index=H).fillna(0.0)
HN0 = pd.Series(index=H).fillna(0.0)
HW0 = pd.Series(index=H).fillna(0.0)
M0 = pd.Series(index=I).fillna(0.0)
M01 = pd.Series(index=Z).fillna(0.0)
MI0 = pd.Series(index=H).fillna(0.0)
MO0 = pd.Series(index=H).fillna(0.0)
N0 = pd.DataFrame(index=K, columns=IG).fillna(0.0)

# NKIO
KPFOR01 = pd.Series(index=K).fillna(0.0)
KPFOR0 = pd.Series(index=K).fillna(0.0)
LNFOR0 = pd.Series(index=LA).fillna(0.0)
LNFOR01 = pd.Series(index=LA).fillna(0.0)
GVFOR0 = pd.Series(index=G).fillna(0.0)
P0 = pd.Series(index=IG).fillna(0.0)
PH0 = pd.Series(index=HD).fillna(0.0)
PD0 = pd.Series(index=I).fillna(0.0)
PVA0 = pd.Series(index=I).fillna(0.0)
PWM0 = pd.Series(index=I).fillna(0.0)
PW0 = pd.Series(index=I).fillna(0.0)
Q0 = pd.Series(index=Z).fillna(0.0)
Q10 = pd.Series(index=Z).fillna(0.0)
R0 = pd.DataFrame(index=F, columns=Z).fillna(1.0)
RA0 = pd.Series(index=F).fillna(0.0)
S0 = pd.Series(index=Z).fillna(0.0)

# SPIO

V0 = pd.Series(index=I).fillna(0.0)
V0T = pd.Series(index=I).fillna(0.0)
TP = pd.DataFrame(index=H, columns=G).fillna(0.0)

# TAUF0 = Table(G,F,Z)

YD0 = pd.Series(index=H).fillna(0.0)
Y0 = pd.Series(index=Z).fillna(0.0)

for label in G1:
    out.loc[label,label]                       = 0
out.loc['FED', 'CYGF']              = 1

IGTD.loc[G,G1]                       = 0

IGTD.loc['CYGF', GFUS]                = 1
IGTD.loc['CYGF', 'STPIT']             = 1

IGTD.loc['CYGF', 'ACCTAX']          = 1
IGTD.loc['CYGF', 'LOCTAX']          = 1
IGTD.loc['CYGF', 'PROPTX']           = 1

TPC.loc[H,G]                         = 0
TPC.loc[H,GFUS]                      = 1

TAUFF.loc[G,F]                       = 0
TAUFF.loc['USSOCL1', 'L1']            = 1
TAUFF.loc['USSOCL2', 'L2']            = 1
TAUFF.loc['USSOCL3', 'L3']            = 1
TAUFF.loc['USSOCL4', 'L4']            = 1
TAUFF.loc['USSOCL5', 'L5']            = 1
TAUFF.loc['PROPTX', 'KAP']          = 1

for label in G1:
    IOUT.loc[label, label]                     = 0
IOUT.loc['FED', 'CYGF']             = 1

LANDCAP.loc[IG, ETALANDCAP] = 1
LANDCAP.loc['CONST1', 'ETAL1']       = 0.5
LANDCAP.loc['RETAIL1', 'ETAL1']      = 2
LANDCAP.loc['SERV1', 'ETAL1']        = 1.4
LANDCAP.loc['HC1', 'ETAL1']          = 1.4
LANDCAP.loc['ACCOM1', 'ETAL1']       = 0.5
LANDCAP.loc['REST1', 'ETAL1']       = 0.5
LANDCAP.loc['AG2', 'ETAL1']          = 0.5
LANDCAP.loc['CONST2', 'ETAL1']       = 0.5
LANDCAP.loc['MANUF2', 'ETAL1']       = 0.5
LANDCAP.loc['RETAIL2', 'ETAL1']      = 2
LANDCAP.loc['SERV2', 'ETAL1']        = 0.5
LANDCAP.loc['HC2', 'ETAL1']          = 0.5
LANDCAP.loc['ACCOM2', 'ETAL1']       = 0.5
LANDCAP.loc['REST2', 'ETAL1']        = 0.5
LANDCAP.loc['AG3', 'ETAL1']          = 0.5
LANDCAP.loc['UTIL', 'ETAL1']         = 1.4
LANDCAP.loc['CONST3', 'ETAL1']       = 1.4
LANDCAP.loc['RETAIL3', 'ETAL1']      = 2
LANDCAP.loc['SERV3', 'ETAL1']        = 1.4
LANDCAP.loc['HC3', 'ETAL1']          = 2
LANDCAP.loc['HS1', 'ETAL1']          = 2
LANDCAP.loc['HS2', 'ETAL1']          = 2
LANDCAP.loc['HS3', 'ETAL1']          = 2

MISCH.loc[H, ETAMISCH]               = 0
MISCH.loc[HH1, 'ETAPT']             = -0.5
MISCH.loc[HH2, 'ETAPIT']             = -0.15
MISCH.loc[HH3, 'ETAPIT']             = -0.2
MISCH.loc[HH4, 'ETAPIT']             = -0.25
MISCH.loc[HH5, 'ETAPIT']             = -0.35

MISCH.loc[H, 'NRPG']                 = 1
MISCH.loc[H, 'ETARA']                = 1

# DRAM
MISCH.loc[HH2, 'ETARA']                = 0.2
MISCH.loc[HH3, 'ETARA']                = 0.3
MISCH.loc[HH4, 'ETARA']                = 0.5
MISCH.loc[HH5, 'ETARA']                = 0.8

MISCH.loc[HH1, 'ETAYD']              = 1.3
MISCH.loc[HH2, 'ETAYD']              = 1.6
MISCH.loc[HH3, 'ETAYD']              = 1.8
MISCH.loc[HH4, 'ETAYD']              = 2.0
MISCH.loc[HH5, 'ETAYD']              = 2.1

MISCH.loc[HH1, 'ETAU']               = -0.8
MISCH.loc[HH2, 'ETAU']               = -0.6
MISCH.loc[HH3, 'ETAU']               = -0.5
MISCH.loc[HH4, 'ETAU']               = -0.4
MISCH.loc[HH5, 'ETAU']               = -0.3

MISC.loc[IG, ETAMISC]                = 0
MISC.loc[IP, 'ETAM']                 = 1
MISC.loc[IP, 'ETAE']                 = -3.65
MISC.loc[I, 'ETAY']                  = 1
MISC.loc[I, 'ETAOP']                 = -1

# CENTERVILLE MISC
#MISCH[H, 'ETAYD']                = 1;
#MISCH[H, 'ETAU']                 = -1;

#===============================================================================
# PARAMETERS AND ELASTICITIES
#===============================================================================

BETA.loc[I,H]        = MISC.loc[I,'ETAY'];
BETAH.loc[HD,H]      = MISC.loc[HD,'ETAY'];
for label in I:
    LAMBDA.loc[label,label] = MISC.loc[label,'ETAOP'];
for label in HD:
    LAMBDAH.loc[label,label] = MISC.loc[label,'ETAOP'];
ETAE.loc[I]          = MISC.loc[I,'ETAE'];
ETAM.loc[I]          = MISC.loc[I,'ETAM'];
ETARA.loc[H]         = MISCH.loc[H,'ETARA'];

ETAPIT.loc[H]        = MISCH.loc[H,'ETAPIT'];
ETAPT.loc[H]         = MISCH.loc[H,'ETAPT'];
ETAYD.loc[H]         = MISCH.loc[H,'ETAYD'];
ETAU.loc[H]          = MISCH.loc[H,'ETAU'];

ETAIX.loc['KAP',IG]  = LANDCAP.loc[IG,'ETAI1'];
ETAI.loc[IG]         = LANDCAP.loc[IG,'ETAI1'];
ETAL.loc['LAND',IG]  = LANDCAP.loc[IG,'ETAL1'];
ETALB.loc[L,IG]      = LANDCAP.loc[IG,'ETALB1'];

NRPG.loc[H]          = MISCH.loc[H,'NRPG'];

# EXPERIMENTAL ELASTICITIES
#ECOMI[L]         = 0.75;
#ECOMO[CM]        = 1.5;

# CENTERVILLE ELASTICITIES

ETARA.loc[H]          = 2.5;
#ETARA[H]          = 2.0;

ETAUI.loc[H]          = -1.5;
ETAUO.loc[H]          = -0.72;

ETAYDO.loc[H]         = 1.4;
ETAYDI.loc[H]         = 1.5;

#ETAIX['KAP',IG]  = 0.1*ETAIX['KAP',IG];
ETAIX.loc['KAP',IG]  = 0.1;
ETAE.loc[IP]          = -1.5;

# DRAM ELASTICITIES
#ETAUO[H]         = MISCH[H, 'ETAU'];
#ETAUI[H]         = MISCH[H, 'ETAU'];
#ETAE[IP]         = -1.65;

#ETAYDO[H]         = ETAYD[H];
#ETAYDI[H]         = ETAYD[H];

#ETAUI[H]          = ETAU[H];
#ETAUO[H]          = ETAU[H];

SIGMA.loc[I]         = 0.67;

# -------------------------------------------------------------------------------------------------------------
# CALCULATIONS OF PARAMETERS AND INITIAL VALUES
# -------------------------------------------------------------------------------------------------------------

Q10.loc[Z] = SAM.loc[Z].sum(0)  # Column Totals of SAM table
Q0.loc[Z] = SAM.loc[Z].sum(1)  # Row Totals of SAM table
DQ0.loc[Z] = Q10.loc[Z] - Q0.loc[Z]  # difference of SAM row and coloumn totals

Q10.loc[Z] = SAM.loc[Z].sum(0)  # Column Totals of SAM table
Q0.loc[Z] = SAM.loc[Z].sum(1)  # Row Totals of SAM table
DQ0.loc[Z] = Q10.loc[Z] - Q0.loc[Z]  # difference of SAM row and coloumn totals

B1.loc[I, I] = SAM.loc[I, I]

out.loc[G, G] = IOUT.loc[G, G]

HH0.loc[H] = HHTABLE.loc[H,'HH0']
HW0.loc[H] = HHTABLE.loc[H,'HW0']
HN0.loc[H] = HH0.loc[H] - HW0.loc[H]

MI0.loc[H] = HH0.loc[H] * 0.04
MO0.loc[H] = HH0.loc[H] * 0.04

FD0.loc[F, IG] = EMPLOY.loc[IG, F].T
JOBCOR.loc[H, L] = JOBCR.loc[H, L]

TAUQ_1 = SAM.loc[GS, I]
TAUQ_2 = SAM.loc[I, I].sum(1)
TAUQ_3 = SAM.loc[I, H].sum(1)
TAUQ_4 = SAM.loc[I, ['INVES']].sum(1)
TAUQ_5 = SAM.loc[I, G].sum(1)
TAUQ_6 = SAM.loc[I, ['ROW']].sum(1)
TAUQ_7 = SAM.loc[GS1, I].sum(0)

TAUQ.loc[GS, I] = TAUQ_1 / (TAUQ_2 + TAUQ_3 + TAUQ_4 + TAUQ_5 + TAUQ_6 - TAUQ_7)

# NOTE:
# set taxes to average if not specific to model
TAUC.loc[GS, I] = TAUQ.loc[GS, I]
TAUV.loc[GS, I] = TAUQ.loc[GS, I]
TAUN.loc[GS, I] = TAUQ.loc[GS, I]
TAUG.loc[GS, I] = TAUQ.loc[GS, I]
TAUX.loc[GS, I] = TAUQ.loc[GS, I]

TAUH.loc[GH, H] = SAM.loc[GH, H].div(HH0.loc[H], axis='columns')
TAUH0.loc[GH, H] = SAM.loc[GH, H].div(HH0.loc[H], axis='columns')

TAUFarray = [[[0 for k in range(len(Z))] for j in range(len(F))] for i in range(len(G))]
for i in range(len(GF)):
    for j in range(len(F)):
        for k in range(len(I)):
            if SAM.loc[F[j], I[k]] != 0 and TAUFF.loc[GF[i], F[j]] != 0:
                TAUFarray[G.index(GF[i])][j][Z.index(I[k])] = SAM.loc[GF[i], I[k]] / SAM.loc[F[j], I[k]]

for i in range(len(GF)):
    for j in range(len(F)):
        for k in range(len(G)):
            if SAM.loc[F[j], G[k]] != 0 and TAUFF.loc[GF[i], F[j]] != 0:
                TAUFarray[G.index(GF[i])][j][Z.index(G[k])] = SAM.loc[GF[i], G[k]] / SAM.loc[F[j], G[k]]

TAUFX_SUM_array = [[0 for j in range(len(Z))] for i in range(len(F))]
for i in range(len(F)):
    for j in range(len(Z)):
        tmp = 0
        for k in range(len(G)):
            tmp += TAUFarray[k][i][j]
        TAUFX_SUM_array[i][j] = tmp

# TAUFX summed over GX
TAUFX_SUM = pd.DataFrame(TAUFX_SUM_array, index=F, columns=Z).fillna(0.0)

TAUFX_GF = pd.DataFrame(TAUFX_SUM_array, index=F, columns=Z).fillna(0.0)

TAUFXgx = {}
for i in range(len(GX)):
    TAUFXgx[GX[i]] = pd.DataFrame(TAUFarray[i], index=F, columns=Z).fillna(0.0)

# TAUFH(GF,F)$(TAUFF(GF,F)) =SAM(GF,F) / SUM(Z, SAM(Z,F));
for i in GF:
    for j in F:
        if TAUFF.loc[i, j] != 0:
            TAUFH.set_value(i, j, SAM.loc[i, j] / SAM.loc[Z, F].sum(0).loc[j])

# TAUFH(GF,L)  =SAM(GF,L) / SUM(L, SAM(L,IG));
for i in GF:
    for j in L:
        if TAUFF.loc[i, j] != 0:
            TAUFH.set_value(i, j, SAM.loc[i, j] / SAM.loc[L, IG].sum(1).loc[j])

TAUFL.loc[GF, L] = SAM.loc[GF, L] / SAM.loc[Z, L].sum(0)

TAUFLA.loc[GF, LA] = SAM.loc[GF, LA] / SAM.loc[Z, LA].sum(0)

TAUFK.loc[GF, K] = SAM.loc[GF, K] / SAM.loc[Z, K].sum(0)

TAXS.loc[G, GX] = SAM.loc[G, GX] / SAM.loc[G, GX].sum(0)

TAXS1.loc[GNL] = SAM.loc[GNL, ['CYGF']].sum(1) / SAM.loc[GNL, ['CYGF']].sum(1).sum(0)

IGT0.loc[G, GX] = SAM.loc[G, GX]

PWM0.loc[I] = 1.0
PW0.loc[I] = 1.0
P0.loc[I] = 1.0
PH0.loc[HD] = 1.0
PD0.loc[I] = 1.0
CPI0.loc[H] = 1.0
CPIN0.loc[H] = 1.0
CPIH0.loc[H] = 1.0
TT.loc[F,IG] = 1.0
EXWGEI.loc[L] = 1.0
R0.loc[F,Z] = 1.0
RA0.loc[F] = 1.0

R0.loc[F, IG] = (SAM.loc[F, IG] / EMPLOY.loc[IG, F].T).fillna(1.0)

TP.loc[H, G] = SAM.loc[H, G].div(HH0.loc[H], axis='index').fillna(0.0)

KS0.loc[K, IG] = FD0.loc[K, IG]
KSNEW0.loc[K, IG] = KS0.loc[K, IG]
LAS0.loc[LA, IG] = FD0.loc[LA, IG]

DEPR = float((SAM.loc[IG, ["INVES"]].sum(0)) / (KS0.loc[K, IG].sum(1).sum(0)))

A.loc[Z, Z] = SAM.loc[Z, Z].div(Q0.loc[Z], axis='columns')

AG_1 = SAM.loc[I, G]
AG_2 = SAM.loc[I, G].sum(0) + SAM.loc[F, G].sum(0) + SAM.loc[GF, G].sum(0)
AG.loc[I, G] = AG_1 / AG_2

# correct gov. transfers for model with commuting
AGFS.loc['L1', G] = SAM.loc['L1', G] + SAM.loc['USSOCL1', G]
AGFS.loc['L2', G] = SAM.loc['L2', G] + SAM.loc['USSOCL2', G]
AGFS.loc['L3', G] = SAM.loc['L3', G] + SAM.loc['USSOCL3', G]
AGFS.loc['L4', G] = SAM.loc['L4', G] + SAM.loc['USSOCL4', G]
AGFS.loc['L5', G] = SAM.loc['L5', G] + SAM.loc['USSOCL5', G]

AG_1 = SAM.loc[F, G]
AG.loc[F, G] = AG_1 / AG_2

AG_1 = AGFS.loc[L, G]
AG.loc[L, G] = AG_1 / AG_2
AG = AG.fillna(0.0)

CX0.loc[I] = SAM.loc[I, ["ROW"]].div(P0.loc[I], axis='index').div(1.0 + TAUQ.loc[GS, I].sum(0), axis='index').sum(1)

M01.loc[I] = SAM.loc[["ROW"], I].sum(0) / PWM0[I].T

M0.loc[IP] = SAM.loc[IP, Z].sum(1) - (B1.loc[I, IP].sum(0) + SAM.loc[F, IP].sum(0) + SAM.loc[G, IP].sum(0))

M0.loc[I] = (M0[I] / PWM0[I])
M0 = M0.fillna(0.0)

V0.loc[I] = SAM.loc[I, I].sum(1) / P0.loc[I] / (1.0 + TAUQ.loc[GS, I].sum(0))

V0T.loc[I] = SAM.loc[I, I].sum(1) / P0.loc[I]

CH0.loc[I, H] = SAM.loc[I, H].div(P0.loc[I], axis='index').div(1.0 + TAUQ.loc[GS, I].sum(0), axis='index')

CH0T.loc[I, H] = SAM.loc[I, H].div(P0[I], axis='index')

CG0.loc[I, GN] = SAM.loc[I, GN].div(P0.loc[I], axis='index').div((1.0 + TAUQ.loc[GS, I].sum(0)), axis='index')

CG0T.loc[I, GN] = SAM.loc[I, GN].div(P0.loc[I], axis='index')

DEPR = float((SAM.loc[IG, ["INVES"]].sum(0)) / (KS0.loc[K, IG].sum(1).sum(0)))

N0.loc[K, IG] = KS0.loc[K, IG] * DEPR

CN0.loc[I] = 0.0

B.loc[I,IG] = BB.loc[I,IG].fillna(0.0)

CN0.loc[I] = B.loc[I, IG].mul(N0.loc[K, IG].sum(0), axis='columns').sum(1).div(P0.loc[I], axis='index').div(
    1.0 + TAUQ.loc[GS, I].sum(0), axis='index').transpose()

CN0T.loc[I] = B.loc[I, IG].mul(N0.loc[K, IG].sum(0), axis='columns').sum(1).div(P0.loc[I], axis='index')

DD0.loc[I] = CH0.loc[I, H].sum(1) + CG0.loc[I, G].sum(1) + CN0.loc[I] + V0.loc[I]

D0.loc[I] = 1.0 - M0.loc[I] / DD0.loc[I]

ETAD.loc[I] = -1.0 * ETAM.loc[I] * M0.loc[I] / (DD0.loc[I] * D0.loc[I])

DS0.loc[I] = DD0.loc[I] + CX0.loc[I] - M0.loc[I];

AD.loc[I, I] = SAM.loc[I, I].div(P0.loc[I], axis='index').div(1.0 + TAUQ.loc[GS, I].sum(0), axis='index') / DS0.loc[I]

PVA0.loc[I] = PD0.loc[I] - (AD.loc[I, I].mul(P0.loc[I], axis='index').mul(1.0 + TAUQ.loc[GS, I].sum(0).T, axis='index').sum(0).T)

RHO.loc[I] = (1 - SIGMA.loc[I])/SIGMA.loc[I];
#RA0.loc[F] = 1.0

# create data frame for factor taxes by sector

a = pd.Series(index=I).fillna(0.0)
a = SAM.loc[USSOCL, I].append(a, ignore_index=True).append(SAM.loc[GL, I]) # labor, land, capital
a.index = F

ALPHA.loc[F, I] = (SAM.loc[F, I] + a.loc[F, I]) / (SAM.loc[F, I].sum(0) + SAM.loc[GF, I].sum(0))
ALPHA.loc[F, I] = ALPHA.loc[F, I] / ALPHA.loc[F, I].sum(0)

# GAMMA(I)    = DS0(I) / ( SUM(F, ALPHA(F,I) *  FD0(F,I)) ** ( - RHO(I) ) ) ** ( -1 / RHO(I) );
GAMMA.loc[I] = DS0.loc[I] / (((ALPHA.loc[F, I] * FD0.loc[F, I] ** (RHO.loc[I])).sum(0) ) ** (1 / RHO.loc[I]))

# DELTA(I) = DS0(I)/ (PROD(F$ALPHA(F,I),FD0(F,I)**ALPHA(F,I)));
# replace takes care of multiplying by zeros, by changing zeros to ones.
DELTA.loc[I] = DS0.loc[I] / (FD0.loc[F, I] ** ALPHA.loc[F, I]).replace({0: 1}).product(0)

# OTHER DATA

PRIVRET.loc[H] = SAM.loc[Z, H].sum(0) - (SAM.loc[H, F].sum(1) + SAM.loc[H, GX].sum(1))

PRIVRET.loc[H] = PRIVRET.loc[H]/HH0.loc[H]

# Y0(F)= SUM(IG, SAM(F,IG) );
Y0.loc[F] = SAM.loc[F, IG].sum(1)

KPFOR01.loc[K] = SAM.loc[K, ["ROW"]].sum(1)

KPFOR0[K] = SAM.loc[Z, K].sum(0).T - SAM.loc[K, IG].sum(1)

LNFOR01.loc[LA] = SAM.loc[K, ["ROW"]].sum(1)

LNFOR0.loc[LA] = SAM.loc[Z, LA].sum(0).T - SAM.loc[LA, IG].sum(1)

GVFOR0.loc[G] = SAM.loc[G, ["ROW"]].sum(1)

GVFOR0.loc[GT] = SAM.loc[Z, GT].sum(0) - (
        SAM.loc[GT, I].sum(1)
        + SAM.loc[GT, F].sum(1)
        + SAM.loc[GT, H].sum(1)
        + SAM.loc[GT, G].sum(1)
        )

A.loc[H, L] = SAM.loc[H, L].div(HW0.loc[H], axis='index') / (
        Y0.loc[L] + SAM.loc[Z, L].sum(0) - SAM.loc[L, IG].sum(1)) * (1.0 - TAUFL.loc[G, L].sum(0))

A.loc[H, K] = SAM.loc[H, K].div(HW0.loc[H], axis='index') / (
        Y0.loc[K] + SAM.loc[Z, K].sum(0) - SAM.loc[K, IG].sum(1))

A.loc[H, LA] = SAM.loc[H, LA].div(HW0.loc[H], axis='index') / (
        Y0.loc[LA] + SAM.loc[Z, LA].sum(0) - SAM.loc[LA, IG].sum(1)) * (1.0 - TAUFLA.loc[G, LA].sum(0))

S0.loc[H] = SAM.loc[["INVES"], H].T.sum(1)

YD0.loc[H] = SAM.loc[I, H].sum(0).T + S0.loc[H]

Y0.loc[G] = SAM.loc[G, Z].sum(1) - SAM.loc[G, ["ROW"]].sum(1)

S0.loc[G] = SAM.loc[["INVES"], G].sum(0)

LFOR.loc[LA] = LNFOR0.loc[LA] / SAM.loc[["LAND"], IG].sum(1)

KFOR.loc[K] = KPFOR0.loc[K] / SAM.loc[["KAP"], IG].sum(1)

GFOR.loc[G] = GVFOR0.loc[G] / Y0.loc[G]

NKI0 = (M0.loc[I] * PWM0.loc[I]).sum(0) - (CX0.loc[I] * PD0.loc[I]).sum(0) - \
       (PRIVRET.loc[H] * HH0.loc[H]).sum(0) - LNFOR0.loc[LA].sum(0) - \
       KPFOR0.loc[K].sum(0) - GVFOR0.loc[G].sum(0)

Y0.loc[H] = (A.loc[H, L].mul(HW0[H], axis='index').div(A.loc[H, L].mul(HW0[H], axis='index').sum(0), axis='columns') \
      .mul(Y0.loc[L] - (CMIWAGE.loc[L] * CMI0.loc[L]), axis='columns').mul(1.0 - TAUFL.loc[G, L].sum(0), axis='columns')).sum(1) \
      + (A.loc[H, LA].mul(HW0[H], axis='index').div(A.loc[H, LA].mul(HW0[H], axis='index').sum(0), axis='columns') \
         * (Y0.loc[LA] * (1.0 - TAUFLA.loc[G, LA].sum(0)) + LNFOR0.loc[LA])).sum(1) \
         + (A.loc[H, K].mul(HW0[H], axis='index') / A.loc[H, K].mul(HW0[H], axis='index').sum(0) \
            * (Y0[K] * (1.0 - TAUFK.loc[G, K].sum(0)) + KPFOR0.loc[K])).sum(1)

SPI0 = (Y0.loc[H].sum(0) +
        TP.loc[H, G].mul(HH0.loc[H], axis='index').sum(1).sum(0) +
        (PRIVRET[H] * HH0[H]).sum(0))

PIT.loc[GI, H] = SAM.loc[GI, H].div(Y0[H], axis='columns')

TAUH.loc[GH, H] = SAM.loc[GH, H].div(HH0.loc[H], axis='columns')

TAUH0.loc[GH, H] = SAM.loc[GH, H] / HH0.loc[H]

MI0.loc[H] = HH0.loc[H] * 0.04

MO0.loc[H] = HH0.loc[H] * 0.04

GCP0 = CH0.loc[I, H].sum(1).sum(0) + CN0.loc[I].sum(0) + CG0.loc[I, GN].sum(1).sum(0) + CX0.loc[I].sum(0) - M0.loc[I].sum(0)

KSNEW0.loc[K, IG] = KS0.loc[K, IG]

KSNEW.loc[K, IG] = KSNEW0.loc[K, IG]

###########################################
# VARIABLE DECLARATION
###########################################

vars = VarContainer()

# PUBLIC CONSUMPTION
CG = vars.add('CG', rows=I, cols=G)

# PRIVATE CONSUMPTION
CH = vars.add('CH', rows=I, cols=H)

# GROSS INVESTMENT BY SECTOR OF SOURCE
CN = vars.add('CN', rows=I)

# CONSUMER PRICE INDEX
CPI = vars.add('CPI', rows=H)

# EXPORT DEMAND
CX = vars.add('CX', rows=I)

# DOMESTIC SHARE OF DOMESTIC DEMAND
D = vars.add('D', rows=I)

# DOMESTIC DEMAND
DD = vars.add('DD', rows=I)

# DOMESTIC SUPPLY
DS = vars.add('DS', rows=I)

# SECTORAL FACTOR DEMAND
FD = vars.add('FD', rows=F, cols=Z)

# NUMBER OF HOUSEHOLDS
HH = vars.add('HH', rows=H)

# NUMBER OF NONWORKING HOUSEHOLDS
HN = vars.add('HN', rows=H)

# NUMBER OF WORKING HOUSEHOLDS
HW = vars.add('HW', rows=H)

# INTER GOVERNMENTAL TRANSFERS
IGT = vars.add('IGT', rows=G, cols=GX)

# CAPITAL FLOW
KS = vars.add('KS', rows=K, cols=IG)

# LAND FLOW
LAS = vars.add('LAS', rows=LA, cols=IG)

# IMPORTS
M = vars.add('M', rows=I)

# GROSS INVESTMENT BY SECTOR OF DESTINATION
N = vars.add('N', rows=K, cols=IG)

# NET CAPITAL INFLOW
NKI = vars.add('NKI')

# LAND OUTFLOW
LNFOR = vars.add('LNFOR', rows=LA)

# CAPITAL OUTFLOW
KPFOR = vars.add('KPFOR', rows=K)

# GOVT OUTFLOW
GVFOR = vars.add('GVFOR', rows=G)

# AGGREGATE DOMESTIC PRICE PAID BY PURCHASERS
P = vars.add('P', rows=I)

# DOMESTIC PRICE RECEIVED BY SUPPLIERS
PD = vars.add('PD', rows=I)

# VALUE ADDED PRICE
PVA = vars.add('PVA', rows=I)

# ECONOMY WIDE SCALAR RENTAL RATES OF FACTORS
RA = vars.add('RA', rows=F)

# SECTORAL RENTAL RATES
R = vars.add('R', rows=F, cols=Z)

# SAVINGS
S = vars.add('S', rows=Z)

# PERSONAL INCOME (OBJECTIVE FUNCTION)
SPI = vars.add('SPI')

# INTERMEDIATE GOODS
V = vars.add('V', rows=I)

# GROSS INCOMES
Y = vars.add('Y', rows=Z)

# AFTER TAX TOTAL HOUSEHOLD INCOMES
YD = vars.add('YD', rows=H)

# OUT COMMUTERS
#CMO = vars.add('CMO', rows=CM)

# IN COMMUTERS
#CMI = vars.add('CMI', rows=L)

###########################################
# INITIALIZE VARIABLES FOR SOLVER
###########################################

vars.init('CG', CG0.loc[I, G])
vars.init('CH', CH0.loc[I, H])
vars.init('CN', CN0.loc[I])
vars.init('CPI', CPI0.loc[H])
vars.init('CX', CX0.loc[I])
vars.init('D', D0.loc[I])
vars.init('DD', DD0.loc[I])
vars.init('DS', DS0.loc[I])
vars.init('FD', FD0.loc[F, Z])
vars.init('HH', HH0.loc[H])
vars.init('HN', HN0.loc[H])
vars.init('HW', HW0.loc[H])
vars.init('IGT', IGT0.loc[G, GX])
vars.init('KS', KS0.loc[K, IG])
vars.init('LAS', LAS0.loc[LA, IG])
vars.init('M', M0.loc[I])
vars.init('N', N0.loc[K, IG])
vars.init('NKI', NKI0)
vars.init('LNFOR', LNFOR0.loc[LA])
vars.init('KPFOR', KPFOR0.loc[K])
vars.init('GVFOR', GVFOR0.loc[G])
vars.init('P', P0.loc[I])
vars.init('PD', PD0.loc[I])
vars.init('PVA', PVA0.loc[I])
vars.init('RA', RA0.loc[F])
vars.init('R', R0.loc[F, Z])
vars.init('S', S0.loc[Z])
vars.init('SPI', SPI0)
vars.init('V', V0.loc[I])
vars.init('Y', Y0.loc[Z])
vars.init('YD', YD0.loc[H])
#vars.init('CMO', CMO0.loc[CM])
#vars.init('CMI', CMI0.loc[L])

#-------------------------------------------------------------------------------------------------------------
# DEFINE BOUNDS FOR VARIABLES
#-------------------------------------------------------------------------------------------------------------

vars.lo('P',vars.get('P')/1000); vars.up('P',vars.get('P')*1000)
vars.lo('PD',vars.get('PD')/1000); vars.up('PD',vars.get('PD')*1000)
vars.lo('PVA',vars.get('PVA')/1000); vars.up('PVA',vars.get('PVA')*1000)
vars.lo('RA',vars.get('RA')/1000); vars.up('RA',vars.get('RA')*1000)
vars.lo('CPI',vars.get('CPI')/1000); vars.up('CPI',vars.get('CPI')*1000)
vars.lo('DS',vars.get('DS')/1000); vars.up('DS',vars.get('DS')*1000)
vars.lo('DD',vars.get('DD')/1000); vars.up('DD',vars.get('DD')*1000)
vars.lo('D',vars.get('D')/1000); vars.up('D',vars.get('D')*1000)
vars.lo('V',vars.get('V')/1000); vars.up('V',vars.get('V')*1000)
vars.lo('FD',vars.get('FD')/1000); vars.up('FD',vars.get('FD')*1000)
vars.lo('HH',vars.get('HH')/1000); vars.up('HH',vars.get('HH')*1000)
vars.lo('HW',vars.get('HW')/1000); vars.up('HW',vars.get('HW')*1000)
vars.lo('HN',vars.get('HN')/1000); vars.up('HN',vars.get('HN')*1000)
vars.lo('KS',vars.get('KS')/1000); vars.up('KS',vars.get('KS')*1000)
vars.lo('LAS',vars.get('LAS')/1000); vars.up('LAS',vars.get('LAS')*1000)
vars.lo('M',vars.get('M')/1000); vars.up('M',vars.get('M')*1000)
vars.lo('Y',vars.get('Y')/1000); vars.up('Y',vars.get('Y')*1000)
vars.lo('YD',vars.get('YD')/1000); vars.up('YD',vars.get('YD')*1000)
vars.lo('CH',vars.get('CH')/1000); vars.up('CH',vars.get('CH')*1000)
vars.lo('CG',vars.get('CG')/1000); vars.up('CG',vars.get('CG')*1000)
vars.lo('CX',vars.get('CX')/1000); vars.up('CX',vars.get('CX')*1000)
vars.lo('R',vars.get('R')/1000); vars.up('R',vars.get('R')*1000)
#vars.lo('CMI',vars.get('CMI')/1000); vars.up('CMI',vars.get('CMI')*1000)
#vars.lo('CMO',vars.get('CMO')/1000); vars.up('CMO',vars.get('CMO')*1000)
vars.lo('N',0)
vars.lo('CN',0)

def set_variable(filname):

  # clear the file before write the variables
  with open(filename, 'w') as f:
    f.write("")

  vars.write(filename)

#-------------------------------------------------------------------------------------------------------------
# DEFINE EQUATIONS AND SET CONDITIONS
#-------------------------------------------------------------------------------------------------------------

def set_equation(filename):

  count = [0]

#   CPIEQ(H)..
#   CPI(H)=E=
#   SUM(I, P(I) * ( 1 + SUM(GS, TAUC(GS,I) ) ) * CH(I,H) )
#       / SUM(I, P0(I) * ( 1 + SUM(GS, TAUQ(GS,I) ) ) * CH(I,H) );
  print('CPIEQ(H)')
  line1 = (P.loc(I) * ExprM(vars, m = 1 + TAUC.loc[GS,I].sum(0)) * CH.loc(I,H)).sum(I)
  line2 = (ExprM(vars, m = P0.loc[I] * (1 + TAUQ.loc[GS,I].sum(0)) ) * CH.loc(I,H)).sum(I)

  CPIEQ = (line1 / line2 - ~CPI.loc(H))
  print(CPIEQ.test(vars.initialVals))
  CPIEQ.write(count,filename)

  #YEQ(H).. Y(H)            =E= SUM(L,  A(H,L) * HW(H) / SUM(H1, A(H1,L) * HW(H1) )
  #                                * Y(L) * ( 1 - SUM(G, TAUFL(G,L))))
  #                               + SUM(LA,  A(H,LA) * HW(H) / SUM(H1, A(H1,LA) * HW(H1)) * (Y(LA)+ LNFOR(LA))*( 1 - SUM(G, TAUFLA(G,LA) ) ) )
  #                              + SUM(K,  A(H,K) * HW(H) / SUM(H1, A(H1,K) * HW(H1)) * (Y(K) + KPFOR(K)) * ( 1 - SUM(G, TAUFK(G,K) ) ) );

  print('YEQ(H)')
  line1 = (ExprM(vars, m= A.loc[H,L]) * HW.loc(H) / (ExprM(vars, m= A.loc[H1,L]) * HW.loc(H1)).sum(H1) * Y.loc(L) * ExprM(vars, m = 1-TAUFL.loc[G,L].sum(0))).sum(L)
  #line2 = (ExprM(vars, m= A.loc[H,CM] * CMOWAGE.loc[CM])*CMO.loc(CM)).sum(CM)
  line3 = (ExprM(vars, m= A.loc[H,LA]) * HW.loc(H) / (ExprM(vars, m= A.loc[H1,LA]) * HW.loc(H1)).sum(H1) * (Y.loc(LA) + LNFOR.loc(LA) ) * ExprM(vars, m= 1 - TAUFLA.loc[G,LA].sum(0))).sum(LA)
  line4 = (ExprM(vars, m= A.loc[H,K]) * HW.loc(H) / (ExprM(vars, m= A.loc[H1,K]) * HW.loc(H1)).sum(H1) * (Y.loc(K) + KPFOR.loc(K)) * ExprM(vars, m= 1 - TAUFK.loc[G,K].sum(0))).sum(K)

  YEQ = ((line1 + line3 + line4) - Y.loc(H))
  print(YEQ.test(vars.initialVals))
  YEQ.write(count,filename)
  # print(YEQ)

#  YDEQ(H).. YD(H)          =E=   Y(H) + (PRIVRET(H) * HH(H))
#                                         + SUM(G, TP(H,G) * HH(H))
#                                         - SUM(GI, PIT(GI,H)  * Y(H))
#                                         - SUM(G, TAUH(G,H)  * HH(H));
  print('YDEQ(H)')
  line1 = Y.loc(H) + ExprM(vars, m= PRIVRET.loc[H]) * HH.loc(H)
  line2 = (ExprM(vars, m = TP.loc[H,G]) * HH.loc(H)).sum(G)
  line3 = ~(ExprM(vars, m = PIT.loc[GI,H]) * Y.loc(H)).sum(GI)
  line4 = ~(ExprM(vars, m = TAUH.loc[G,H]) * HH.loc(H)).sum(G)

  YDEQ = ((line1 + line2 - line3 - line4) - YD.loc(H))
  YDEQ.write(count,filename)
  print(YDEQ.test(vars.initialVals))
  # print(YDEQ)

#  CHEQ(I,H).. CH(I,H)      =E= CH0(I,H)* ((YD(H) / YD0(H)) / ( CPI(H) / CPI0(H)))**(BETA(I,H))
#                                 * PROD(J, ((P(J)*( 1 + SUM(GS, TAUC(GS,J))))/ (P0(J)*(1 + SUM(GS, TAUQ(GS,J)))))** (LAMBDA(J,I)));
  print('CHEQ(I,H)')
  line1 = ExprM(vars,m=CH0.loc[I,H]) * ((YD.loc(H) / ExprM(vars,m=YD0.loc[H])) / (CPI.loc(H) / ExprM(vars, m=CPI0.loc[H]) )) ** ExprM(vars,m=BETA.loc[I,H])
  line2 = (((P.loc(J) * ExprM(vars, m = 1 + TAUC.loc[GS,J].sum(0))) / (ExprM(vars, m= P0.loc[J])*ExprM(vars, m = 1 + TAUQ.loc[GS,J].sum(0))))**ExprM(vars, m =LAMBDA.loc[J,I])).prod(0)

  CHEQ = ((line1 * line2) - CH.loc(I, H))
  CHEQ.write(count,filename)
  print(CHEQ.test(vars.initialVals))
  # print(CHEQ)

#  SHEQ(H).. S(H)           =E= YD(H) - SUM(I, P(I) * CH(I,H) * ( 1 + SUM(GS, TAUC(GS,I))));
  print('SHEQ(H)')
  line = YD.loc(H) - ~((P.loc(I) * CH.loc(I,H) * ExprM(vars, m = 1 + TAUC.loc[GS,I].sum(0))).sum(I))

  SHEQ = (line - S.loc(H))
  SHEQ.write(count,filename)
  print(SHEQ.test(vars.initialVals))
  # print(SHEQ)

#  PVAEQ(I).. PVA(I)        =E= PD(I) - SUM(J, AD(J,I) * P(J) * (1 + SUM(GS, TAUQ(GS, J))));
  print('PVAEQ(I)')
  line = PD.loc(I) - ~((ExprM(vars, m = AD.loc[J,I]) * P.loc(J)* ExprM(vars, m = 1 + TAUQ.loc[GS, J].sum(0))).sum(0))

  PVAEQ = (line- PVA.loc(I))
  PVAEQ.write(count,filename)
  print(PVAEQ.test(vars.initialVals))
  # print(PVAEQ)

#  PFEQ(I)..DS(I)           =E= DELTA(I)*PROD(F, (FD(F,I))**ALPHA(F,I));
  print('PFEQ(I)')
  line =  ExprM(vars, m =DELTA.loc[I]) *((FD.loc(F, I)) ** ExprM(vars, m = ALPHA.loc[F, I])).prod(F)

  PFEQ = (line - DS.loc(I))
  PFEQ.write(count,filename)
  # print(PFEQ)

# FDEQ(F,I).. R(F,I) * RA(F) * (1 + SUM(GF,TAUFX(GF,F,I) ) )* (FD(F,I))
#                         =E= PVA(I) * DS(I) * ALPHA(F,I);
  print('FDEQ(F,I)')
  left = R.loc(F,I) * RA.loc(F) * ExprM(vars, m = 1 + TAUFX_SUM.loc[F,I])* (FD.loc(F,I))
  right = ~(PVA.loc(I) * DS.loc(I) * ExprM(vars, m = ALPHA.loc[F, I]))

  FDEQ = (right - left)

  #FDEQ.test(vars.initialVals)
  FDEQ.write(count,filename)
  # print(FDEQ)

#   VEQ(I).. V(I) =E= SUM(J, AD(I,J) * DS(J) );
  print('VEQ(I)')
  line = (ExprM(vars, m = AD.loc[I,J]) * ~DS.loc(J)).sum(1)

  VEQ = (line - V.loc(I))
  VEQ.write(count,filename)
  print(VEQ.test(vars.initialVals))
  # print(VEQ)

#   YFEQL(L).. Y(L) =E= SUM(IG, R(L,IG)* RA(L)*FD(L,IG));
  print('YFEQL(L)')
  line = (R.loc(L,IG)* RA.loc(L)*FD.loc(L,IG)).sum(IG)

  YFEQL = (line - Y.loc(L))
  YFEQL.write(count,filename)
  print(YFEQL.test(vars.initialVals))
  # print(YFEQL)

  # YFEQK(K).. Y('KAP') =E= SUM(IG, R('KAP',IG) * RA('KAP') * FD('KAP',IG));
  print('YFEQK(K)')
  line = (R.loc(['KAP'],IG) * RA.loc(['KAP']) * FD.loc(['KAP'],IG)).sum(IG)

  YFEQK = (line - Y.loc(['KAP']))
  YFEQK.write(count,filename)
  print(YFEQK.test(vars.initialVals))
  # print(YFEQK)

#  YFEQLA(LA).. Y('LAND')   =E= SUM(IG, R('LAND',IG) * RA('LAND') * FD('LAND',IG));
  print('YFEQLA(LA)')
  line = (R.loc(['LAND'],IG) * RA.loc(['LAND']) * FD.loc(['LAND'],IG)).sum(IG)

  YFEQLA = (line - Y.loc(['LAND']))
  YFEQLA.write(count,filename)
  print(YFEQLA.test(vars.initialVals))
  # print(YFEQLA)

#  LANFOR(LA).. LNFOR(LA)   =E= LFOR(LA) * Y(LA);
  print('LANFOR(LA)')
  line = ExprM(vars, m = LFOR.loc[LA])*Y.loc(LA)

  LANFOR = (line - LNFOR.loc(LA))
  LANFOR.write(count,filename)
  print(LANFOR.test(vars.initialVals))
  # print(LANFOR)

#  KAPFOR(K).. KPFOR(K)     =E= KFOR(K) * Y(K);
  print('KAPFOR(K)')
  line = ExprM(vars, m = KFOR.loc[K])*Y.loc(K)

  KAPFOR = (line - KPFOR.loc(K))
  KAPFOR.write(count,filename)
  print(KAPFOR.test(vars.initialVals))
  # print(KAPFOR)

#  XEQ(I).. CX(I)           =E= CX0(I)*((PD(I))/(PWM0(I)))**(ETAE(I));
  print('XEQ(I)')
  line = ExprM(vars, m = CX0.loc[I]) * ((PD.loc(I))/ExprM(vars, m = PW0.loc[I]))** ExprM(vars, m = ETAE.loc[I])

  XEQ = (line - CX.loc(I))
  XEQ.write(count,filename)
  print(XEQ.test(vars.initialVals))
  # print(XEQ)

#  DEQ(I)$PWM0(I).. D(I)    =E= D0(I) *(PD(I)/PWM0(I))**(ETAD(I));
  print('DEQ(I)$PWM0(I)')
  line = ExprM(vars, m = D0.loc[I]) * ( PD.loc(I) / ExprM(vars, m = PWM0.loc[I]))** ExprM(vars, m = ETAD.loc[I])

  DEQ =  (line - D.loc(I))
#  DEQ.setCondition(PWM0.loc[I])
  DEQ.write(count,filename)
  print(DEQ.test(vars.initialVals))
  # print(DEQ)

#  PEQ(I)..  P(I)           =E= D(I) * PD(I) + ( 1 - D(I) ) * PWM0(I);
  print('PEQ(I)')
  line = (D.loc(I)*PD.loc(I) + (1 - D.loc(I)) * ExprM(vars, m = PWM0.loc[I]))

  PEQ = (line - P.loc(I))
  PEQ.write(count,filename)
  print(PEQ.test(vars.initialVals))
  # print(PEQ)

#  MEQ(I).. M(I)            =E= ( 1 - D(I) ) * DD(I);
  print('MEQ(I)')
  line = ( 1 - D.loc(I)) * DD.loc(I)

  MEQ = (line - M.loc(I))
  MEQ.write(count,filename)
  print(MEQ.test(vars.initialVals))
  # print(MEQ)

#  NKIEQ.. NKI              =E= SUM(I, M(I) * PWM0(I) )
#                                 - SUM(I, CX(I) * PD(I) )
#                                 - SUM(H, PRIVRET(H)*HH(H))
#                                 - SUM(LA, LNFOR(LA))
#                                 - SUM(K, KPFOR(K))
#                                 - SUM(G, GVFOR(G))

  print('NKIEQ')
  line1 = (M.loc(I) * ExprM(vars, m = PWM0.loc[I])).sum(I)
  line2 = (CX.loc(I) * PD.loc(I)).sum(I)
  line3 = (ExprM(vars, m =PRIVRET.loc[H])*HH.loc(H)).sum(H)
  line4 = LNFOR.loc(LA).sum(LA)
  line5 = KPFOR.loc(K).sum(K)
  line6 = GVFOR.loc(G).sum(G)

  NKIEQ = ((line1 - line2 - line3 - line4 - line5 - line6)  - NKI)
  NKIEQ.write(count,filename)
  print(NKIEQ.test(vars.initialVals))
  # print(NKIEQ)

#  NEQ(K,I).. N(K,I)        =E= N0(K,I)*(R(K,I)/R0(K,I))**(ETAIX(K,I));
  print('NEQ(K,I)')
  line = ExprM(vars, m = N0.loc[K,I])*(R.loc(K,I)/ExprM(vars, m = R0.loc[K,I]))**ExprM(vars, m = ETAIX.loc[K,I])

  NEQ = (line - N.loc(K, I))
  NEQ.write(count,filename)
  print(NEQ.test(vars.initialVals))
  # print(NEQ)

#  CNEQ(I).. P(I)*(1 + SUM(GS, TAUN(GS,I)))*CN(I)
#                         =E= SUM(IG, B(I,IG)*(SUM(K, N(K,IG))));
  print('CNEQ(I)')
  left = P.loc(I)*ExprM(vars, m = 1 + TAUN.loc[GS,I].sum(0))*CN.loc(I)
  right = (ExprM(vars, m = B.loc[I,IG]) * N.loc(K,IG).sum(K)).sum(IG)

  CNEQ = (right - left)
  CNEQ.write(count,filename)
  print(CNEQ.test(vars.initialVals))
  # print(CNEQ)

#  KSEQ(K,IG).. KS(K,IG)    =E= KS0(K,IG) * ( 1 - DEPR) + N(K,IG) ;
  print('KSEQ(K,IG)')
  line = ExprM(vars, m = KS0.loc[K,IG] * ( 1 - DEPR)) + N.loc(K,IG)

  KSEQ = (line - KS.loc(K, IG))
  KSEQ.write(count,filename)
  print(KSEQ.test(vars.initialVals))
  # print(KSEQ)

#LSEQ1(H).. HW(H)/HH(H) =E= HW0(H)/HH0(H)
#                   * ((SUM(L, RA(L) / RA0(L))/5)/ (CPI(H) / CPI0(H)))** (ETARA(H))
#                  * ( SUM(G, TP(H,G) / CPI(H) )/ SUM(G, TP(H,G) / CPI0(H) )) ** ETAPT(H)
#                  *  ((SUM(GI, PIT0(GI,H)* HH0(H))+ SUM(G, TAUH0(G,H)*HH0(H)))/(SUM(GI, PIT(GI,H)* HH(H))+ SUM(G, TAUH(G,H)*HH(H))))**(ETAPIT(H)*1) ;
  print('LSEQ1(H)')
  line1 = ExprM(vars, m =HW0.loc[H] / HH0.loc[H])
  LSEQ1line2pre = FD.loc(L,Z).sum(1)
  line2 = (((RA.loc(L) / ExprM(vars, m = RA0.loc[L])).sum(L)/5)/(CPI.loc(H) / ExprM(vars, m = CPI0[H]))) ** ExprM(vars, m = ETARA.loc[H])
  line3 = ( (ExprM(vars, m = TP.loc[H,G]) / CPI.loc(H)).sum(G) / (ExprM(vars, m = TP.loc[H,G]) / ExprM(vars, m = CPI0.loc[H] )).sum(G) ) ** ExprM(vars, m = ETAPT.loc[H])
  #line4 =( ((ExprM(vars, m = PIT.loc[GI,H])* ExprM(vars, m = HH0.loc[H])).sum(GI)+ (ExprM(vars, m = TAUH0.loc[G,H])*ExprM(vars, m = HH0.loc[H])).sum(G))\
  #        / ((ExprM(vars, m = PIT.loc[GI,H])* HH.loc(H)).sum(GI)+ (ExprM(vars, m = TAUH.loc[G,H])*HH.loc(H)).sum(G)) )** ExprM(vars, m = ETAPIT.loc[H])
  line4 =( ((ExprM(vars, m = PIT.loc[GI,H])* HH.loc(H)).sum(GI)+ (ExprM(vars, m = TAUH0.loc[G,H])* HH.loc(H)).sum(G))\
          / ((ExprM(vars, m = PIT.loc[GI,H])* HH.loc(H)).sum(GI)+ (ExprM(vars, m = TAUH.loc[G,H])*HH.loc(H)).sum(G)) )** ExprM(vars, m = ETAPIT.loc[H])

  LSEQ1 = ((line1 * line2 * line3 * line4) - HW.loc(H)/HH.loc(H))
  LSEQ1.write(count,filename)
  print(LSEQ1.test(vars.initialVals))
  # print(LSEQ1)

#  LASEQ1(LA,I).. LAS(LA,I) =E= LAS0(LA,I)*(R(LA, I)/R0(LA, I))**(ETAL(LA,I));
  print('LASEQ1(LA,I)')
  line = ExprM(vars, m = LAS0.loc[LA, I]) * (R.loc(LA,I) / ExprM(vars, m = R0.loc[LA, I]))**ExprM(vars, m = ETAL.loc[LA,I])

  LASEQ1 = (line - LAS.loc(LA, I))
  LASEQ1.write(count,filename)
  print(LASEQ1.test(vars.initialVals))
  # print(LASEQ1)

#  POPEQ(H).. HH(H)         =E= HH0(H) * NRPG(H)
#                                + MI0(H) * ((YD(H)/HH(H))/(YD0(H)/HH0(H))/(CPI(H)/CPI0(H))) ** (ETAYDI(H))
#                                         *((HN(H)/HH(H))/(HN0(H)/HH0(H))) ** (ETAUI(H))
#                              - MO0(H) *((YD0(H)/HH0(H))/(YD(H)/HH(H))/(CPI0(H)/CPI(H))) ** (ETAYDO(H))
#                                         *((HN0(H)/HH0(H))/(HN(H)/HH(H))) ** (ETAUO(H));

  print('POPEQ(H)')
  line1 = ExprM(vars, m = HH0.loc[H] * NRPG.loc[H])
  line2 = ExprM(vars, m = MI0.loc[H]) * ((YD.loc(H)/HH.loc(H)) / ExprM(vars, m = YD0.loc[H] / HH0.loc[H]) / (CPI.loc(H)/ExprM(vars, m = CPI0.loc[H]))) ** ExprM(vars, m = ETAYDI.loc[H])
  line3 = ((HN.loc(H)   / HH.loc(H)   ) / ExprM(vars, m = HN0.loc[H]  / HH0.loc[H]  ) ) ** ExprM(vars, m = ETAUI.loc[H])
  line4 = ExprM(vars, m = MO0.loc[H]) * (ExprM(vars, m = YD0.loc[H]  / HH0.loc[H]  ) / ( YD.loc(H)   / HH.loc(H)   ) / ( ExprM(vars, m = CPI0.loc[H]) / CPI.loc(H)  ) ) ** ExprM(vars, m = ETAYDO.loc[H])
  line5 = (ExprM(vars, m = HN0.loc[H]  / HH0.loc[H]  ) / ( HN.loc(H)   / HH.loc(H)   ) ) ** ExprM(vars, m = ETAUO.loc[H])

  POPEQ = (line1 + line2*line3 - line4*line5 - HH.loc(H))
  POPEQ.write(count,filename)
  print(POPEQ.test(vars.initialVals))
  # print(POPEQ)

#  ANEQ(H).. HN(H)          =E= HH(H) - HW(H);
  print('ANEQ(H)')
  line = HH.loc(H) - HW.loc(H)

  ANEQ = (line - HN.loc(H))
  ANEQ.write(count,filename)
  print(ANEQ.test(vars.initialVals))
  # print(ANEQ)

#  YGEQ(GX).. Y(GX)         =E=   SUM(I, TAUV(GX,I) * V(I) * P(I) )
#                                 + SUM(I, TAUX(GX,I)* CX(I) *PD(I))
#                                 + SUM((H,I), TAUC(GX,I) * CH(I,H) * P(I) )
#                                 + SUM(I, TAUN(GX,I) * CN(I) * P(I) )
#                                 + SUM((GN,I), TAUG(GX,I) * CG(I,GN) * P(I) )
#                                 + SUM((F,I), TAUFX(GX,F,I) * RA(F) * R(F,I) * TT(F,I)*FD(F,I) )
#                                 + SUM((F,GN), TAUFX(GX,F,GN) * RA(F) * R(F,GN) * FD(F,GN) )
#                                 + SUM(F, TAUFH(GX,F) * (Y(F)))
#                                 + SUM(H, PIT(GX,H) * Y(H) )
#                                 + SUM(H, TAUH(GX,H) * HH(H) )
#                                 + SUM(GX1, IGT(GX,GX1));
  print('YGEQ')
  line1 = (ExprM(vars, m = TAUV.loc[GX,I]) * V.loc(I) * P.loc(I)).sum(I)
  line2 = (ExprM(vars, m = TAUX.loc[GX,I]) * CX.loc(I) * PD.loc(I)).sum(I)

  YGEQline3pre = ExprM(vars, m = pd.DataFrame(index = GX, columns = H).fillna(0.0)) # first just set it to correct size
  for label in GX:
      for hlabel in H:
          YGEQline3pre.m[GX.index(label)][H.index(hlabel)] = Expr((ExprM(vars, m = TAUC.loc[[label],I]) * CH.loc(I, [hlabel]) * P.loc(I)).sum().m[0][0])

  line3 = YGEQline3pre.sum(1)
  line4 = (ExprM(vars, m = TAUN.loc[GX,I]) * CN.loc(I) * P.loc(I)).sum(I)

  YGEQline5pre = ExprM(vars, m = TAUG.loc[GX, I]).sum(I) # first just set it to correct size
  for label in GX:
      YGEQline5pre.m[GX.index(label)][0] = Expr((ExprM(vars, m = TAUG.loc[[label],I]) * CG.loc(I, GN) * P.loc(I)).sum().m[0][0])
  line5 = YGEQline5pre

  line6 = ExprM(vars, m = TAUG.loc[GX, I]).sum(I)
  for label in GX:
    line6.m[GX.index(label)][0] = Expr((ExprM(vars, m = TAUFXgx[label].loc[F, I]) *  RA.loc(F) * R.loc(F,I) * FD.loc(F,I) ).sum().m[0][0])

  line7 = ExprM(vars, m = TAUG.loc[GX, I]).sum(I)
  for label in GX:
    line7.m[GX.index(label)][0] = Expr((ExprM(vars, m = TAUFXgx[label].loc[F, GN]) *  RA.loc(F) * R.loc(F,GN) * FD.loc(F,GN) ).sum().m[0][0])

  line8 = (ExprM(vars, m = TAUFH.loc[GX,F]) * Y.loc(F)).sum(F)
  line9 = (ExprM(vars, m = PIT.loc[GX,H]) * Y.loc(H)).sum(H)
  line10 = (ExprM(vars, m = TAUH.loc[GX,H]) * HH.loc(H) ).sum(H)
  line11 = IGT.loc(GX,GX1).sum(1)

  YGEQ = ((line1 + line2 + line3 + line4 + line5 + line6 + line7 + line8 + line9 + line10 + line11) - Y.loc(GX))
  YGEQ.write(count,filename)
  print(YGEQ.test(vars.initialVals))
  # print(YGEQ)

#    YGEQ2(GT).. Y(cf)        =E= SUM(GX, IGT(cf,GX));

  line = IGT.loc(CF,GX).sum(GX)
  print('YGEQ2')
  YGEQ2 = (line - Y.loc(CF))
  YGEQ2.write(count,filename)
  print(YGEQ2.test(vars.initialVals))
  # print(YGEQ2)

#  YGEQ1(GNL).. Y(GNL)      =E= TAXS1(GNL)*Y('CYGF');
  print('YGEQ1(GNL)')
  line = ExprM(vars, m = TAXS1.loc[GNL])*Y.loc(['CYGF'])
  YGEQ1 =  (line - Y.loc(GNL))
  YGEQ1.write(count,filename)
  print(YGEQ1.test(vars.initialVals))
  # print(YGEQ1)

#  GOVFOR(G).. GVFOR(G)     =E= GFOR(G)*Y(G);
  print('GOVFOR(G)')
  line = ExprM(vars, m = GFOR.loc[G])*Y.loc(G)

  GOVFOR = (line - GVFOR.loc(G))
  GOVFOR.write(count,filename)
  print(GOVFOR.test(vars.initialVals))
  # print(GOVFOR)

#  CGEQ(I,GN).. P(I)*(1 + SUM(GS, TAUG(GS,I))) * CG(I,GN)
#                         =E= AG(I,GN) * (Y(GN)+ GFOR(GN)*Y(GN));
  print('CGEQ(I,GN)')
  left = P.loc(I) * ExprM(vars, m = 1 + TAUG.loc[GS,I].sum(0)) * CG.loc(I,GN)
  right = ExprM(vars, m = AG.loc[I,GN]) * (Y.loc(GN)+ ExprM(vars, m = GFOR.loc[GN])*Y.loc(GN))

  CGEQ = (right - left)
  CGEQ.write(count,filename)
  print(CGEQ.test(vars.initialVals))
  # print(CGEQ)

#  GFEQ(F,GN)..  FD(F,GN) * R(F,GN) * RA(F)*( 1 + SUM(GF, TAUFX(GF,F,GN)))
#                         =E= AG(F,GN) * (Y(GN)+ GFOR(GN)*Y(GN));
  print('GFEQ(F,GN)')
  left =  FD.loc(F, GN) * R.loc(F, GN) * RA.loc(F) *(1 + ExprM(vars, m = TAUFX_SUM.loc[F, GN]))
  right = ExprM(vars, m = AG.loc[F, GN]) * (Y.loc(GN) + ExprM(vars, m = GFOR.loc[GN])*Y.loc(GN))

  GFEQ = left - right
  GFEQ.write(count,filename)
  print(GFEQ.test(vars.initialVals))
  # print(GFEQ)

#  GSEQL(GN).. S(GN)        =E= (Y(GN)+ GVFOR(GN))
#                                 - SUM(I, CG(I,GN)*P(I)*(1 + SUM(GS, TAUG(GS,I))))
#                                 - SUM(F, FD(F,GN)*R(F,GN)*RA(F)*(1 + SUM(GF, TAUFX(GF,F,GN))));
  print('GSEQL(GN)')
  line1 = Y.loc(GN) + GVFOR.loc(GN)
  line2 = (CG.loc(I, GN) * P.loc(I) * (1 + ExprM(vars, m = TAUG.loc[GS, I]).sum(GS))).sum(I)
  line3 = (FD.loc(F, GN) * R.loc(F, GN) * RA.loc(F) * (1 + ExprM(vars, m = TAUFX_SUM.loc[F, GN]))).sum(F)

  GSEQL = ((line1 - ~line2 - ~line3) - S.loc(GN))
  GSEQL.write(count,filename)
  print(GSEQL.test(vars.initialVals))
  # print(GSEQL)

#  GSEQ(GX).. S(GX)         =E= (Y(GX) + GFOR(GX)*Y(GX)) - SUM(H, (TP(H,GX)*HH(H))) - SUM(G,IGT(G,GX));
  print('GSEQ(GX)')
  line1 = (Y.loc(GX) + ExprM(vars, m = GFOR.loc[GX])*Y.loc(GX))
  line2 = (ExprM(vars, m = TP.loc[H,GX]) * HH.loc(H)).sum(H)
  line3 = IGT.loc(G,GX).sum(G)

  GSEQ = ((line1 - ~line2 - ~line3) - S.loc(GX))
  GSEQ.write(count,filename)
  print(GSEQ.test(vars.initialVals))
  # print(GSEQ)

#  TDEQ(G,GX)$(IGTD(G,GX) EQ 1).. IGT(G,GX)
#                         =E= TAXS(G,GX)*(Y(GX) + GVFOR(GX)- SUM(H, (TP(H,GX)*HH(H))));
  print('TDEQ(G,GX)$(IGTD(G,GX) EQ 1)')
  line = ExprM(vars, m = TAXS.loc[G,GX]) * ( Y.loc(GX) + GVFOR.loc(GX) - ~(ExprM(vars, m = TP.loc[H,GX]) * HH.loc(H)).sum(H) )

  TDEQ = line - IGT.loc(G, GX)
  TDEQ.setCondition(IGTD.loc[G,GX], 'EQ', 1)
  TDEQ.write(count,filename)
  print(TDEQ.test(vars.initialVals))
  # print(TDEQ)

  #GSEQJ1('CYGF').. S('CYGF')=E= Y('CYGF') -  Y('CYGF');
  print('GSEQJ1(\'CYGF\')')
  GSEQJ1 = S.loc(['CYGF']) - Y.loc(['CYGF']) + Y.loc(['CYGF'])
  GSEQJ1.write(count,filename)
  print(GSEQJ1.test(vars.initialVals))

#  SPIEQ.. SPI              =E= SUM(H, Y(H)) + SUM((H,G), TP(H,G)*HH(H)) + SUM(H, PRIVRET(H)*HH(H));
  print('SPIEQ')
  line = Y.loc(H).sum(H) + (ExprM(vars, m = TP.loc[H,G]) * HH.loc(H)).sum() + (ExprM(vars, m = PRIVRET.loc[H])* HH.loc(H)).sum(H)

  SPIEQ = (line-SPI)
  SPIEQ.write(count,filename)
  print(SPIEQ.test(vars.initialVals))
  # print(SPIEQ)

#  LMEQ1.. SUM(H, HW(H)* JOBCOR(H,'L1')) + CMI('L1') =E= SUM(Z, FD('L1',Z)) + SUM(CM1, SUM(H, HW(H)*OUTCR(H, CM1)));
# LMEQ1(L)= SUM(H, HW(H)* JOBCOR(H, L)) - SUM(Z, FD(L ,Z) ) ;
  print('LMEQ1')
  left = (ExprM(vars, m = JOBCOR.loc[H, L])*HW.loc(H)).sum(H)
  right = FD.loc(L, Z).sum(Z)
  # right = FD.loc(['L1'], Z).sum(Z) + CMO.loc(CM1).sum(CM1)

  LMEQ1 = (right - left)
  LMEQ1.write(count, filename)
  print(LMEQ1.test(vars.initialVals))
  # print(LMEQ1)

#  KMEQ(K,IG).. KS(K,IG)    =E= FD(K,IG);
  print('KMEQ(K,IG)')
  KMEQ = (FD.loc(K,IG) - KS.loc(K,IG))
  KMEQ.write(count,filename)
  print(KMEQ.test(vars.initialVals))
  # print(KMEQ)

#  LAMEQ(LA,IG).. LAS(LA,IG)=E= FD(LA,IG);
  print('LAMEQ(LA,IG)')
  LAMEQ = (FD.loc(LA, IG) - LAS.loc(LA, IG))
  LAMEQ.write(count,filename)
  print(LAMEQ.test(vars.initialVals))
  # print(LAMEQ)

#  GMEQ(I).. DS(I)          =E= DD(I) + CX(I) - M(I);
  print('GMEQ(I)')
  GMEQ = (DD.loc(I) + CX.loc(I) - M.loc(I) - DS.loc(I))
  GMEQ.write(count,filename)
  print(GMEQ.test(vars.initialVals))
  # print(GMEQ)

#  DDEQ(I).. DD(I)          =E= V(I) + SUM(H, CH(I,H) ) + SUM(G, CG(I,G) ) + CN(I);
  print('DDEQ(I)')
  DDEQ = (V.loc(I) + CH.loc(I,H).sum(H) + CG.loc(I,G).sum(G) + CN.loc(I) - DD.loc(I))
  DDEQ.write(count,filename)
  print(DDEQ.test(vars.initialVals))
  # print(DDEQ)

  #IGT.FX(G,GX)$(NOT IGT0(G,GX))=0;
  print('IGT.FX(G,GX)$(NOT IGT0(G,GX))=0')
  FX1 = IGT.loc(G,GX)
  FX1.setCondition(IGT0.loc[G,GX], 'EQ', 0)
  FX1.write(count,filename)
  # print(FX1)

  #IGT.FX(G,GX)$(IGTD(G,GX) EQ 2)=IGT0(G,GX);
  print('IGT.FX(G,GX)$(IGTD(G,GX) EQ 2)=IGT0(G,GX)')
  FX2 = IGT.loc(G,GX) - ExprM(vars, m = IGT0.loc[G,GX])
  FX2.setCondition(IGTD.loc[G,GX], 'EQ', 2)
  FX2.write(count,filename)
  # print(FX2)

  #R.FX(L,Z)=R0(L,Z);
  print('R.FX(L,Z)=R0(L,Z)')
  FX3 = R.loc(L,Z) - ExprM(vars, m = R0.loc[L,Z])
  FX3.write(count,filename)
  # print(FX3)

  #RA.FX(LA)=RA0(LA);
  print('RA.FX(LA)=RA0(LA)')
  FX4 = RA.loc(LA) - ExprM(vars, m = RA0.loc[LA])
  FX4.write(count,filename)
  # print(FX4)

  #RA.FX(K)=RA0(K);
  print('RA.FX(K)=RA0(K)')
  FX5 = RA.loc(K) - ExprM(vars, m = RA0.loc[K])
  FX5.write(count,filename)
  # print(FX5)

  print("Objective")
  obj = vars.getIndex('SPI')

  with open(filename,'a') as f:
    f.write('model.obj = Objective(expr=-1*model.x' + str(obj) + ')')

def run_solver(cons_filename, temp_file_name="tmp.py"):
  solver = 'ipopt'
  solver_io = 'nl'
  stream_solver = True     # True prints solver output to screen
  keepfiles = False    # True prints intermediate file names (.nl,.sol,...)
  opt = SolverFactory(solver, solver_io= solver_io)

  if opt is None:
      print("")
      print("ERROR: Unable to create solver plugin for %s "\
            "using the %s interface" % (solver, solver_io))
      print("")
      exit(1)

  ### Create the model
  model = ConcreteModel()
  set_variable(cons_filename)
  set_equation(cons_filename)
  ###

  ### read the model
  exec(open(cons_filename).read())
  ###

  ### Declare all suffixes

  # Ipopt bound multipliers (obtained from solution)
  model.ipopt_zL_out = Suffix(direction=Suffix.IMPORT)
  model.ipopt_zU_out = Suffix(direction=Suffix.IMPORT)

  # Ipopt bound multipliers (sent to solver)
  model.ipopt_zL_in = Suffix(direction=Suffix.EXPORT)
  model.ipopt_zU_in = Suffix(direction=Suffix.EXPORT)

  # Obtain dual solutions from first solve and send to warm start
  model.dual = Suffix(direction=Suffix.IMPORT_EXPORT)

  #opt.options['halt_on_ampl_error'] = 'yes'
  #opt.options['acceptable_tol'] = '1e-3'
  ### Send the model to ipopt and collect the solution
  #results = opt.solve(model,keepfiles=keepfiles,tee=stream_solver)

  # IMPORT / IMPORT_EXPORT Suffix components)
  # model.solutions.load_from(results)

  ### Set Ipopt options for warm-start
  # The current values on the ipopt_zU_out and
  # ipopt_zL_out suffixes will be used as initial
  # conditions for the bound multipliers to solve
  # the new problem
  model.ipopt_zL_in.update(model.ipopt_zL_out)
  model.ipopt_zU_in.update(model.ipopt_zU_out)
  opt.options['warm_start_init_point'] = 'yes'
  opt.options['warm_start_bound_push'] = 1e-6
  opt.options['warm_start_mult_bound_push'] = 1e-6
  opt.options['mu_init'] = 1e-6
  #opt.options['acceptable_tol'] = 10
  #opt.options['max_iter'] = 15
  #opt.options['compl_inf_tol'] = 1e-3
  #opt.options['bound_relax_factor'] = 0
  #opt.options['start_with_resto'] = 'yes'
  #opt.options['acceptable_iter'] = 15
  #opt.options['halt_on_ampl_error'] = 'yes'
  #opt.options['fixed_variable_treatment'] = 'relax_bounds'
  #opt.options['print_options_documentation'] = 'yes'

  ###

  ### Send the model and suffix information to ipopt and collect the solution
  # The solver plugin will scan the model for all active suffixes
  # valid for importing, which it will store into the results object

  results = opt.solve(model,keepfiles=keepfiles,tee=stream_solver)

  x = [None for i in range(vars.nvars)]

  with open(temp_file_name,'w') as f:
    for i in range(vars.nvars):
      f.write('x['+str(i)+']=value(model.x'+str(i)+')\n')

  exec(open(temp_file_name).read())

  soln.append(x[:])

  return None

'''
Calibrate the model
'''

soln = []
filename = os.path.join(filePath, "ipopt_cons.py")
tmp = os.path.join(filePath, "tmp.py")
print("Calibration: ")
run_solver(filename, tmp)

'''
Simulation code below:
In each simulation:

1. Apply simulation code (for instance PI(I) = 1.02).
2. Rewrite all equations
3. Solve the new model with the result from last run as initial guess.

'''

iNum = 1 # dynamic model itterations

for ittr in range(iNum):
  print("Simulation: ", ittr+1)
  if ittr == 0: # if it is the first simulation, apply the shock

      #DELTA.loc[I] = 1.02 * DELTA.loc[I]

      KS0.loc[K, I] = KS0.loc[K, I]*0.7

      #KS0.loc[K, ['HS1']] = KS0.loc[K, ['HS1']] * 0.675
      #KS0.loc[K, ['HS2']] = KS0.loc[K, ['HS2']] * 0.739
      #KS0.loc[K, ['HS3']] = KS0.loc[K, ['HS3']] * 0.958
      #KS0.loc[K, ['GOODS']] = KS0.loc[K, ['GOODS']] * 0.658
      #KS0.loc[K, ['TRADE']] = KS0.loc[K, ['TRADE']] * 0.961
      #KS0.loc[K, ['OTHER']] = KS0.loc[K, ['OTHER']] * 0.673

  else: # other simulations

      #KS0 = KSNEW*(1-DEPR)+vars.get('N', x=soln[-1])
      KS0 = vars.get('KS', x=soln[-1])

  run_solver(filename, tmp)

exec(open(os.path.join(modelPath, "seaside_output.py")).read())


"""EmplyoeePro URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""

from django.urls import path
from employee.views import EmployeeCreate,EmployeeList,EmployeeEdit,EmployeeDetails,EmployeeDelete

urlpatterns = [

path('create',EmployeeCreate.as_view(),name="create"),
path('list',EmployeeList.as_view(),name="list"),
path('edit/<int:pk>',EmployeeEdit.as_view(),name="edit"),
path('details/<int:pk>',EmployeeDetails.as_view(),name="details"),
path('delete/<int:pk>',EmployeeDelete.as_view(),name="delete"),
]


##! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 18/12/14

@author: Sammy Pfeiffer

From http://docs.opencv.org/trunk/doc/py_tutorials/py_calib3d/py_calibration/py_calibration.html#calibration

Extra info:
http://docs.opencv.org/2.4.10/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=calibratecamera#cv2.calibrateCamera

"""
import numpy as np
import cv2
import glob
import math
import pickle
import time

def _pdist(p1, p2):
        """
        Distance bwt two points. p1 = (x, y), p2 = (x, y)
        """
        return math.sqrt(math.pow(p1[0] - p2[0], 2) + math.pow(p1[1] - p2[1], 2))

def draw(img, corners, imgpts):
        corner = tuple(corners[0].ravel())
        cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
        cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
        cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
        return img
        """
        Distance bwt two points. p1 = (x, y), p2 = (x, y)
        """
        return math.sqrt(math.pow(p1[0] - p2[0], 2) + math.pow(p1[1] - p2[1], 2))

def draw(img, corners, imgpts):
        corner = tuple(corners[0].ravel())
        cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
        cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
        cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
        return img

print ("Initializing")
cap =  cv2.VideoCapture(0)

while not cap.isOpened():
        cap = cv2.VideoCapture(0)
        cv2.waitKey(1000)
        print("Wait For Camera")

n_rows = 4
n_cols = 5
n_cols_and_rows = (n_cols, n_rows) #originally (7,6) # 4,5 same results
n_rows_and_cols = (n_rows, n_cols)
sqr_size = 0.037 # 37mm

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((n_rows*n_cols,3), np.float32)
objp[:,:2] = np.mgrid[0:n_rows,0:n_cols].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

mypath ="/home/pi/Desktop/gitHub/chessboard_pose/data/calibrationdata_camera_1/"#calib_data_yigit/" #"/home/sampfeiffer/svn/argus_ws/src/argus_tools/data/calibrationdata_camera_1/"

axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)
fourcc = cv2.cv.CV_FOURCC('H','2','6','1')
out = cv2.VideoWriter()

inf = open(mypath+"calibration_return_values_rows_and_cols.pickle", "rb" )
datathings = pickle.load(inf)
ret, mtx, dist, rvecs, tvecs = datathings
mtx = mtx.reshape(3,3)
sum = 0
i = 0
success = out.open('output.avi',fourcc,20.0,(352,288),1)

outtxt  = open("Webcam_exec_times.txt","w")
while True:
        i = i + 1
        start = time.time()
        ret,img = cap.read(0)
        img = cv2.resize(img,(352,288))
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        ret, corners = cv2.findChessboardCorners(gray, n_rows_and_cols,None)
        print(ret)
        if ret == True:
                corners2 = corners# cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
                print(np.size(corners2))
                print(np.size(objp))
                print((mtx))
                print(np.size(dist))

                # Find the rotation and translation vectors.

                rtval,rvecs, tvecs = cv2.solvePnP(objp, corners2, mtx, dist)
#                       print(rvecs)
#                       print(tvecs)

                # project 3D points to image plane
                imgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist)

                img = draw(img,corners2,imgpts)
                out.write(img)
                cv2.imshow('img',img)
                if cv2.waitKey(1) & 0xFF  == ord('q'):
                        break
                        #cv2.imwrite(fname[:6]+'.png', img)
                end = time.time()

                print(end - start)
                outtxt.write("%f" % (end -start))

                sum = sum + end - start
        elif ret == False:
                if cv2.waitKey(1) & 0xFF  == ord('q'):
                        break

                cv2.imshow('img',img)
                cv2.waitKey(10)

out.release()
print("Mean Execution time:")
print(sum/i)
cap.release()
cv2.destroyAllWindows()