class Colours(QtWidgets.QDialog):

    def __init__(self, ini_file=None, section='Colors', add_colour=False, palette=None, underscore=False):
        super(Colours, self).__init__()
        config = configparser.RawConfigParser()
        if ini_file is not None:
            self.config_file = ini_file
        elif len(sys.argv) > 1:
            self.config_file = sys.argv[1]
        else:
            self.config_file = getModelFile('SIREN.ini')
        self.section = section
        self.underscore = underscore
        config.read(self.config_file)
        groups = ['Fossil Technologies', 'Grid', 'Map', 'Plot', 'Resource', 'Technologies', 'The Rest']
        map_colours = ['background', 'border', 'fossil', 'fossil_name', 'station', 'station_name',
                       'town', 'town_name']
        plot_colours = ['cumulative', 'gross_load', 'load', 'shortfall']
        resource_colours = ['dhi_high', 'dhi_low', 'dni_high', 'dni_low', 'ghi_high', 'ghi_low',
                            'rain_high', 'rain_low', 'temp_high', 'temp_low', 'wind50_high',
                            'wind50_low', 'wind_high', 'wind_low']
        colour_groups = {}
        for group in groups:
            colour_groups[group] = []
        try:
            technologies = config.get('Power', 'technologies')
            technologies = technologies.split()
        except:
            technologies = []
        try:
            fossil_technologies = config.get('Power', 'fossil_technologies')
            fossil_technologies = fossil_technologies.split()
        except:
            fossil_technologies = []
        self.map = ''
        if self.section == 'Colors':
            try:
                self.map = config.get('Map', 'map_choice')
            except:
                pass
        self.colours = {}
        try:
            colours0 = config.items(self.section)
            for it, col in colours0:
                if it == 'ruler':
                    continue
                self.colours[it] = ['', col]
        except:
            pass
        self.default_col = 1
        if self.map != '':
            self.default_col = 2
            try:
                colours1 = config.items(self.section + self.map)
                for it, col in colours1:
                    if it == 'ruler':
                        continue
                    if it in self.colours:
                        self.colours[it] = [col, self.colours[it][1]]
                    else:
                        self.colours[it] = [col, '']
            except:
                pass
        if palette is not None and len(palette) > 0: # set palette of colours
            col = ['', '']
            col[0] = QtWidgets.QColorDialog.getColor(QtCore.Qt.white, None, 'Select colour for item 1')
            if len(palette) > 1:
                col[1] = QtWidgets.QColorDialog.getColor(QtCore.Qt.white, None,
                         'Select colour for item ' + str(len(palette)))
                inc = []
                for c in range(3):
                    inc.append((col[1].getRgb()[c] - col[0].getRgb()[c]) / (len(palette) - 1))
                for i in range(len(palette)):
                    colr = []
                    for c in range(3):
                        colr.append(int(col[0].getRgb()[c] + inc[c] * i))
                    QtGui.QColor.setRgb(col[1], colr[0], colr[1], colr[2])
                    if self.underscore:
                        self.colours[palette[i].lower()] = ['', col[1].name()]
                    else:
                        self.colours[palette[i].lower().replace(' ', '_')] = ['', col[1].name()]
            else:
                if self.underscore:
                    self.colours[palette[0].lower()] = ['', col[0].name()]
                else:
                    self.colours[palette[0].lower().replace(' ', '_')] = ['', col[0].name()]
        group_colours = False
        try:
            gc = config.get('View', 'group_colours')
            if gc.lower() in ['true', 'on', 'yes']:
                group_colours = True
        except:
            pass
        self.old_ruler = ''
        for key, value in self.colours.items():
            if key in fossil_technologies:
                colour_groups['Fossil Technologies'].append(key)
            elif key.find('grid') >= 0:
                colour_groups['Grid'].append(key)
            elif key in map_colours:
                colour_groups['Map'].append(key)
            elif key in plot_colours:
                colour_groups['Plot'].append(key)
            elif key in resource_colours:
                colour_groups['Resource'].append(key)
            elif key in technologies:
                colour_groups['Technologies'].append(key)
            else:
                colour_groups['The Rest'].append(key)
            for i in range(2):
                if value[i] != '':
                    value[i] = QtGui.QColor(value[i])
            self.colours[key] = value
        self.width = [0, 0]
        self.height = [0, 0]
        self.item = []
        self.btn = []
        self.grid = QtWidgets.QGridLayout()
        self.grid.addWidget(QtWidgets.QLabel('Item'), 0, 0)
        if self.map != '':
            self.grid.addWidget(QtWidgets.QLabel('Colour for ' + self.map), 0, 1)
        self.grid.addWidget(QtWidgets.QLabel('Default Colour'), 0, self.default_col)
        i = 1
        if group_colours:
            bold = QtGui.QFont()
            bold.setBold(True)
            for gkey, gvalue in iter(sorted(colour_groups.items())):
                label = QtWidgets.QLabel(gkey)
                label.setFont(bold)
                self.grid.addWidget(label, i, 0)
                i += 1
                for key in sorted(gvalue):
                    value = self.colours[key]
                    self.add_item(key, value, i)
                    i += 1
        else:
            for key, value in iter(sorted(self.colours.items())):
                self.add_item(key, value, i)
                i += 1
        if add_colour:
            if self.underscore:
                key = add_colour.lower()
            else:
                key = add_colour.lower().replace(' ', '_')
            self.colours[key] = ['', '']
            self.add_item(key, ['', ''], -1)
            self.showDialog(colour=key)
        buttonLayout = QtWidgets.QHBoxLayout()
        quit = QtWidgets.QPushButton('Quit', self)
        quit.setMaximumWidth(70)
        buttonLayout.addWidget(quit)
        quit.clicked.connect(self.quitClicked)
        save = QtWidgets.QPushButton('Save && Exit', self)
        buttonLayout.addWidget(save)
        save.clicked.connect(self.saveClicked)
        if self.section != 'Colors':
            add = QtWidgets.QPushButton('Add', self)
            buttonLayout.addWidget(add)
            add.clicked.connect(self.addClicked)
        buttons = QtWidgets.QFrame()
        buttons.setLayout(buttonLayout)
        layout = QtWidgets.QVBoxLayout()
        layout.addLayout(self.grid)
        layout.addWidget(buttons)
        self.setLayout(layout)
        self.grid.setColumnMinimumWidth(0, self.width[0])
        self.grid.setColumnMinimumWidth(1, self.width[0])
        if self.map != '':
            self.grid.setColumnMinimumWidth(2, self.width[0])
        frame = QtWidgets.QFrame()
        frame.setLayout(layout)
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(frame)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.scroll)
        screen = QtWidgets.QDesktopWidget().availableGeometry()
       # if self.height[0] == 0:
        metrics = quit.fontMetrics()
        self.height[0] = metrics.boundingRect(quit.text()).height() + self.grid.verticalSpacing() * 3
        height = (self.height[0] + self.grid.verticalSpacing() * 2) * self.grid.rowCount() + buttons.sizeHint().height()
        if height > int(screen.height() * .9):
            self.height[1] = int(screen.height() * .9)
        else:
            self.height[1] = height
        if self.width[0] == 0:
            self.width[1] = buttons.sizeHint().width() + 80
        else:
            self.width[1] = self.width[0] * 3 + 80
        self.resize(self.width[1], self.height[1])
     #   self.resize(640, 480)
        self.setWindowTitle('SIREN - Color dialog')
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.quitClicked)

    def add_item(self, key, value, i):
        if i < 0:
            i = self.grid.rowCount() # could possibly use this always just not sure about colour groups
            screen = QtWidgets.QDesktopWidget().availableGeometry()
            if self.height[1] + self.height[0] < int(screen.height() * .9):
                width = max(self.width[1], self.frameGeometry().width())
                self.height[1] += self.height[0]
                self.resize(width, self.height[1])
        wht = techClean(key, full=True)
        self.grid.addWidget(QtWidgets.QLabel(wht), i, 0)
        if self.map != '':
            self.btn.append(QtWidgets.QPushButton(key, self))
            self.btn[-1].clicked.connect(self.showDialog)
            if value[0] != '':
                self.btn[-1].setStyleSheet('QPushButton {background-color: %s; color: %s;}' %
                             (value[0].name(), value[0].name()))
            self.grid.addWidget(self.btn[-1], i, 1)
            metrics = self.btn[-1].fontMetrics()
            if metrics.boundingRect(self.btn[-1].text()).width() > self.width[0]:
                self.width[0] = metrics.boundingRect(self.btn[-1].text()).width()
            if metrics.boundingRect(self.btn[-1].text()).height() > self.height[0]:
                self.height[0] = metrics.boundingRect(self.btn[-1].text()).height() + self.grid.verticalSpacing() * 2
        self.btn.append(QtWidgets.QPushButton(key + '_base', self))
        metrics = self.btn[-1].fontMetrics()
        if i < 2:
            self.default_style = self.btn[-1].styleSheet()
        self.btn[-1].clicked.connect(self.showDialog)
        if value[1] != '':
            self.btn[-1].setStyleSheet('QPushButton {background-color: %s; color: %s;}' %
                         (value[1].name(), value[1].name()))
        self.grid.addWidget(self.btn[-1], i, self.default_col)
        if metrics.boundingRect(self.btn[-1].text()).width() > self.width[0]:
            self.width[0] = metrics.boundingRect(self.btn[-1].text()).width()
        if metrics.boundingRect(self.btn[-1].text()).height() > self.height[0]:
            self.height[0] = metrics.boundingRect(self.btn[-1].text()).height() + self.grid.verticalSpacing() * 2

    def mousePressEvent(self, event):
        if QtCore.Qt.RightButton == event.button():
            for btn in self.btn:
                if btn.hasFocus():
                    if btn.text()[-5:] != '_base':
                        key = btn.text()
                        if self.colours[key][0] != '':
                            self.colours[key] = ['delete', self.colours[key][1]]
                        btn.setStyleSheet(self.default_style)
                    elif self.section != 'Colors':
                        if btn.text()[-5:] == '_base':
                            key = btn.text()[:-5]
                        else:
                            key = btn.text()
                        self.colours[key] = ['', '']
                        btn.setStyleSheet(self.default_style)
                        break

    def showDialog(self, colour=False):
        sender = self.sender()
        if not colour:
            if sender.text()[-5:] == '_base':
                key = sender.text()[:-5]
                ndx = 1
            else:
                key = sender.text()
                ndx = 0
        else:
            key = colour
            ndx = 1
        if self.colours[key][ndx] != '' and self.colours[key][ndx] != 'delete':
            col = QtWidgets.QColorDialog.getColor(self.colours[key][ndx], None, 'Select colour for ' + key.title())
        else:
            col = QtWidgets.QColorDialog.getColor(QtGui.QColor('white'), None, 'Select colour for ' + key.title())
        if col.isValid():
            if not colour:
                if ndx == 0:
                    self.colours[key] = [col, self.colours[key][1]]
                else:
                    self.colours[key] = [self.colours[key][0], col]
                for i in range(len(self.btn)):
                    if self.btn[i] == sender:
                        self.btn[i].setStyleSheet('QPushButton {background-color: %s; color: %s;}' % (col.name(), col.name()))
                        break
            else:
                for i in range(len(self.btn) -1, -1, -1):
                    self.colours[key] = [self.colours[key][0], col]
                    if self.btn[i].text() == key + '_base':
                        self.btn[i].setStyleSheet('QPushButton {background-color: %s; color: %s;}' % (col.name(), col.name()))
                        break

    def quitClicked(self):
        self.close()

    def addClicked(self):
        text, ok = QtWidgets.QInputDialog.getText(self, 'Add Colour Item', 'Enter name for colour item:')
        if ok:
            if self.underscore:
                key = text.lower()
            else:
                key = text.lower().replace(' ', '_')
            self.colours[key] = ['', '']
            self.add_item(key, ['', ''], -1)

    def saveClicked(self):
        updates = {}
        lines = [[], []]
        for key, value in self.colours.items():
            for i in range(2):
                if value[i] == 'delete':
                    lines[i].append(key + '=')
                elif value[i] != '':
                    lines[i].append(key + '=' + value[i].name())
                elif self.section != 'Colors':
                    lines[i].append(key + '=')
        if len(lines[0]) > 0:
            updates[self.section + self.map] = lines[0]
        updates[self.section] = lines[1]
        SaveIni(updates, ini_file=self.config_file)
        self.close()

    def getValues(self):
        return self.anobject class PlotWeather():
    def haversine(self, lat1, lon1, lat2, lon2):
        """
        Calculate the great circle distance between two points
        on the earth (specified in decimal degrees)
        """
   #     convert decimal degrees to radians
        lon1, lat1, lon2, lat2 = list(map(radians, [lon1, lat1, lon2, lat2]))

   #     haversine formula
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
        c = 2 * asin(sqrt(a))

   #     6367 km is the radius of the Earth
        km = 6367 * c
        return km

    def find_closest(self, latitude, longitude, wind=False, rain=False):
        dist = 99999
        closest = ''
        close_lat = 0
        close_lon = 0
        if wind:
            filetype = '.srw'
            technology = 'wind_index'
            index_file = self.wind_index
            folder = self.wind_files
        elif rain:
            filetype = '.csv'
            technology = 'rain_index'
            index_file = ''
            folder = self.rain_files
        else:
            filetype = '.smw'
            technology = 'solar_index'
            index_file = self.solar_index
            folder = self.solar_files
        if folder != '':
            if index_file == '':
                fils = os.listdir(folder)
                for fil in fils:
                    if fil[-4:] == filetype or filetype != '.srw' and fil[-4:] == '.csv':
                        bit = fil.split('_')
                        if bit[-1][:4] == str(self.base_year):
                            dist1 = self.haversine(float(bit[-3]), float(bit[-2]), latitude, longitude)
                            if dist1 < dist:
                                closest = fil
                                dist = dist1
                                close_lat = bit[-3]
                                close_lon = bit[-2]
            else:
                fils = []
                ndx_file = ''
                if os.path.exists(index_file):
                    ndx_file = index_file
                elif os.path.exists(folder + '/' + index_file):
                    ndx_file = folder + '/' + index_file
                if ndx_file != '':
                    if ndx_file[-4:] == '.xls' or ndx_file[-5:] == '.xlsx':
                        var = {}
                        xl_file = xlrd.open_workbook(ndx_file)
                        worksheet = xl_file.sheet_by_index(0)
                        num_rows = worksheet.nrows - 1
                        num_cols = worksheet.ncols - 1
#                       get column names
                        curr_col = -1
                        while curr_col < num_cols:
                            curr_col += 1
                            var[worksheet.cell_value(0, curr_col)] = curr_col
                        curr_row = 0
                        while curr_row < num_rows:
                            curr_row += 1
                            lat = worksheet.cell_value(curr_row, var['Latitude'])
                            lon = worksheet.cell_value(curr_row, var['Longitude'])
                            fil = worksheet.cell_value(curr_row, var['Filename'])
                            fils.append([lat, lon, fil])
                    else:
                        dft_variables = csv.DictReader(open(ndx_file))
                        for var in dft_variables:
                            lat = float(var['Latitude'])
                            lon = float(var['Longitude'])
                            fil = var['Filename']
                            fils.append([lat, lon, fil])
                    for fil in fils:
                        dist1 = self.haversine(fil[0], fil[1], latitude, longitude)
                        if dist1 < dist:
                            closest = fil[2]
                            dist = dist1
        if __name__ == '__main__':
            print(closest)
        return closest, dist, close_lat, close_lon

    def showGraphs(self, ly, x, locn):
        def dayPlot(self, period, data, locn, per_labels=None, x_labels=None):
            plt.figure(period)
            plt.suptitle(self.hdrs[period] + locn, fontsize=16)
            maxy = 0
            maxw = 0
            if len(data[0]) > 9:
                p_y = 3
                p_x = 4
                xl = 8
                yl = [0, 4, 8]
                yl2 = [3, 7, 11]
            elif len(data[0]) > 6:
                p_y = 3
                p_x = 3
                xl = 6
                yl = [0, 3]
                yl2 = [2, 5]
            elif len(data[0]) > 4:
                p_y = 2
                p_x = 3
                xl = 3
                yl = [0, 3]
                yl2 = [2, 5]
            elif len(data[0]) > 2:
                p_y = 2
                p_x = 2
                xl = 2
                yl = [0, 2]
                yl2 = [1, 3]
            else:
                p_y = 1
                p_x = 2
                xl = 0
                yl = [0, 1]
                yl2 = [0, 1]
            wi = -1
            ra = -1
            te = -1
            i = -1
            for key, value in iter(sorted(self.ly.items())):
                i += 1
                if key == 'wind':
                    wi = i
                elif key == 'temp':
                    te = i
                elif key == 'rain':
                    ra = i
            for p in range(len(data[0])):
                for i in range(len(ly)):
                    maxy = max(maxy, max(data[i][p]))
                    if i == wi or i == te or i == ra:
                        maxw = max(maxw, max(data[i][p]))
            for p in range(len(data[0])):
                px = plt.subplot(p_y, p_x, p + 1)
                i = -1
                if self.two_axes:
                    px2 = px.twinx()
                for key, value in iter(sorted(self.ly.items())):
                    i += 1
                    lw = 2.0
                    if self.two_axes and key in self.ylabel2[0]:
                        px2.plot(x24, data[i][p], linewidth=lw, label=key, color=self.colours[key])
                    else:
                        px.plot(x24, data[i][p], linewidth=lw, label=key, color=self.colours[key])
                    plt.title(per_labels[p])
                plt.xlim([1, 24])
                plt.xticks(list(range(4, 25, 4)))
       #         px.set_xticklabels(labels])
  #              plt.xticks(range(0, 25, 4))
           #     plt.grid(axis='x')
                px.set_xticklabels(x_labels[1:])
                px.set_ylim([0, maxy])
                if self.two_axes:
                    px2.set_ylim(0, maxw)
                    if p in yl2:
                        px2.set_ylabel(self.ylabel2[2])
                if p >= xl:
                    px.set_xlabel('Hour of the Day')
                if p in yl:
                    px.set_ylabel(self.ylabel[1])
            if self.two_axes:
                lines = []
                for key in self.ly:
                    lines.append(mlines.Line2D([], [], color=self.colours[key], label=key))
                px.legend(handles=lines, loc='best')
            else:
                px.legend(loc='best')
            if self.maximise:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        papersizes = {'a0': '33.1,46.8', 'a1': '23.4,33.1', 'a2': '16.5,23.4',
                    'a3': '11.7,16.5', 'a4': '8.3,11.7', 'a5': '5.8,8.3',
                    'a6': '4.1,5.8', 'a7': '2.9,4.1', 'a8': '2,2.9',
                    'a9': '1.5,2', 'a10': '1,1.5', 'b0': '39.4,55.7',
                    'b1': '27.8,39.4', 'b2': '19.7,27.8', 'b3': '13.9,19.7',
                    'b4': '9.8,13.9', 'b5': '6.9,9.8', 'b6': '4.9,6.9',
                    'b7': '3.5,4.9', 'b8': '2.4,3.5', 'b9': '1.7,2.4',
                    'b10': '1.2,1.7', 'foolscap': '8.0,13.0', 'ledger': '8.5,14.0',
                    'legal': '8.5,14.09', 'letter': '8.5,11.0'}
        landscape = False
        papersize = ''
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.maximise = False
        seasons = []
        periods = []
        parents = []
        try:
            parents = getParents(config.items('Parents'))
        except:
            pass
        try:
            self.scenarios = config.get('Files', 'scenarios')
            for key, value in parents:
                self.scenarios = self.scenarios.replace(key, value)
            self.scenarios = self.scenarios.replace('$USER$', getUser())
            self.scenarios = self.scenarios.replace('$YEAR$', str(self.base_year))
            i = self.scenarios.rfind('/')
            self.scenarios = self.scenarios[:i + 1]
        except:
            self.scenarios = ''
        try:
            items = config.items('Power')
            for item, values in items:
                if item[:6] == 'season':
                    if item == 'season':
                        continue
                    i = int(item[6:]) - 1
                    if i >= len(seasons):
                        seasons.append([])
                    seasons[i] = values.split(',')
                    for j in range(1, len(seasons[i])):
                        seasons[i][j] = int(seasons[i][j]) - 1
                elif item[:6] == 'period':
                    if item == 'period':
                        continue
                    i = int(item[6:]) - 1
                    if i >= len(periods):
                        periods.append([])
                    periods[i] = values.split(',')
                    for j in range(1, len(periods[i])):
                        periods[i][j] = int(periods[i][j]) - 1
                elif item == 'maximise':
                    if values.lower() in ['true', 'on', 'yes']:
                        self.maximise = True
                elif item == 'save_format':
                    plt.rcParams['savefig.format'] = values
                elif item == 'figsize':
                    try:
                        papersize = papersizes[values]
                    except:
                        papersize = values
                elif item == 'orientation':
                    if values.lower()[0] == 'l':
                        landscape = True
        except:
            pass
        if papersize != '':
            if landscape:
                bit = papersize.split(',')
                plt.rcParams['figure.figsize'] = bit[1] + ',' + bit[0]
            else:
                plt.rcParams['figure.figsize'] = papersize
        if len(seasons) == 0:
            seasons = [['Summer', 11, 0, 1], ['Autumn', 2, 3, 4], ['Winter', 5, 6, 7], ['Spring', 8, 9, 10]]
        if len(periods) == 0:
            periods = [['Winter', 4, 5, 6, 7, 8, 9], ['Summer', 10, 11, 0, 1, 2, 3]]
        for i in range(len(periods)):
            for j in range(len(seasons)):
                if periods[i][0] == seasons[j][0]:
                    periods[i][0] += '2'
                    break
        mth_labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        ssn_labels = []
        for i in range(len(seasons)):
            ssn_labels.append('%s (%s-%s)' % (seasons[i][0], mth_labels[seasons[i][1]],
                               mth_labels[seasons[i][-1]]))
      #   ssn_labels = ['Summer (Dec, Jan-Feb)', 'Autumn (Mar-May)', 'Winter (Jun-Aug)', 'Spring(Sep-Nov)']
        smp_labels = []
        for i in range(len(periods)):
            smp_labels.append('%s (%s-%s)' % (periods[i][0], mth_labels[periods[i][1]],
                               mth_labels[periods[i][-1]]))
     #    smp_labels = ['Winter (May-Oct)', 'Summer (Nov-Apr)']
        labels = ['0:00', '4:00', '8:00', '12:00', '16:00', '20:00', '24:00']
        mth_xlabels = ['0:', '4:', '8:', '12:', '16:', '20:', '24:']
        m = 0
        d = 1
        day_labels = []
        while m < len(the_days):
            day_labels.append('%s %s' % (str(d), mth_labels[m]))
            d += 7
            if d > the_days[m]:
                d = d - the_days[m]
                m += 1
        lbl_font = FontProperties()
        lbl_font.set_size('small')
        x24 = []
        l24 = []
        m24 = []
        q24 = []
        s24 = []
        t12 = []
        for i in range(24):
            x24.append(i + 1)
        for i in range(len(self.ly)):
            if self.plots['total']:
                l24.append([])
                for j in range(24):
                    l24[i].append(0.)
            if self.plots['month']:
                m24.append([])
                for m in range(12):
                    m24[i].append([])
                    for j in range(24):
                        m24[i][m].append(0.)
            if self.plots['season']:
                q24.append([])
                for q in range(len(seasons)):
                    q24[i].append([])
                    for j in range(24):
                        q24[i][q].append(0.)
            if self.plots['period']:
                s24.append([])
                for s in range(len(periods)):
                    s24[i].append([])
                    for j in range(24):
                        s24[i][s].append(0.)
            if self.plots['monthly'] or self.plots['mthavg']:
                t12.append([])
                for m in range(14):
                    t12[i].append(0.)
        the_qtrs = []
        for i in range(len(seasons)):
            d = 0
            for j in range(1, len(seasons[i])):
                d += the_days[seasons[i][j]]
            the_qtrs.append(d)
        the_ssns = []
        for i in range(len(periods)):
            d = 0
            for j in range(1, len(periods[i])):
                d += the_days[periods[i][j]]
            the_ssns.append(d)
        the_hours = [0]
        i = 0
        for m in range(len(the_days)):
            i = i + the_days[m] * 24
            the_hours.append(i)
        d = -1
        for i in range(0, len(x), 24):
            m = 11
            d += 1
            while i < the_hours[m] and m > 0:
                m -= 1
            for k in range(24):
                j = -1
                for key, value in iter(sorted(self.ly.items())):
                    if len(value) == 0:
                        continue
                    j += 1
                    if self.plots['total']:
                        l24[j][k] += value[i + k]
                    if self.plots['month']:
                        m24[j][m][k] = m24[j][m][k] + value[i + k]
                    if self.plots['season']:
                        for q in range(len(seasons)):
                            if m in seasons[q]:
                                break
                        q24[j][q][k] = q24[j][q][k] + value[i + k]
                    if self.plots['period']:
                        for s in range(len(periods)):
                            if m in periods[s]:
                                break
                        s24[j][s][k] = s24[j][s][k] + value[i + k]
                    if self.plots['monthly'] or self.plots['mthavg']:
                        t12[j][m + 1] = t12[j][m + 1] + value[i + k]
        for i in range(len(ly)):
            for k in range(24):
                if self.plots['total']:
                    l24[i][k] = l24[i][k] / 365
                if self.plots['month']:
                    for m in range(12):
                        m24[i][m][k] = m24[i][m][k] / the_days[m]
                if self.plots['season']:
                    for q in range(len(seasons)):
                        q24[i][q][k] = q24[i][q][k] / the_qtrs[q]
                if self.plots['period']:
                    for s in range(len(periods)):
                        s24[i][s][k] = s24[i][s][k] / the_ssns[s]
        if self.plots['hour']:
            if self.plots['save_plot']:
                vals = ['hour']
                data = []
                data.append(x)
            fig = plt.figure('hour')
            plt.grid(True)
            hx = fig.add_subplot(111)
            plt.title(self.hdrs['hour'] + ' - ' + locn)
            maxy = 0
            if self.two_axes:
                hx2 = hx.twinx()
            for key, value in iter(sorted(self.ly.items())):
                lw = 2.0
                if self.two_axes and key in self.ylabel2[0]:
                    hx2.plot(x, value, linewidth=lw, label=key, color=self.colours[key])
                else:
                    hx.plot(x, value, linewidth=lw, label=key, color=self.colours[key])
                    maxy = max(maxy, max(value))
                if self.plots['save_plot']:
                    vals.append(key)
                    data.append(value)
            if self.plots['save_plot']:
                titl = 'hour'
                dialog = displaytable.Table(list(map(list, list(zip(*data)))), title=titl, fields=vals, save_folder=self.scenarios)
                dialog.exec_()
                del dialog, data, vals
            hx.set_ylim([0, maxy])
            plt.xlim([0, len(x)])
            plt.xticks(list(range(12, len(x), 168)))
            hx.set_xticklabels(day_labels, rotation='vertical')
            hx.set_xlabel('Month of the year')
            hx.set_ylabel(self.ylabel[0])
            hx.legend(loc='best')
            if self.two_axes:
                ylim = hx2.get_ylim()
                hx2.set_ylim(0, ylim[1])
                lines = []
                for key in self.ly:
                    lines.append(mlines.Line2D([], [], color=self.colours[key], label=key))
                hx.legend(handles=lines, loc='best')
                hx2.set_ylabel(self.ylabel2[1])
            if self.maximise:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            zp = ZoomPanX()
            if self.two_axes:
                f = zp.zoom_pan(hx2, base_scale=1.2) # enable scrollable zoom
            else:
                f = zp.zoom_pan(hx, base_scale=1.2) # enable scrollable zoom
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
            del zp
        if self.plots['total']:
            if self.plots['save_plot']:
                vals = ['hour of the day']
                decpts = [0]
                data = []
                data.append(x24)
            figt = plt.figure('total')
            plt.grid(True)
            tx = figt.add_subplot(111)
            plt.title(self.hdrs['total'] + ' - ' + locn)
            maxy = 0
            i = -1
            lw = 2.0
            if self.two_axes:
                tx2 = tx.twinx()
            for key, value in iter(sorted(self.ly.items())):
                i += 1
                if self.two_axes and key in self.ylabel2[0]:
                    tx2.plot(x24, l24[i], linewidth=lw, label=key, color=self.colours[key])
                else:
                    tx.plot(x24, l24[i], linewidth=lw, label=key, color=self.colours[key])
                    maxy = max(maxy, max(l24[i]))
                if self.plots['save_plot']:
                    vals.append(key)
                    data.append(l24[i])
                    if key == 'wind':
                        decpts.append(2)
                    else:
                        decpts.append(1)
            if self.plots['save_plot']:
                titl = 'total'
                dialog = displaytable.Table(list(map(list, list(zip(*data)))), title=titl, fields=vals, save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, data, vals
            tx.set_ylim([0, maxy])
            plt.xlim([1, 24])
            plt.xticks(list(range(4, 25, 4)))
            tx.set_xticklabels(labels[1:])
            tx.set_xlabel('Hour of the Day')
            tx.set_ylabel(self.ylabel[0])
            tx.legend(loc='best')
            if self.two_axes:
                ylim = tx2.get_ylim()
                tx2.set_ylim(0, ylim[1])
                lines = []
                for key in self.ly:
                    lines.append(mlines.Line2D([], [], color=self.colours[key], label=key))
                tx.legend(handles=lines, loc='best')
                tx2.set_ylabel(self.ylabel2[1])
            if self.maximise:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if self.plots['month']:
            dayPlot(self, 'month', m24, locn, mth_labels, mth_xlabels)
        if self.plots['season']:
            dayPlot(self, 'season', q24, locn, ssn_labels, labels)
        if self.plots['period']:
            dayPlot(self, 'period', s24, locn, smp_labels, labels)
        if 'pdf' in list(self.plots.keys()):
            if self.plots['pdf'] and self.plots['wind']:
                j = int(ceil(max(self.ly['wind'])))
                figp = plt.figure('pdf')
                plt.grid(True)
                px = figp.add_subplot(111)
                plt.title(self.hdrs['pdf'] + ' - ' + locn)
                px.hist(self.ly['wind'], j)
                px.set_ylabel('Number of occurences')
                px.set_xlabel('Wind Speed (m/s)')
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if self.plots['monthly']:
            if self.plots['save_plot']:
                vals = ['monthly']
                data = []
                data.append(x24[:12])
                decpts = [0]
            figt = plt.figure('monthly')
            plt.grid(True)
            tx = figt.add_subplot(111)
            plt.title(self.hdrs['monthly'] + ' - ' + locn)
            maxy = 0
            i = -1
            if self.two_axes:
                tx2 = tx.twinx()
            for key, value in iter(sorted(self.ly.items())):
                i += 1
                lw = 2.0
                if self.two_axes and key in self.ylabel2[0]:
                    tx2.step(x24[:14], t12[i], linewidth=lw, label=key, color=self.colours[key])
                else:
                    tx.step(x24[:14], t12[i], linewidth=lw, label=key, color=self.colours[key])
                    maxy = max(maxy, max(t12[i]) + 1)
                if self.plots['save_plot']:
                    vals.append(key)
                    data.append(t12[i][1:-1])
                    if key == 'wind':
                        decpts.append(2)
                    else:
                        decpts.append(1)
            if self.plots['save_plot']:
                titl = 'monthly'
                dialog = displaytable.Table(list(map(list, list(zip(*data)))), title=titl, fields=vals, save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, data, vals
            tx.set_ylim([0, maxy])
            tick_spot = []
            for i in range(12):
                tick_spot.append(i + 1.5)
            tx.set_xticks(tick_spot)
            tx.set_xticklabels(mth_labels)
            plt.xlim([1, 13.0])
            tx.set_xlabel('Month')
            tx.set_ylabel(self.ylabel[0])
            tx.legend(loc='best')
            if self.two_axes:
                ylim = tx2.get_ylim()
                tx2.set_ylim(0, ylim[1])
                lines = []
                for key in self.ly:
                    lines.append(mlines.Line2D([], [], color=self.colours[key], label=key))
                tx.legend(handles=lines, loc='best')
                tx2.set_ylabel(self.ylabel2[1])
            if self.maximise:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if self.plots['mthavg']:
            if self.plots['save_plot']:
                vals = ['monthly_average']
                data = []
                data.append(x24[:12])
                decpts = [0]
            figt = plt.figure('monthly_average')
            plt.grid(True)
            tx = figt.add_subplot(111)
            plt.title(self.hdrs['mthavg'] + ' - ' + locn)
            maxy = 0
            if self.two_axes:
                tx2 = tx.twinx()
            m12 = []
            for i in range(len(t12)):
                m12.append([])
                for m in range(1, 13):
                    m12[-1].append(t12[i][m] / the_days[m - 1] / 24.)
            i = -1
            lw = 2.0
            for key, value in iter(sorted(self.ly.items())):
                i += 1
                if self.two_axes and key in self.ylabel2[0]:
                    tx2.plot(x24[:12], m12[i], linewidth=lw, label=key, color=self.colours[key])
                else:
                    tx.plot(x24[:12], m12[i], linewidth=lw, label=key, color=self.colours[key])
                    maxy = max(maxy, max(m12[i]) + 1)
                if self.plots['save_plot']:
                    vals.append(key)
                    data.append(m12[i])
                    if key == 'wind':
                        decpts.append(2)
                    else:
                        decpts.append(1)
            if self.plots['save_plot']:
                titl = 'mthavg'
                dialog = displaytable.Table(list(map(list, list(zip(*data)))), title=titl, fields=vals, save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, data, vals
            tx.set_ylim([0, maxy])
            plt.xlim([1, 12])
            plt.xticks(list(range(1, 13, 1)))
            tx.set_xticklabels(mth_labels)
            tx.set_xlabel('Month')
            tx.set_ylabel(self.ylabel[0])
            tx.legend(loc='best')
            if self.two_axes:
                ylim = tx2.get_ylim()
                tx2.set_ylim(0, ylim[1])
                lines = []
                for key in self.ly:
                    lines.append(mlines.Line2D([], [], color=self.colours[key], label=key))
                tx.legend(handles=lines, loc='best')
                tx2.set_ylabel(self.ylabel2[1])
            if self.maximise:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if not self.plots['block']:
            plt.show()

    def __init__(self, latitude, longitude, year=None, adjust_wind=None):
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        if year is None:
            try:
                self.base_year = config.get('Base', 'year')
                self.base_year = str(self.base_year)
            except:
                self.base_year = '2012'
        else:
            self.base_year = year
        parents = []
        try:
            parents = getParents(config.items('Parents'))
        except:
            pass
        try:
            self.rain_files = config.get('Files', 'rain_files')
            for key, value in parents:
                self.rain_files = self.rain_files.replace(key, value)
            self.rain_files = self.rain_files.replace('$USER$', getUser())
            self.rain_files = self.rain_files.replace('$YEAR$', str(self.base_year))
        except:
            self.rain_files = ''
        try:
            self.solar_files = config.get('Files', 'solar_files')
            for key, value in parents:
                self.solar_files = self.solar_files.replace(key, value)
            self.solar_files = self.solar_files.replace('$USER$', getUser())
            self.solar_files = self.solar_files.replace('$YEAR$', str(self.base_year))
        except:
            self.solar_files = ''
        try:
            self.solar_index = config.get('Files', 'solar_index')
            for key, value in parents:
                self.solar_index = self.solar_index.replace(key, value)
            self.solar_index = self.solar_index.replace('$USER$', getUser())
            self.solar_index = self.solar_index.replace('$YEAR$', str(self.base_year))
        except:
            self.solar_index = ''
        try:
            self.wind_files = config.get('Files', 'wind_files')
            for key, value in parents:
                self.wind_files = self.wind_files.replace(key, value)
            self.wind_files = self.wind_files.replace('$USER$', getUser())
            self.wind_files = self.wind_files.replace('$YEAR$', str(self.base_year))
        except:
            self.wind_files = ''
        try:
            self.wind_index = config.get('Files', 'wind_index')
            for key, value in parents:
                self.wind_index = self.wind_index.replace(key, value)
            self.wind_index = self.wind_index.replace('$USER$', getUser())

            self.wind_index = self.wind_index.replace('$YEAR$', str(self.base_year))
        except:
            self.wind_index = ''
        rain = False
        try:
            variable = config.get('View', 'resource_rainfall')
            if variable.lower() in ['true', 'yes', 'on']:
                rain = True
        except:
            pass
        self.windy = adjust_wind
       # find closest solar file
        self.solar_file, dist, lat, lon = self.find_closest(latitude, longitude)
        if os.path.exists(self.solar_files + '/' + self.solar_file):
            comment = 'Solar: %s\n            at %s, %s (%s Km away)' % (self.solar_file, lat, lon, '{:0,.0f}'.format(dist))
        self.wind_file, dist, lat, lon = self.find_closest(latitude, longitude, wind=True)
        if os.path.exists(self.wind_files + '/' + self.wind_file):
            if comment != '':
                comment += '\n'
            comment += 'Wind: %s\n            at %s, %s (%s Km away)' % (self.wind_file, lat, lon, '{:0,.0f}'.format(dist))
        plot_order = ['show_menu', 'dhi', 'dni', 'ghi', 'temp', 'wind']
        if rain:
            plot_order.append('rain')
        plot_order2 = ['hour', 'total', 'month', 'season', 'period', 'mthavg', 'block'] #, 'pdf']
        for plt in plot_order2:
            plot_order.append(plt)
        if rain:
            plot_order.append('monthly')
        plot_order.append('save_plot')
        self.hdrs = {'show_menu': 'Check / Uncheck all',
                'dhi': 'Solar - DHI (Diffuse)',
                'dni': 'Solar - DNI (Beam)',
                'ghi': 'Solar - GHI (Global)',
                'temp': 'Solar - Temperature',
                'wind': 'Wind - Speed',
                'hour': 'Hourly weather',
                'total': 'Daily average',
                'month': 'Daily average by month',
                'season': 'Daily average by season',
                'period': 'Daily average by period',
                'mthavg': 'Monthly average',
                'block': 'Show plots one at a time',
                'pdf': 'Probability Density Function',
                'save_plot': 'Save plot data to a file'}
        if rain:
             self.hdrs['rain'] = 'Rainfall - mm'
             self.hdrs['monthly'] = 'Monthly totals'
        spacers = {'dhi': 'Weather values',
                   'hour': 'Choose plots (all use a full year of data)',
                   'save_plot': 'Save plot data'}
        weathers = ['dhi', 'dni', 'ghi', 'rain', 'temp', 'wind']
        self.plots = {}
        for i in range(len(plot_order)):
            self.plots[plot_order[i]] = False
        self.plots['total'] = True
        what_plots = whatPlots(self.plots, plot_order, self.hdrs, spacers, self.base_year, comment)
        what_plots.exec_()
        self.plots = what_plots.getValues()
        if self.plots is None:
            return
        if 'rain' not in list(self.plots.keys()):
            self.plots['monthly'] = False
            self.plots['rain'] = False
        self.x = []
        self.ly = {}
        self.text = ''
        rain_col = -1
        if self.plots['dhi'] or self.plots['dni'] or self.plots['ghi'] or self.plots['temp'] or self.plots['rain']:
            if os.path.exists(self.solar_files + '/' + self.solar_file):
                tf = open(self.solar_files + '/' + self.solar_file, 'r')
                lines = tf.readlines()
                tf.close()
                fst_row = len(lines) - 8760
                if self.plots['dhi']:
                    self.ly['dhi'] = []
                if self.plots['dni']:
                    self.ly['dni'] = []
                if self.plots['ghi']:
                    self.ly['ghi'] = []
                if self.plots['temp']:
                    self.ly['temp'] = []
                if self.plots['wind']:  # on the off chance there's no wind file we'll use what we can from solar
                    self.ly['wind'] = []
                    wind_col = -1
                if self.plots['rain']:
                    self.ly['rain'] = []
                if self.solar_file[-4:] == '.smw':
                    dhi_col = 9
                    dni_col = 8
                    ghi_col = 7
                    temp_col = 0
                elif self.solar_file[-10:] == '(TMY2).csv' or self.solar_file[-10:] == '(TMY3).csv' \
                  or self.solar_file[-10:] == '(INTL).csv' or self.solar_file[-4:] == '.csv':
                    ghi_col = -1
                    if fst_row < 3:
                        bits = lines[0].split(',')
                        src_lat = float(bits[4])
                        src_lon = float(bits[5])
                        src_zne = float(bits[6])
                    else:
                        cols = lines[fst_row - 3].split(',')
                        bits = lines[fst_row - 2].split(',')
                        for i in range(len(cols)):
                            if cols[i].lower() in ['latitude', 'lat']:
                                src_lat = float(bits[i])
                            elif cols[i].lower() in ['longitude', 'lon', 'long', 'lng']:
                                src_lon = float(bits[i])
                            elif cols[i].lower() in ['tz', 'timezone', 'time zone']:
                                src_zne = float(bits[i])
                    cols = lines[fst_row - 1].strip().split(',')
                    for i in range(len(cols)):
                        if cols[i].lower() in ['df', 'dhi', 'diffuse', 'diffuse horizontal',
                                               'diffuse horizontal irradiance']:
                            dhi_col = i
                        elif cols[i].lower() in ['dn', 'dni', 'beam', 'direct normal',
                                                 'direct normal irradiance']:
                            dni_col = i
                        elif cols[i].lower() in ['gh', 'ghi', 'global', 'global horizontal',
                                                 'global horizontal irradiance']:
                            ghi_col = i
                        elif cols[i].lower() in ['temp', 'tdry']:
                            temp_col = i
                        elif cols[i].lower() in ['wspd', 'wind speed']:
                            wind_col = i
                        elif cols[i].lower() in ['rain', 'rainfall', 'rainfall (mm)']:
                            rain_col = i
                for i in range(fst_row, len(lines)):
                    bits = lines[i].split(',')
                    if self.plots['dhi']:
                        self.ly['dhi'].append(float(bits[dhi_col]))
                    if self.plots['dni']:
                        self.ly['dni'].append(float(bits[dni_col]))
                    if self.plots['ghi']:
                        if ghi_col < 0:
                            zenith = getZenith(i - fst_row + 1, src_lat, src_lon, src_zne)
                            ghi_val = int(self.ly['dni'][-1] * cos(radians(zenith)) + self.ly['dhi'][-1])
                            self.ly['ghi'].append(ghi_val)
                        else:
                            self.ly['ghi'].append(float(bits[ghi_col]))
                    if self.plots['temp']:
                        self.ly['temp'].append(float(bits[temp_col]))
                    if self.plots['wind'] and wind_col >= 0:
                        self.ly['wind'].append(float(bits[wind_col]))
                    if self.plots['rain'] and rain_col >= 0:
                        self.ly['rain'].append(float(bits[rain_col]))
                for key in weathers:
                    try:
                        if len(self.ly[key]) == 0:
                            self.ly.pop(key)
                    except:
                        pass
                if len(self.ly) == 0:
                    return
            else:
                return
        if self.plots['wind']:
            if self.wind_file != '':
                if os.path.exists(self.wind_files + '/' + self.wind_file):
                    tf = open(self.wind_files + '/' + self.wind_file, 'r')
                    lines = tf.readlines()
                    tf.close()
                    fst_row = len(lines) - 8760
                    self.ly['wind'] = []  # we'll override and wind from the solar file
                    if self.windy is None:
                        pass
                    else:
                        self.ly['wind2'] = []
                    if self.wind_file[-4:] == '.srw':
                        units = lines[3].strip().split(',')
                        heights = lines[4].strip().split(',')
                        col = -1
                        for j in range(len(units)):
                            if units[j] == 'm/s':
                               if heights[j] == '50':
                                   col = j
                                   break
                        for i in range(fst_row, len(lines)):
                            bits = lines[i].split(',')
                            self.ly['wind'].append(float(bits[col]))
                            if self.windy is None:
                                pass
                            else:
                                self.ly['wind2'].append(float(bits[col]) * (self.windy[1] / self.windy[0]) ** 0.143)
                else:
                    return
        if self.plots['rain'] and rain_col < 0:
            if self.rain_files != '':
                self.rain_file, dist, lat, lon = self.find_closest(latitude, longitude, wind=True)
                if os.path.exists(self.rain_files + '/' + self.rain_file):
                    if comment != '':
                        comment += '\n'
                    comment += 'Rain: %s\n            at %s, %s (%s Km away)' % (self.rain_file, lat, lon, '{:0,.0f}'.format(dist))
                    tf = open(self.rain_files + '/' + self.rain_file, 'r')
                    lines = tf.readlines()
                    tf.close()
                    fst_row = len(lines) - 8760
                    self.ly['rain'] = []  # we'll override and wind from the solar file
                    cols = lines[fst_row - 1].strip().split(',')
                    for i in range(len(cols)):
                        if cols[i].lower() in ['rain', 'rainfall', 'rainfall (mm)']:
                            rain_col = i
                            break
                    for i in range(fst_row, len(lines)):
                        bits = lines[i].split(',')
                        self.ly['rain'].append(float(bits[rain_col]))
        len_x = 8760
        for i in range(len_x):
            self.x.append(i)
        self.colours = {'dhi': 'r', 'dni': 'y', 'ghi': 'orange', 'rain': 'c', 'temp': 'g', 'wind': 'b', 'wind2': 'black'}
        self.two_axes = False
        self.ylabel = ['Irradiance (W/m2)', 'Irrad (W/m2)']
        if (self.plots['dhi'] or self.plots['dni'] or self.plots['ghi']):
            if self.plots['temp']:
                self.two_axes = True
                self.ylabel2 = [['temp'], 'Temperature. (oC)', 'Temp. (oC)']
            if self.plots['wind']:
                if self.two_axes:
                    self.ylabel2 = [['temp', 'wind'], 'Wind (m/s) & Temp. (oC)', 'Wind & Temp.']
                else:
                    self.two_axes = True
                    self.ylabel2 = [['wind'], 'Wind Speed (m/s)', 'Wind (m/s)']
        elif self.plots['temp']:
            self.ylabel = ['Temperature. (oC)', 'Temp. (oC)']
            if self.plots['wind']:
                self.two_axes = True
                self.ylabel2 = [['wind'], 'Wind Speed (m/s)', 'Wind (m/s)']
        elif self.plots['wind']:
            self.ylabel = ['Wind Speed (m/s)', 'Wind (m/s)']
        elif self.plots['rain']:
            self.ylabel = ['Rainfall (mm)', 'Rain (mm)']
        self.showGraphs(self.ly, self.x, ' for location %s, %s - %s' % (latitude, longitude, self.base_year)) class PowerModel():
    powerExit = QtCore.pyqtSignal(str)
   # barProgress = QtCore.pyqtSignal(int, str)
   # barRange = QtCore.pyqtSignal(int, int)

    def showGraphs(self, ydata, x):
        def shrinkKey(key):
            remove = ['Biomass', 'Community', 'Farm', 'Fixed', 'Geothermal', 'Hydro', 'Pumped',
                      'PV', 'Rooftop', 'Solar', 'Station', 'Thermal', 'Tracking', 'Wave', 'Wind']
            oukey = key
            for i in range(len(remove)):
                oukey = oukey.replace(remove[i], '')
            oukey = ' '.join(oukey.split())
            if oukey == '' or oukey == 'Existing':
                return key
            else:
                return oukey

        def stepPlot(self, period, data, x_labels=None):
            k1 = list(data.keys())[0]
            if self.plots['cumulative']:
                pc = 1
            else:
                pc = 0
            if self.plots['gross_load']:
                pc += 1
            if self.plots['shortfall']:
                pc += 1
            fig = plt.figure(self.hdrs['by_' + period].title() + self.suffix)
            plt.grid(True)
            bbdx = fig.add_subplot(111)
            plt.title(self.hdrs['by_' + period].title() + self.suffix)
            maxy = 0
            miny = 0
            xs = []
            for i in range(len(data[k1]) + 1):
                xs.append(i)
            if self.plots['save_plot']:
                sp_data = []
                sp_data.append(xs[1:])
                if period == 'day':
                    sp_vals = [period, 'Date']
                    sp_data.append([])
                    mm = 0
                    dy = 1
                    for d in range(1, len(xs)):
                        sp_data[-1].append('%s-%s-%s' % (self.load_year,
                                           str(mm + 1).zfill(2), str(dy).zfill(2)))
                        dy += 1
                        if dy > the_days[mm]:
                            mm += 1
                            dy = 1
                else:
                    sp_vals = ['No.', period]
                    sp_data.append(x_labels)
            if self.plots['cumulative']:
                cumulative = [0.]
                for i in range(len(data[k1])):
                    cumulative.append(0.)
            load = []
            i = -1
            storage = None
            if self.plots['show_pct']:
                load_sum = 0.
                gen_sum = 0.
            for key, value in iter(sorted(ydata.items())):
                if key == 'Generation':
                    continue
                dval = [0.]
                if self.plots['show_pct']:
                    for d in range(len(data[key])):
                        if key[:4] == 'Load':
                            for k in range(len(data[key][d])):
                                load_sum += data[key][d][k]
                        elif key == 'Storage':
                            pass
                        else:
                            for k in range(len(data[key][d])):
                                gen_sum += data[key][d][k]
                                if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                    load_sum += data[key][d][k]
                for d in range(len(data[key])):
                   dval.append(0.)
                   for k in range(len(data[key][0])):
                       dval[-1] += data[key][d][k] / 1000
                maxy = max(maxy, max(dval))
                lw = self.other_width
                if self.plots['cumulative'] and key[:4] != 'Load' and key != 'Storage':
                    lw = 1.0
                    for j in range(len(xs)):
                        cumulative[j] += dval[j]
                bbdx.step(xs, dval, linewidth=lw, label=shrinkKey(key), color=self.colours[key],
                          linestyle=self.linestyle[key])
                if self.plots['save_plot']:
                    sp_vals.append(shrinkKey(key))
                    sp_data.append(dval[1:])
                if (self.plots['shortfall'] or self.plots['show_load']) and key[:4] == 'Load':
                    load = dval[:]
                if self.plots['shortfall'] and key == 'Storage':
                    storage = dval[:]
            if self.plots['show_pct']:
                self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                plt.title(self.hdrs['by_' + period].title() + self.suffix + self.gen_pct)
            if self.plots['cumulative']:
                bbdx.step(xs, cumulative, linewidth=self.other_width, label='Tot. Generation', color=self.colours['cumulative'])
                maxy = max(maxy, max(cumulative))
                if self.plots['save_plot']:
                    sp_vals.append('Tot. Generation')
                    sp_data.append(cumulative[1:])
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                pass
            if (self.plots['shortfall'] and self.do_load):
                load2 = []
                if storage is None:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] - load[i])
                        if load2[-1] < miny:
                            miny = load2[-1]
                else:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] + storage[i] - load[i])
                        if load2[-1] < miny:
                            miny = load2[-1]
                bbdx.step(xs, load2, linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                plt.axhline(0, color='black')
                if rndup != 0 and miny < 0:
                    miny = -ceil(-miny / rndup) * rndup
                if self.plots['save_plot']:
                    sp_vals.append('Shortfall')
                    sp_data.append(load2[1:])
            else:
                miny = 0
            if self.plots['save_plot']:
                titl = 'By_' + period
                decpts = [3] * len(sp_vals)
                decpts[0] = decpts[1] = 0
                dialog = displaytable.Table(list(map(list, list(zip(*sp_data)))), title=titl, fields=sp_vals,
                                            save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, sp_data, sp_vals
            plt.ylim([miny, maxy])
            plt.xlim([0, len(data[k1])])
            if (len(ydata) + pc) > 9:
                 # Shrink current axis by 5%
                box = bbdx.get_position()
                bbdx.set_position([box.x0, box.y0, box.width * 0.95, box.height])
                 # Put a legend to the right of the current axis
                bbdx.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop=lbl_font)
            else:
                bbdx.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=(len(ydata) + pc),
                            prop=lbl_font)
            rotn = 'horizontal'
            if len(data[k1]) > 12:
                stp = 7
                rotn = 'vertical'
            else:
                stp = 1
            plt.xticks(list(range(0, len(data[k1]), stp)))
            tick_spot = []
            for i in range(0, len(data[k1]), stp):
                tick_spot.append(i + .5)
            bbdx.set_xticks(tick_spot)
            bbdx.set_xticklabels(x_labels, rotation=rotn)
            bbdx.set_xlabel(period.title() + ' of the year')
            bbdx.set_ylabel('Energy (MWh)')
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()

        def dayPlot(self, period, data, per_labels=None, x_labels=None):
            k1 = list(data.keys())[0]
            if self.plots['cumulative']:
                pc = 1
            else:
                pc = 0
            if self.plots['gross_load']:
                pc += 1
            if self.plots['shortfall']:
                pc += 1
            hdr = self.hdrs[period].replace('Power - ', '')
            plt.figure(hdr + self.suffix)
            plt.suptitle(self.hdrs[period] + self.suffix, fontsize=16)
            maxy = 0
            miny = 0
            if len(data[k1]) > 9:
                p1 = 3
                p2 = 4
                xl = 8
                yl = [0, 4, 8]
            elif len(data[k1]) > 6:
                p1 = 3
                p2 = 3
                xl = 6
                yl = [0, 3, 6]
            elif len(data[k1]) > 4:
                p1 = 2
                p2 = 3
                xl = 3
                yl = [0, 3]
            elif len(data[k1]) > 2:
                p1 = 2
                p2 = 2
                xl = 2
                yl = [0, 2]
            else:
                p1 = 1
                p2 = 2
                xl = 0
                yl = [0, 1]
            for key in list(data.keys()):
                for p in range(len(data[key])):
                    maxy = max(maxy, max(data[key][p]))
            if self.plots['show_pct']:
                load_sum = []
                gen_sum = []
                for p in range(len(data[k1])):
                    load_sum.append(0.)
                    gen_sum.append(0.)
            for p in range(len(data[k1])):
                if self.plots['cumulative']:
                    cumulative = []
                    for i in range(len(x24)):
                        cumulative.append(0.)
                if self.plots['gross_load']:
                    gross_load = []
                    for i in range(len(x24)):
                        gross_load.append(0.)
                px = plt.subplot(p1, p2, p + 1)
                l_k = ''
                for key, value in iter(sorted(ydata.items())):
                    if key == 'Generation':
                        continue
                    if key[:4] == 'Load':
                        l_k = key
                    if self.plots['show_pct']:
                        for d in range(len(data[key][p])):
                            if key[:4] == 'Load':
                                load_sum[p] += data[key][p][d]
                            elif key == 'Storage':
                                pass
                            else:
                                gen_sum[p] += data[key][p][d]
                                if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                    load_sum[p] += data[key][p][d]
                    lw = self.other_width
                    if self.plots['cumulative'] and key[:4] != 'Load' and key != 'Storage':
                        lw = 1.0
                        for j in range(len(x24)):
                            cumulative[j] += data[key][p][j]
                    if self.plots['gross_load'] and (key[:4] == 'Load' or
                      key == 'Existing Rooftop PV'):
                        for j in range(len(x24)):
                            gross_load[j] += data[key][p][j]
                    px.plot(x24, data[key][p], linewidth=lw, label=shrinkKey(key),
                            color=self.colours[key], linestyle=self.linestyle[key])
                    plt.title(per_labels[p])
                if self.plots['cumulative']:
                    px.plot(x24, cumulative, linewidth=self.other_width, label='Tot. Generation',
                            color=self.colours['cumulative'])
                    maxy = max(maxy, max(cumulative))
                if self.plots['gross_load'] and 'Existing Rooftop PV' in list(ydata.keys()):
                    px.plot(x24, gross_load, linewidth=1.0, label='Gross Load', color=self.colours['gross_load'])
                    maxy = max(maxy, max(gross_load))
                if self.plots['shortfall'] and self.do_load:
                    load2 = []
                    for i in range(len(x24)):
                        load2.append(cumulative[i] - data[l_k][p][i])
                    miny = min(miny, min(load2))
                    px.plot(x24, load2, linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                    plt.axhline(0, color='black')
                plt.xticks(list(range(4, 25, 4)))
                px.set_xticklabels(x_labels[1:])
                plt.xlim([1, 24])
                if p >= xl:
                    px.set_xlabel('Hour of the Day')
                if p in yl:
                    px.set_ylabel('Power (MW)')
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                pass
            if self.plots['shortfall']:
                if rndup != 0 and miny < 0:
                    miny = -ceil(-miny / rndup) * rndup
            for p in range(len(data[k1])):
                px = plt.subplot(p1, p2, p + 1)
                plt.ylim([miny, maxy])
                plt.xlim([1, 24])
                if self.plots['show_pct']:
                    pct = ' (%s%%)' % '{:0,.1f}'.format(gen_sum[p] * 100. / load_sum[p])
                    titl = px.get_title()
                    px.set_title(titl + pct)
                    #  px.annotate(pct, xy=(1.0, 3.0))
            px = plt.subplot(p1, p2, len(data[k1]))
         #    px.legend(bbox_to_anchor=[1., -0.15], loc='best', ncol=min((len(ly) + pc), 9),
         # prop=lbl_font)
            if (len(ydata) + pc) > 9:
                if len(data[k1]) > 9:
                    do_in = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
                elif len(data[k1]) > 6:
                    do_in = [1, 4, 7, 2, 5, 8, 3, 6, 9]
                elif len(data[k1]) > 4:
                    do_in = [1, 4, 2, 5, 3, 6]
                elif len(data[k1]) > 2:
                    do_in = [1, 3, 2, 4]
                else:
                    do_in = [1, 2]
                do_in = do_in[:len(data[k1])]
                for i in range(len(do_in)):
                    px = plt.subplot(p1, p2, do_in[i])
                 # Shrink current axis by 5%
                    box = px.get_position()
                    px.set_position([box.x0, box.y0, box.width * 0.95, box.height])
                 # Put a legend to the right of the current axis
                px.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop=lbl_font)
            else:
                px.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=(len(ydata) + pc),
                          prop=lbl_font)
            if self.plots['show_pct']:
                for p in range(1, len(gen_sum)):
                    load_sum[0] += load_sum[p]
                    gen_sum[0] += gen_sum[p]
                self.gen_pct = ' (%s%%) of load)' % '{:0,.1f}'.format(gen_sum[0] * 100. / load_sum[0])
                titl = px.get_title()
                plt.suptitle(self.hdrs[period] + self.suffix + self.gen_pct, fontsize=16)
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()

        def saveBalance(self, shortstuff):
            data_file = 'Powerbalance_data_%s.xls' % (
                        QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                        'yyyy-MM-dd_hhmm'))
            data_file = QtWidgets.QFileDialog.getSaveFileName(None, 'Save Powerbalance data file',
                        self.scenarios + data_file, 'Excel Files (*.xls*);;CSV Files (*.csv)')[0]
            if data_file != '':
                if data_file[-4:] == '.csv' or data_file[-4:] == '.xls' \
                  or data_file[-5:] == '.xlsx':
                    pass
                else:
                    data_file += '.xls'
                if os.path.exists(data_file):
                    if os.path.exists(data_file + '~'):
                        os.remove(data_file + '~')
                    os.rename(data_file, data_file + '~')
                stns = {}
                techs = {}
                for i in range(len(self.power_summary)):
                    stns[self.power_summary[i].name] = i
                    techs[self.power_summary[i].technology] = [0., 0., 0.]
                if data_file[-4:] == '.csv':
                    tf = open(data_file, 'w')
                    line = 'Generation Summary Table'
                    tf.write(line + '\n')
                    line = 'Name,Technology,Capacity (MW),CF,Generation'
                    if getattr(self.power_summary[0], 'transmitted') != None:
                        line += ',Transmitted'
                    tf.write(line + '\n')
                    for key, value in iter(sorted(stns.items())):
                        if self.power_summary[value].generation > 0:
                            cf = '{:0.2f}'.format(self.power_summary[value].generation /
                                 (self.power_summary[value].capacity * 8760))
                        else:
                            cf = ''
                        if self.power_summary[value].transmitted is not None:
                            ts = '{:0.2f}'.format(self.power_summary[value].transmitted)
                            techs[self.power_summary[value].technology][2] += self.power_summary[value].transmitted
                        else:
                            ts = ''
                        line = '"%s",%s,%s,%s,%s,%s' % (self.power_summary[value].name,
                                               self.power_summary[value].technology,
                                               '{:0.2f}'.format(self.power_summary[value].capacity),
                                               cf,
                                               '{:0.0f}'.format(self.power_summary[value].generation),
                                               ts)
                        techs[self.power_summary[value].technology][0] += self.power_summary[value].capacity
                        techs[self.power_summary[value].technology][1] += self.power_summary[value].generation
                        tf.write(line + '\n')
                    total = [0., 0., 0.]
                    for key, value in iter(sorted(techs.items())):
                        total[0] += value[0]
                        total[1] += value[1]
                        if value[2] > 0:
                            v2 = ',{:0.0f}'.format(value[2])
                            total[2] += value[2]
                        else:
                            v2 = ''
                        line = ',%s,%s,,%s%s' % (key,
                                               '{:0.2f}'.format(value[0]),
                                               '{:0.0f}'.format(value[1]),
                                               v2)
                        tf.write(line + '\n')
                    if total[2] > 0:
                        v2 = ',{:0.0f}'.format(total[2])
                        total[2] += value[2]
                    else:
                        v2 = ''
                    line = ',Total,%s,,%s%s' % ('{:0.2f}'.format(total[0]),
                                               '{:0.0f}'.format(total[1]),
                                               v2)
                    tf.write(line + '\n')
                    line = '\nHourly Shortfall Table'
                    tf.write(line + '\n')
                    line = 'Hour,Period,Shortfall'
                    tf.write(line + '\n')
                    for i in range(len(shortstuff)):
                        line = '%s,%s,%s' % (str(shortstuff[i].hour), shortstuff[i].period,
                                             '{:0.2f}'.format(shortstuff[i].shortfall))
                        tf.write(line + '\n')
                    tf.close()
                else:
                    wb = xlwt.Workbook()
                    fnt = xlwt.Font()
                    fnt.bold = True
                    styleb = xlwt.XFStyle()
                    styleb.font = fnt
                    style2d = xlwt.XFStyle()
                    style2d.num_format_str = '#,##0.00'
                    style0d = xlwt.XFStyle()
                    style0d.num_format_str = '#,##0'
                    pattern = xlwt.Pattern()
                    pattern.pattern = xlwt.Pattern.SOLID_PATTERN
                    pattern.pattern_fore_colour = xlwt.Style.colour_map['ice_blue']
                    style2db = xlwt.XFStyle()
                    style2db.num_format_str = '#,##0.00'
                    style2db.pattern = pattern
                    style0db = xlwt.XFStyle()
                    style0db.num_format_str = '#,##0'
                    style0db.pattern = pattern
                    ws = wb.add_sheet('Powermatch')
                    xl_lens = {}
                    row = 0
                    col = 0
                    ws.write(row, col, 'Hourly Shortfall Table', styleb)
                    row += 1
                    shrt_cols = ['Hour', 'Period', 'Shortfall']
                    for i in range(len(shrt_cols)):
                        ws.write(row, col + i, shrt_cols[i], styleb)
                        xl_lens[col + i] = 0
                    row += 1
                    for i in range(len(shortstuff)):
                        ws.write(row, col, shortstuff[i].hour)
                        ws.write(row, col + 1, shortstuff[i].period)
                        xl_lens[col + 1] = max(xl_lens[col + 1], len(shortstuff[i].period))
                        ws.write(row, col + 2, shortstuff[i].shortfall, style2db)
                        row += 1
                    row = 0
                    col = len(shrt_cols) + 1
                    ws.write(row, col, 'Generation Summary Table', styleb)
                    sum_cols = ['Name', 'Technology', 'Capacity (MW)', 'CF', 'Generated\n(to be\ncosted)']
                    if getattr(self.power_summary[0], 'transmitted') != None:
                        sum_cols.append('Transmitted\n(reduces\nShortfall)')
                    for i in range(len(sum_cols)):
                        ws.write(1, col + i, sum_cols[i], styleb)
                        j = sum_cols[i].find('\n') - 1
                        if j < 0:
                            j = len(sum_cols[i])
                        xl_lens[col + i] = j
                    for key, value in iter(stns.items()):
                        techs[self.power_summary[value].technology][0] += self.power_summary[value].capacity
                        techs[self.power_summary[value].technology][1] += self.power_summary[value].generation
                        if self.power_summary[value].transmitted is not None:
                            techs[self.power_summary[value].technology][2] += self.power_summary[value].transmitted
                    total = [0., 0., 0.]
                    row = 2
                    ws.write(row, col, 'Totals', styleb)
                    row += 1
                    for key, value in iter(sorted(techs.items())):
                        ws.write(row, col + 1, key)
                        ws.write(row, col + 2, value[0], style2db)
                        total[0] += value[0]
                        ws.write(row, col + 4, value[1], style0db)
                        total[1] += value[1]
                        if value[2] > 0:
                            ws.write(row, col + 5, value[2], style0d)
                            total[2] += value[2]
                        row += 1
                    ws.write(row, col + 1, 'Total', styleb)
                    ws.write(row, col + 2, total[0], style2db)
                    ws.write(row, col + 4, total[1], style0db)
                    if total[2] > 0:
                        ws.write(row, col + 5, total[2], style0d)
                    row += 1
                    ws.write(row, col, 'Stations', styleb)
                    row += 1
                    for key, value in iter(sorted(stns.items())):
                        ws.write(row, col, self.power_summary[value].name)
                        xl_lens[col] = max(xl_lens[col], len(self.power_summary[value].name))
                        ws.write(row, col + 1, self.power_summary[value].technology)
                        xl_lens[col + 1] = max(xl_lens[col + 1], len(self.power_summary[value].technology))
                        ws.write(row, col + 2, self.power_summary[value].capacity, style2d)
                        if self.power_summary[value].generation > 0:
                            ws.write(row, col + 3, self.power_summary[value].generation /
                                     (self.power_summary[value].capacity * 8760), style2d)
                        ws.write(row, col + 4, self.power_summary[value].generation, style0d)
                        if self.power_summary[value].transmitted is not None:
                            ws.write(row, col + 5, self.power_summary[value].transmitted, style0d)
                        row += 1
                    for key in xl_lens:
                        if xl_lens[key] * 275 > ws.col(key).width:
                            ws.col(key).width = xl_lens[key] * 275
                    ws.row(1).height_mismatch = True
                    ws.row(1).height = 256 * 3
                    ws.set_panes_frozen(True)
                    ws.set_horz_split_pos(2)
                    ws.set_remove_splits(True)
                    wb.save(data_file)

        def saveMatch(self, shortstuff):
            def cell_format(cell, new_cell):
                if cell.has_style:
                    new_cell.number_format = cell.number_format

         #   for i in range(len(shortstuff)):
          #             ws.write(row, col, shortstuff[i].hour)
            ts = oxl.load_workbook(self.pm_template)
            ws = ts.active
            type_tags = ['name', 'tech', 'cap', 'cf', 'gen', 'tmit', 'hrly']
            tech_tags = ['load', 'wind', 'offw', 'roof', 'fixed', 'single', 'dual', 'biomass', 'geotherm', 'other1', 'cst']
            tech_names = ['Load', 'Wind', 'Offshore Wind', 'Rooftop PV', 'Fixed PV', 'Tracking PV', 'Dual Axis PV',
                          'Biomass', 'Geothermal', 'Other1', 'CST']
            tech_names2 = [''] * len(tech_names)
            tech_names2[tech_names.index('Wind')] = 'Onshore Wind'
            tech_names2[tech_names.index('Tracking PV')] = 'Dual Axis PV'
            tech_names2[tech_names.index('CST')] = 'Solar Thermal'
            st_row = []
            st_col = []
            tech_row = []
            tech_col = []
            for i in range(len(type_tags)):
                st_row.append(0)
                st_col.append(0)
            for j in range(len(tech_tags)):
                tech_row.append([])
                tech_col.append([])
                for i in range(len(type_tags)):
                    tech_row[-1].append(0)
                    tech_col[-1].append(0)
            per_row = [0, 0]
            per_col= [0, 0]
            for row in range(1, ws.max_row + 1):
                for col in range(1, ws.max_column + 1):
                    try:
                        if ws.cell(row=row, column=col).value[0] != '<':
                            continue
                        if ws.cell(row=row, column=col).value == '<title>':
                            titl = ''
                            for stn in self.stations:
                                if stn.scenario not in titl:
                                    titl += stn.scenario + '; '
                            try:
                                titl = titl[:-2]
                                titl = titl.replace('.xls', '')
                                ws.cell(row=row, column=col).value = titl
                            except:
                                ws.cell(row=row, column=col).value = None
                        elif ws.cell(row=row, column=col).value == '<date>':
                            dte = QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                                  'yyyy-MM-dd hh:mm')
                            ws.cell(row=row, column=col).value = dte
                        elif ws.cell(row=row, column=col).value == '<period>':
                            per_row[1] = row
                            per_col[1] = col
                            ws.cell(row=row, column=col).value = None
                        elif ws.cell(row=row, column=col).value == '<hour>':
                            per_row[0] = row
                            per_col[0] = col
                            ws.cell(row=row, column=col).value = None
                        elif ws.cell(row=row, column=col).value == '<year>':
                            ws.cell(row=row, column=col).value = str(self.base_year)
                        elif ws.cell(row=row, column=col).value == '<growth>':
                            if self.load_multiplier != 0:
                                ws.cell(row=row, column=col).value = self.load_multiplier
                            else:
                                ws.cell(row=row, column=col).value = None
                        elif ws.cell(row=row, column=col).value[:5] == '<stn_':
                            bit = ws.cell(row=row, column=col).value[:-1].split('_')
                            ty = type_tags.index(bit[-1])
                            st_row[ty] = row
                            st_col[ty] = col
                            ws.cell(row=row, column=col).value = None
                        elif ws.cell(row=row, column=col).value.find('_') > 0:
                            bit = ws.cell(row=row, column=col).value[1:-1].split('_')
                            te = tech_tags.index(bit[0])
                            ty = type_tags.index(bit[-1])
                            tech_row[te][ty] = row
                            tech_col[te][ty] = col
                            ws.cell(row=row, column=col).value = None
                    except:
                        pass
            data_file = 'Powermatch_data_%s.xlsx' % (
                        QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                        'yyyy-MM-dd_hhmm'))
            data_file = QtWidgets.QFileDialog.getSaveFileName(None,
                        'Save Powermatch data file',
                        self.scenarios + data_file, 'Excel Files (*.xlsx)')[0]
            if data_file == '':
                return
            if data_file[-5:] != '.xlsx':
                data_file += '.xlsx'
            if os.path.exists(data_file):
                if os.path.exists(data_file + '~'):
                    os.remove(data_file + '~')
                os.rename(data_file, data_file + '~')
            stns = {}
            techs = {}
            for i in range(len(self.power_summary)):
                stns[self.power_summary[i].name] = i
                techs[self.power_summary[i].technology] = [0., 0., 0.]
            st = 0
            for key, value in iter(sorted(stns.items())):
                ws.cell(row=st_row[0] + st, column=st_col[0]).value = self.power_summary[value].name
                ws.cell(row=st_row[1] + st, column=st_col[1]).value = self.power_summary[value].technology
                ws.cell(row=st_row[2] + st, column=st_col[2]).value = self.power_summary[value].capacity
                if self.power_summary[value].generation > 0:
                    ws.cell(row=st_row[3] + st, column=st_col[3]).value = self.power_summary[value].generation / \
                             (self.power_summary[value].capacity * 8760)
                ws.cell(row=st_row[4] + st, column=st_col[4]).value = self.power_summary[value].generation
                if self.power_summary[value].transmitted is not None:
                    ws.cell(row=st_row[5] + st, column=st_col[5]).value = self.power_summary[value].transmitted
                st += 1
            for key, value in iter(stns.items()):
                techs[self.power_summary[value].technology][0] += self.power_summary[value].capacity
                techs[self.power_summary[value].technology][1] += self.power_summary[value].generation
                if self.power_summary[value].transmitted is not None:
                    techs[self.power_summary[value].technology][2] += self.power_summary[value].transmitted
            for key, value in iter(techs.items()):
                try:
                    te = tech_names.index(key)
                except:
                    try:
                        te = tech_names2.index(key)
                    except:
                        continue
                ws.cell(row=tech_row[te][2], column=tech_col[te][2]).value = value[0]
                ws.cell(row=tech_row[te][4], column=tech_col[te][4]).value = value[1]
                if self.plots['grid_losses']:
                    ws.cell(row=tech_row[te][5], column=tech_col[te][5]).value = value[2]
                if value[1] > 0:
                    ws.cell(row=tech_row[te][3], column=tech_col[te][3]).value = \
                      value[1] / (value[0] * 8760)
            if per_row[0] > 0:
                for i in range(8760):
                    ws.cell(row=per_row[0] + i, column=per_col[0]).value = shortstuff[i].hour
                    cell_format(ws.cell(row=per_row[0], column=per_col[0]), ws.cell(row=per_row[0] + i, column=per_col[0]))
            if per_row[1] > 0:
                for i in range(8760):
                    ws.cell(row=per_row[1] + i, column=per_col[1]).value = shortstuff[i].period
                    cell_format(ws.cell(row=per_row[1], column=per_col[1]), ws.cell(row=per_row[1] + i, column=per_col[1]))
            if tech_row[0][6] > 0:
                for i in range(8760):
                    ws.cell(row=tech_row[0][6] + i, column=tech_col[0][6]).value = shortstuff[i].load
                    cell_format(ws.cell(row=tech_row[0][6], column=tech_col[0][6]), ws.cell(row=tech_row[0][6] + i,
                                column=tech_col[0][6]))
            ly_keys = []
            for t in range(len(tech_names)):
                ly_keys.append([])
            if self.plots['by_station']:
                for t in range(len(self.stn_tech)):
                    try:
                        i = tech_names.index(self.stn_tech[t])
                    except:
                        try:
                            i = tech_names2.index(self.stn_tech[t])
                        except:
                            continue
                    ly_keys[i].append(self.stn_outs[t])
            else:
                for t in range(len(tech_names)):
                    if tech_names[t] in list(techs.keys()):
                        ly_keys[t].append(tech_names[t])
                    if tech_names2[t] != '':
                        if tech_names2[t] in list(techs.keys()):
                            ly_keys[t].append(tech_names2[t])
            for te in range(len(tech_row)):
                if tech_row[te][6] == 0 or len(ly_keys[te]) == 0:
                    continue
                hrly = [0.] * 8760
                doit = False
                for key in ly_keys[te]:
                    try:
                        values = self.ly[key]
                        for h in range(len(hrly)):
                            hrly[h] += values[h]
                            if hrly[h] != 0:
                                doit = True
                    except:
                        pass
                if doit or not doit:
                    for h in range(len(hrly)):
                        ws.cell(row=tech_row[te][6] + h, column=tech_col[te][6]).value = hrly[h]
                        cell_format(ws.cell(row=tech_row[te][6], column=tech_col[te][6]), \
                                    ws.cell(row=tech_row[te][6] + h, column=tech_col[te][6]))
            ts.save(data_file)

        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        try:
            mapc = config.get('Map', 'map_choice')
        except:
            mapc = ''
        self.colours = {'cumulative': '#006400', 'gross_load': '#a9a9a9', 'load': '#000000',
                        'shortfall': '#8b0000', 'wind': '#6688bb'}
        try:
            colors = config.items('Colors')
            for item, colour in colors:
                if item in self.technologies or item in self.colours:
                    itm = techClean(item)
                    self.colours[itm] = colour
        except:
            pass
        if mapc != '':
            try:
                colors = config.items('Colors' + mapc)
                for item, colour in colors:
                    if item in self.technologies or item in self.colours:
                        itm = techClean(item)
                        self.colours[itm] = colour
            except:
                pass
        papersizes = {'a0': '33.1,46.8', 'a1': '23.4,33.1', 'a2': '16.5,23.4',
                    'a3': '11.7,16.5', 'a4': '8.3,11.7', 'a5': '5.8,8.3',
                    'a6': '4.1,5.8', 'a7': '2.9,4.1', 'a8': '2,2.9',
                    'a9': '1.5,2', 'a10': '1,1.5', 'b0': '39.4,55.7',
                    'b1': '27.8,39.4', 'b2': '19.7,27.8', 'b3': '13.9,19.7',
                    'b4': '9.8,13.9', 'b5': '6.9,9.8', 'b6': '4.9,6.9',
                    'b7': '3.5,4.9', 'b8': '2.4,3.5', 'b9': '1.7,2.4',
                    'b10': '1.2,1.7', 'foolscap': '8.0,13.0', 'ledger': '8.5,14.0',
                    'legal': '8.5,14.09', 'letter': '8.5,11.0'}
        landscape = False
        papersize = ''
        self.other_width = 2.
        seasons = []
        periods = []
        try:
            items = config.items('Power')
        except:
            seasons = [[], [], [], []]
            seasons[0] = ['Summer', 11, 0, 1]
            seasons[1] = ['Autumn', 2, 3, 4]
            seasons[2] = ['Winter', 5, 6, 7]
            seasons[3] = ['Spring', 8, 9, 10]
            periods = [[], []]
            periods[0] = ['Winter', 4, 5, 6, 7, 8, 9]
            periods[1] = ['Summer', 10, 11, 0, 1, 2, 3]
        for item, values in items:
            if item[:6] == 'season':
                if item == 'season':
                    continue
                i = int(item[6:]) - 1
                if i >= len(seasons):
                    seasons.append([])
                seasons[i] = values.split(',')
                for j in range(1, len(seasons[i])):
                    seasons[i][j] = int(seasons[i][j]) - 1
            elif item[:6] == 'period':
                if item == 'period':
                    continue
                i = int(item[6:]) - 1
                if i >= len(periods):
                    periods.append([])
                periods[i] = values.split(',')
                for j in range(1, len(periods[i])):
                    periods[i][j] = int(periods[i][j]) - 1
            elif item == 'other_width':
                try:
                    self.other_width = float(values)
                except:
                    pass
            elif item == 'save_format':
                plt.rcParams['savefig.format'] = values
            elif item == 'figsize':
                try:
                    papersize = papersizes[values]
                except:
                    papersize = values
            elif item == 'orientation':
                if values.lower()[0] == 'l':
                    landscape = True
            elif item == 'debug_sam':
                if values.lower() in ['true', 'yes', 'on']:
                    self.debug = True
                else:
                    self.debug = False
        if papersize != '':
            if landscape:
                bit = papersize.split(',')
                plt.rcParams['figure.figsize'] = bit[1] + ',' + bit[0]
            else:
                plt.rcParams['figure.figsize'] = papersize
        try:
            self.pm_template = config.get('Power', 'pm_template')
        except:
            try:
                self.pm_template = config.get('Files', 'pm_template')
            except:
                self.pm_template = False
        if self.pm_template:
            try:
                parents = getParents(config.items('Parents'))
                for key, value in parents:
                    self.pm_template = self.pm_template.replace(key, value)
                self.pm_template = self.pm_template.replace('$USER$', getUser())
                if not os.path.exists(self.pm_template):
                    self.pm_template = False
            except:
                pass
        mth_labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
                      'Nov', 'Dec']
        ssn_labels = []
        for i in range(len(seasons)):
            if len(seasons[i]) == 2:
                ssn_labels.append('%s (%s)' % (seasons[i][0], mth_labels[seasons[i][1]]))
            else:
                ssn_labels.append('%s (%s-%s)' % (seasons[i][0], mth_labels[seasons[i][1]],
                                   mth_labels[seasons[i][-1]]))
        smp_labels = []
        for i in range(len(periods)):
            if len(periods[i]) == 2:
                smp_labels.append('%s (%s)' % (periods[i][0], mth_labels[periods[i][1]]))
            else:
                smp_labels.append('%s (%s-%s)' % (periods[i][0], mth_labels[periods[i][1]],
                                   mth_labels[periods[i][-1]]))
        labels = ['0:00', '4:00', '8:00', '12:00', '16:00', '20:00', '24:00']
        mth_xlabels = ['0:', '4:', '8:', '12:', '16:', '20:', '24:']
        pct_labels = ['0%', '20%', '40%', '60%', '80%', '100%']
        m = 0
        d = 1
        day_labels = []
        while m < len(the_days):
            day_labels.append('%s %s' % (str(d), mth_labels[m]))
            d += 7
            if d > the_days[m]:
                d = d - the_days[m]
                m += 1
        lbl_font = FontProperties()
        lbl_font.set_size('small')
        x24 = []
        l24 = {}
        m24 = {}
        q24 = {}
        s24 = {}
        d365 = {}
        for i in range(24):
            x24.append(i + 1)
        for key in list(ydata.keys()):
            if self.plots['total']:
                l24[key] = []
                for j in range(24):
                    l24[key].append(0.)
            if self.plots['month'] or self.plots['by_month']:
                m24[key] = []
                for m in range(12):
                    m24[key].append([])
                    for j in range(24):
                        m24[key][m].append(0.)
            if self.plots['season'] or self.plots['by_season']:
                q24[key] = []
                for q in range(len(seasons)):
                    q24[key].append([])
                    for j in range(24):
                        q24[key][q].append(0.)
            if self.plots['period'] or self.plots['by_period']:
                s24[key] = []
                for s in range(len(periods)):
                    s24[key].append([])
                    for j in range(24):
                        s24[key][s].append(0.)
            if self.plots['by_day']:
                d365[key] = []
                for j in range(365):
                    d365[key].append([0.])
        the_qtrs = []
        for i in range(len(seasons)):
            d = 0
            for j in range(1, len(seasons[i])):
                d += the_days[seasons[i][j]]
            the_qtrs.append(d)
        the_ssns = []
        for i in range(len(periods)):
            d = 0
            for j in range(1, len(periods[i])):
                d += the_days[periods[i][j]]
            the_ssns.append(d)
        the_hours = [0]
        i = 0
        for m in range(len(the_days)):
            i = i + the_days[m] * 24
            the_hours.append(i)
        d = -1
        for i in range(0, len(x), 24):
            m = 11
            d += 1
            while i < the_hours[m] and m > 0:
                m -= 1
            for k in range(24):
                for key, value in iter(sorted(ydata.items())):
                    if key == 'Generation':
                        continue
                    if self.plots['total']:
                        l24[key][k] += value[i + k]
                    if self.plots['by_day']:
                        d365[key][d][0] += value[i + k]
                    if self.plots['month'] or self.plots['by_month']:
                        m24[key][m][k] = m24[key][m][k] + value[i + k]
                    if self.plots['season'] or self.plots['by_season']:
                        for q in range(len(seasons)):
                            if m in seasons[q]:
                                break
                        q24[key][q][k] = q24[key][q][k] + value[i + k]
                    if self.plots['period'] or self.plots['by_period']:
                        for s in range(len(periods)):
                            if m in periods[s]:
                                break
                        s24[key][s][k] = s24[key][s][k] + value[i + k]
        if self.plots['cumulative']:
            pc = 1
        else:
            pc = 0
        if self.plots['gross_load']:
            pc += 1
        if self.plots['shortfall']:
            pc += 1
        colours = ['r', 'g', 'b', 'c', 'm', 'y', 'orange', 'darkcyan', 'darkmagenta',
                   'darkolivegreen', 'darkorange', 'darkturquoise', 'darkviolet', 'violet']
        colour_index = 0
        linestyles = ['-', '--', '-.', ':']
        line_index = 0
        self.linestyle = {}
        for key in self.colours:
            self.linestyle[key] = '-'
        for key in ydata:
            if key not in self.colours:
                if key[:4] == 'Load':
                    try:
                        self.colours[key] = self.colours['load']
                    except:
                        self.colours[key] = 'black'
                    self.linestyle[key] = '-'
                else:
                    self.colours[key] = colours[colour_index]
                    self.linestyle[key] = linestyles[line_index]
                    colour_index += 1
                    if colour_index >= len(colours):
                        colour_index = 0
                        line_index += 1
                        if line_index >= len(linestyles):
                            line_index = 0
        if self.plots['by_day']:
            stepPlot(self, 'day', d365, day_labels)
        if self.plots['by_month']:
            stepPlot(self, 'month', m24, mth_labels)
        if self.plots['by_season']:
            stepPlot(self, 'season', q24, ssn_labels)
        if self.plots['by_period']:
            stepPlot(self, 'period', s24, smp_labels)
        for key in list(ydata.keys()):
            for k in range(24):
                if self.plots['total']:
                    l24[key][k] = l24[key][k] / 365
                if self.plots['month']:
                    for m in range(12):
                        m24[key][m][k] = m24[key][m][k] / the_days[m]
                if self.plots['season']:
                    for q in range(len(seasons)):
                        q24[key][q][k] = q24[key][q][k] / the_qtrs[q]
                if self.plots['period']:
                    for s in range(len(periods)):
                        s24[key][s][k] = s24[key][s][k] / the_ssns[s]
        if self.plots['hour']:
            if self.plots['save_plot']:
                sp_vals = ['hour']
                sp_data = []
                sp_data.append(x[1:])
                sp_data[-1].append(len(x))
                sp_vals.append('period')
                sp_data.append([])
                for i in range(len(x)):
                    sp_data[-1].append(the_date(self.load_year, i))
            hdr = self.hdrs['hour'].replace('Power - ', '')
            fig = plt.figure(hdr + self.suffix)
            plt.grid(True)
            hx = fig.add_subplot(111)
            plt.title(self.hdrs['hour'] + self.suffix)
            maxy = 0
            storage = None
            if self.plots['cumulative']:
                cumulative = []
                for i in range(len(x)):
                    cumulative.append(0.)
            if self.plots['gross_load']:
                gross_load = []
                for i in range(len(x)):
                    gross_load.append(0.)
            if self.plots['show_pct']:
                load_sum = 0.
                gen_sum = 0.
            for key, value in iter(sorted(ydata.items())):
                if key == 'Generation':
                    continue
                if self.plots['show_pct']:
                    for i in range(len(x)):
                        if key[:4] == 'Load':
                            load_sum += value[i]
                        elif key == 'Storage':
                            pass
                        else:
                            gen_sum += value[i]
                            if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                load_sum += value[i]
                maxy = max(maxy, max(value))
                lw = self.other_width
                if self.plots['cumulative'] and key[:4] != 'Load' and key != 'Storage':
                    lw = 1.0
                    for i in range(len(x)):
                        cumulative[i] += value[i]
                if self.plots['gross_load'] and (key[:4] == 'Load' or
                      key == 'Existing Rooftop PV'):
                    for i in range(len(x)):
                        gross_load[i] += value[i]
                if self.plots['shortfall'] and key[:4] == 'Load':
                    load = value
                if self.plots['shortfall'] and key == 'Storage':
                    storage = value
                hx.plot(x, value, linewidth=lw, label=shrinkKey(key), color=self.colours[key],
                        linestyle=self.linestyle[key])
                if self.plots['save_plot']:
                    sp_vals.append(shrinkKey(key))
                    sp_data.append(value)
            if self.plots['cumulative']:
                hx.plot(x, cumulative, linewidth=self.other_width, label='Tot. Generation', color=self.colours['cumulative'])
                maxy = max(maxy, max(cumulative))
                if self.plots['save_plot']:
                    sp_vals.append('Tot. Generation')
                    sp_data.append(cumulative)
            if self.plots['gross_load'] and 'Existing Rooftop PV' in list(ydata.keys()):
                hx.plot(x, gross_load, linewidth=1.0, label='Gross Load', color=self.colours['gross_load'])
                maxy = max(maxy, max(gross_load))
                if self.plots['save_plot']:
                    sp_vals.append('Gross Load')
                    sp_data.append(gross_load)
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                rndup = 0
            if self.plots['shortfall'] and self.do_load:
                load2 = []
                if storage is None:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] - load[i])
                else:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] + storage[i] - load[i])
                hx.plot(x, load2, linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                plt.axhline(0, color='black')
                miny = min(load2)
                if rndup != 0 and miny < 0:
                    miny = -ceil(-miny / rndup) * rndup
                if self.plots['save_plot']:
                    sp_vals.append('Shortfall')
                    sp_data.append(load2)
            else:
                miny = 0
            if self.plots['save_plot']:
                titl = 'Hour'
                decpts = [3] * len(sp_vals)
                decpts[0] = decpts[1] = 0
                dialog = displaytable.Table(list(map(list, list(zip(*sp_data)))), title=titl, fields=sp_vals,
                                            save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, sp_data, sp_vals
            plt.ylim([miny, maxy])
            plt.xlim([0, len(x)])
            if (len(ydata) + pc) > 9:
                 # Shrink current axis by 5%
                box = hx.get_position()
                hx.set_position([box.x0, box.y0, box.width * 0.95, box.height])
                 # Put a legend to the right of the current axis
                hx.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop=lbl_font)
            else:
                hx.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=(len(ydata) + pc),
                          prop=lbl_font)
            plt.xticks(list(range(12, len(x), 168)))
            hx.set_xticklabels(day_labels, rotation='vertical')
            hx.set_xlabel('Month of the year')
            hx.set_ylabel('Power (MW)')
            if self.plots['show_pct']:
                self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                plt.title(self.hdrs['hour'] + self.suffix + self.gen_pct)
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            zp = ZoomPanX()
            f = zp.zoom_pan(hx, base_scale=1.2) # enable scrollable zoom
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
            del zp
        if self.plots['augment'] and self.do_load:
            hdr = self.hdrs['augment'].replace('Power - ', '')
            fig = plt.figure(hdr + self.suffix)
            plt.grid(True)
            hx = fig.add_subplot(111)
            plt.title(self.hdrs['augment'] + self.suffix)
            maxy = 0
            miny = 0
            storage = None
            cumulative = []
            for i in range(len(x)):
                cumulative.append(0.)
            if self.plots['gross_load']:
                gross_load = []
                for i in range(len(x)):
                    gross_load.append(0.)
            if self.plots['show_pct']:
                load_sum = 0.
                gen_sum = 0.
            for key, value in iter(sorted(ydata.items())):
                if key == 'Generation' or key == 'Excess': # might need to keep excess
                    continue
                if self.plots['show_pct']:
                    for i in range(len(x)):
                        if key[:4] == 'Load':
                            load_sum += value[i]
                        elif key == 'Storage':
                            pass
                        else:
                            gen_sum += value[i]
                            if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                load_sum += value[i]
                maxy = max(maxy, max(value))
                lw = self.other_width
                if key[:4] != 'Load' and key != 'Storage':
                    for i in range(len(x)):
                        cumulative[i] += value[i]
                if self.plots['gross_load'] and (key[:4] == 'Load' or
                      key == 'Existing Rooftop PV'):
                    for i in range(len(x)):
                        gross_load[i] += value[i]
                if key[:4] == 'Load':
                    load = value
                if key == 'Storage':
                    storage = value
            maxy = max(maxy, max(cumulative))
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                rndup = 0
            regen = cumulative[:]
            for r in range(len(regen)):
                if regen[r] > load[r]:
                    regen[r] = load[r]
            hx.fill_between(x, 0, regen, color=self.colours['cumulative']) #'#004949')
            if storage is not None:
                for r in range(len(storage)):
                    storage[r] += cumulative[r]
                for r in range(len(storage)):
                    if storage[r] > load[r]:
                        storage[r] = load[r]
                hx.fill_between(x, regen, storage, color=self.colours['wind']) #'#006DDB')
                hx.fill_between(x, storage, load, color=self.colours['shortfall']) #'#920000')
            else:
                hx.fill_between(x, load, regen, color=self.colours['shortfall']) #'#920000')
            hx.plot(x, cumulative, linewidth=self.other_width, label='RE', linestyle='--', color=self.colours['gross_load'])
            if self.plots['save_plot']:
                sp_vals = ['hour']
                sp_data = []
                sp_tots = ['']
                sp_pts = [0]
                sp_data.append(x[1:])
                sp_data[-1].append(len(x))
                sp_vals.append('period')
                sp_data.append([])
                sp_tots.append('')
                sp_pts.append(0)
                for i in range(len(x)):
                    sp_data[-1].append(the_date(self.load_year, i))
                sp_vals.append('load')
                sp_data.append(load)
                l = len(sp_data) - 1
                sp_tots.append(0.)
                sp_pts.append(4)
                for ld in load:
                    sp_tots[l] += ld
                sp_vals.append('renewable')
                sp_data.append(regen)
                r = len(sp_data) - 1
                sp_tots.append(0.)
                sp_pts.append(4)
                for re in regen:
                    sp_tots[-1] += re
                if storage is not None:
                    sp_vals.append('storage')
                    sp_data.append(storage)
                    s = len(sp_data) - 1
                    sp_tots.append(0.)
                    sp_pts.append(4)
                else:
                    s = 0
                sp_vals.append('re gen.')
                sp_data.append(cumulative)
                e = len(sp_data) - 1
                sp_tots.append(0.)
                sp_pts.append(4)
                titl = 'Augmented'
                dialog = displaytable.Table(list(map(list, list(zip(*sp_data)))), title=titl, fields=sp_vals,
                                            save_folder=self.scenarios, decpts=sp_pts)
                dialog.exec_()
                del dialog
                if s > 0:
                    for i in range(len(sp_data[s])):
                        sp_data[s][i] = sp_data[s][i] - sp_data[r][i]
                        sp_tots[s] += sp_data[s][i]
                sp_vals.append('excess')
                sp_vals[e] = 'augment'
                sp_data.append([])
                sp_tots.append(0.)
                sp_pts.append(4)
                for i in range(len(sp_data[r])):
                    sp_data[-1].append(sp_data[e][i] - sp_data[r][i])
                    sp_tots[-1] += sp_data[-1][i]
                if s > 0:
                    for i in range(len(sp_data[e])):
                        sp_data[e][i] = sp_data[l][i] - sp_data[r][i] - sp_data[s][i]
                        sp_tots[e] += sp_data[e][i]
                        sp_data[-1][i] -= sp_data[s][i]
                        sp_tots[-1] -= sp_data[s][i]
                else:
                    for i in range(len(sp_data[e])):
                        sp_data[e][i] = sp_data[l][i] - sp_data[r][i]
                        sp_tots[e] += sp_data[e][i]
                titl = 'augmented2'
                dialog = displaytable.Table(list(map(list, list(zip(*sp_data)))), title=titl, fields=sp_vals,
                                            save_folder=self.scenarios, decpts=sp_pts)
                dialog.exec_()
                fields = ['row', 'component', 'MWh', 'Load %']
                values = []
                sp_pts = [0, 0, 4, 1]
                for i in range(2, len(sp_vals)):
                    values.append([i - 1, sp_vals[i].title(), sp_tots[i], 0.])
                    values[-1][-1] = (sp_tots[i] * 100.) / sp_tots[l]
                titl = 'augmented3'
                dialog = displaytable.Table(values, fields=fields, title=titl, save_folder=self.scenarios, decpts=sp_pts)
                dialog.exec_()
                del dialog, sp_vals, sp_data, sp_tots
            plt.ylim([miny, maxy])
            plt.xlim([0, len(x)])
            plt.xticks(list(range(12, len(x), 168)))
            hx.set_xticklabels(day_labels, rotation='vertical')
            hx.set_xlabel('Month of the year')
            hx.set_ylabel('Power (MW)')
            zp = ZoomPanX()
            f = zp.zoom_pan(hx, base_scale=1.2) # enable scrollable zoom
            if self.plots['show_pct']:
                self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                plt.title(self.hdrs['hour'] + self.suffix + self.gen_pct)
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
            del zp
    #        shortstuff = []
    #        vals = ['load', 'renewable', 'storage', 'cumulative']
    #        for i in range(0, len(load)):
    #            if storage is None:
    #                shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i), [load[i],
    #                                  regen[i], 0., cumulative[i]], values=vals))
    #            else:
    #                shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i), [load[i],
    #                                  regen[i], storage[i], cumulative[i]], values=vals))
    #        vals.insert(0, 'period')
    #        vals.insert(0, 'hour')
    #        dialog = displaytable.Table(shortstuff, title='Augmented',
    #                                        save_folder=self.scenarios, fields=vals)
    #        dialog.exec_()
    #        del dialog
        if self.plots['duration']:
            hdr = self.hdrs['duration'].replace('Power - ', '')
            fig = plt.figure(hdr + self.suffix)
            plt.grid(True)
            dx = fig.add_subplot(111)
            plt.title(self.hdrs['duration'] + self.suffix)
            maxy = 0
            if self.plots['cumulative']:
                cumulative = []
                for i in range(len(x)):
                    cumulative.append(0.)
            if self.plots['show_pct']:
                load_sum = 0.
                gen_sum = 0.
            for key, value in iter(sorted(ydata.items())):
                if key == 'Generation':
                    continue
                if self.plots['show_pct']:
                    for i in range(len(x)):
                        if key[:4] == 'Load':
                            load_sum += value[i]
                        elif key == 'Storage':
                            pass
                        else:
                            gen_sum += value[i]
                            if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                load_sum += value[i]
                sortydata = sorted(value, reverse=True)
                lw = self.other_width
                if self.plots['cumulative'] and key[:4] != 'Load' and key != 'Storage':
                    lw = 1.0
                    for i in range(len(x)):
                        cumulative[i] += value[i]
                maxy = max(maxy, max(sortydata))
                dx.plot(x, sortydata, linewidth=lw, label=shrinkKey(key), color=self.colours[key],
                        linestyle=self.linestyle[key])
            if self.plots['cumulative']:
                sortydata = sorted(cumulative, reverse=True)
                dx.plot(x, sortydata, linewidth=self.other_width, label='Tot. Generation', color=self.colours['cumulative'])
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                pass
            plt.ylim([0, maxy])
            plt.xlim([0, len(x)])
            if (len(ydata) + pc) > 9:
                 # Shrink current axis by 10%
                box = dx.get_position()
                dx.set_position([box.x0, box.y0, box.width * 0.95, box.height])

                 # Put a legend to the right of the current axis
                dx.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop=lbl_font)
            else:
                dx.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=(len(ydata) + pc),
                          prop=lbl_font)
            tics = int(len(x) / (len(pct_labels) - 1))
            plt.xticks(list(range(0, len(x), tics)))
            dx.set_xticklabels(pct_labels)
            dx.set_xlabel('Percentage of Year')
            dx.set_ylabel('Power (MW)')
            if self.plots['show_pct']:
                self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                plt.title(self.hdrs['duration'] + self.suffix + self.gen_pct)
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
            if self.do_load:
                hdr = self.hdrs['duration'].replace('Power - ', '')
           #      fig = plt.figure(hdr + self.suffix)
                plt.figure(hdr + ' 2')
                plt.grid(True)
                plt.title(self.hdrs['duration'] + ' with renewable contribution')
                lx = plt.subplot(111)
                maxy = 0
                miny = 0
                load = []  # use for this and next graph
                rgen = []  # use for this and next graph
                rgendiff = []
                for i in range(len(self.x)):
                    rgen.append(0.)
                    rgendiff.append(0.)
                if self.plots['show_pct']:
                    load_sum = 0.
                    gen_sum = 0.
                for key, value in ydata.items():
                    if key == 'Generation':
                        continue
                    if self.plots['show_pct']:
                        for i in range(len(value)):
                            if key[:4] == 'Load':
                                load_sum += value[i]
                            elif key == 'Storage':
                                pass
                            else:
                                gen_sum += value[i]
                                if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                    load_sum += value[i]
                    if key[:4] == 'Load':
                        load = value
                    else:
                        for i in range(len(value)):
                            rgen[i] += value[i]
                for i in range(len(load)):
                    rgendiff[i] = load[i] - rgen[i]
                sortly1 = sorted(load, reverse=True)
                maxy = max(maxy, max(load))
                maxy = max(maxy, max(rgendiff))
                miny = min(miny, min(rgendiff))
                try:
                    rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                    maxy = ceil(maxy / rndup) * rndup
                    miny = -ceil(-miny / rndup) * rndup
                except:
                    pass
                if self.load_multiplier != 0:
                    load_key = 'Load ' + self.load_year
                else:
                    load_key = 'Load'
                lx.plot(x, sortly1, linewidth=self.other_width, label=load_key)
                sortly2 = sorted(rgendiff, reverse=True)
                lx.plot(x, sortly2, linewidth=self.other_width, label='Tot. Generation')
                lx.fill_between(x, sortly1, sortly2, facecolor=self.colours['cumulative'])
                plt.ylim([miny, maxy])
                plt.xlim([0, len(x)])
                lx.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=2, prop=lbl_font)
                tics = int(len(x) / (len(pct_labels) - 1))
                plt.xticks(list(range(0, len(x), tics)))
                lx.set_xticklabels(pct_labels)
                lx.set_xlabel('Percentage of Year')
                lx.set_ylabel('Power (MW)')
                lx.axhline(0, color='black')
                if self.plots['show_pct']:
                    self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                    plt.title(self.hdrs['duration'] + ' with renewable contribution' +
                              self.gen_pct)
                if self.plots['maximise']:
                    mng = plt.get_current_fig_manager()
                    if sys.platform == 'win32' or sys.platform == 'cygwin':
                        if plt.get_backend() == 'TkAgg':
                            mng.window.state('zoomed')
                        elif plt.get_backend() == 'Qt4Agg':
                            mng.window.showMaximized()
                    else:
                        mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if not self.plots['block']:
            plt.show(block=True)
        if (self.plots['shortfall_detail'] or self.plots['save_match']) and self.do_load:
            load = []
            rgen = []
            shortfall = [[], [], [], []]
            generation = []
            for i in range(len(self.x)):
                rgen.append(0.)
                shortfall[0].append(0.)
            for key, value in ydata.items():
                if key == 'Generation':
                    generation = value
                elif key[:4] == 'Load':
                    load = value
                else:
                    for i in range(len(value)):
                        rgen[i] += value[i]
            shortfall[0][0] = rgen[0] - load[0]
            for i in range(1, len(load)):
                shortfall[0][i] = shortfall[0][i - 1] + rgen[i] - load[i]
            d_short = [[], [0], [0, 0]]
            for i in range(0, len(load), 24):
                d_short[0].append(0.)
                for j in range(i, i + 24):
                    d_short[0][-1] += rgen[i] - load[i]
            if self.iterations > 0:
                for i in range(1, len(d_short[0])):
                    d_short[1].append((d_short[0][i - 1] + d_short[0][i]) / 2)
                for i in range(2, len(d_short[0])):
                    d_short[2].append((d_short[0][i - 2] + d_short[0][i - 1] + d_short[0][i]) / 3)
                d_short[1][0] = d_short[1][1]
                d_short[2][0] = d_short[2][1] = d_short[2][2]
                shortstuff = []
                vals = ['shortfall', 'iteration 1', 'iteration 2']
                for i in range(len(d_short[0])):
                    shortstuff.append(DailyData(i + 1, the_date(self.load_year, i * 24)[:10],
                                      [d_short[0][i], d_short[1][i], d_short[2][i]], values=vals))
                vals.insert(0, 'date')
                vals.insert(0, 'day')
                dialog = displaytable.Table(shortstuff, title='Daily Shortfall',
                         save_folder=self.scenarios, fields=vals)
                dialog.exec_()
                del dialog
                del shortstuff
                xs = []
                for i in range(len(d_short[0])):
                    xs.append(i + 1)
                plt.figure('daily shortfall')
                plt.grid(True)
                plt.title('Daily Shortfall')
                sdfx = plt.subplot(111)
                for i in range(self.iterations):
                    sdfx.step(xs, d_short[i], linewidth=self.other_width,
                              label=str(i + 1) + ' day average',
                              color=colours[i])
                plt.xticks(list(range(0, len(xs), 7)))
                tick_spot = []
                for i in range(0, len(xs), 7):
                    tick_spot.append(i + .5)
                sdfx.set_xticks(tick_spot)
                sdfx.set_xticklabels(day_labels, rotation='vertical')
                sdfx.set_xlabel('Day of the year')
                sdfx.set_ylabel('Power (MW)')
                plt.xlim([0, len(xs)])
                sdfx.legend(loc='best')
                for i in range(len(d_short)):
                    lin = min(d_short[i])
                    sdfx.axhline(lin, linestyle='--', color=colours[i])
                    lin = max(d_short[i])
                    sdfx.axhline(lin, linestyle='--', color=colours[i])
                lin = sum(d_short[0]) / len(d_short[0])
                sdfx.axhline(lin, linestyle='--', color='black')
                if self.plots['maximise']:
                    mng = plt.get_current_fig_manager()
                    if sys.platform == 'win32' or sys.platform == 'cygwin':
                        if plt.get_backend() == 'TkAgg':
                            mng.window.state('zoomed')
                        elif plt.get_backend() == 'Qt4Agg':
                            mng.window.showMaximized()
                    else:
                        mng.resize(*mng.window.maxsize())
                plt.show(block=True)
                h_storage = [-(shortfall[0][-1] / len(shortfall[0]))]  # average shortfall
                for s in range(1, self.iterations + 1):
                    for i in range(len(self.x)):
                        shortfall[s].append(0.)
                    ctr = 0
                    still_short = [0, 0]
                    if rgen[0] - load[0] + h_storage[-1] < 0:
                        still_short[0] += rgen[0] - load[0] + h_storage[-1]
                        ctr += 1
                    else:
                        still_short[1] += rgen[0] - load[0] + h_storage[-1]
                    shortfall[s][0] = rgen[0] - load[0] + h_storage[-1]
                    for i in range(1, len(load)):
                        shortfall[s][i] = shortfall[s][i - 1] + rgen[i] - load[i] + h_storage[-1]
                        if rgen[i] - load[i] + h_storage[-1] < 0:
                            still_short[0] += rgen[i] - load[i] + h_storage[-1]
                            ctr += 1
                        else:
                            still_short[1] += rgen[i] - load[i] + h_storage[-1]
    #                 h_storage.append(h_storage[-1] - still_short[0] / len(self.x))
                    h_storage.append(-(shortfall[0][-1] + still_short[0]) / len(self.x))
                dimen = log10(fabs(shortfall[0][-1]))
                unit = 'MW'
                if dimen > 11:
                    unit = 'PW'
                    div = 9
                elif dimen > 8:
                    unit = 'TW'
                    div = 6
                elif dimen > 5:
                    unit = 'GW'
                    div = 3
                else:
                    div = 0
                if div > 0:
                    for s in range(self.iterations + 1):
                        for i in range(len(shortfall[s])):
                            shortfall[s][i] = shortfall[s][i] / pow(10, div)
                plt.figure('cumulative shortfall')
                plt.grid(True)
                plt.title('Cumulative Shortfall')
                sfx = plt.subplot(111)
                sfx.plot(x, shortfall[0], linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                for s in range(1, self.iterations + 1):
                    if h_storage[s - 1] > 1:
                        amt = '{:0,.0f}'.format(h_storage[s - 1])
                    else:
                        amt = '{:0,.1f}'.format(h_storage[s - 1])
                    lbl = 'iteration %s - add %s MW to generation' % (s, amt )
                    sfx.plot(x, shortfall[s], linewidth=self.other_width, label=lbl, color=colours[s])
                plt.xticks(list(range(0, len(x), 168)))
                tick_spot = []
                for i in range(0, len(x), 168):
                    tick_spot.append(i + .5)
                box = sfx.get_position()
                sfx.set_position([box.x0, box.y0, box.width, box.height])
                sfx.set_xticks(tick_spot)
                sfx.set_xticklabels(day_labels, rotation='vertical')
                plt.xlim([0, len(x)])
                sfx.set_xlabel('Day of the year')
                sfx.set_ylabel('Power (' + unit + ')')
                sfx.legend(loc='best', prop=lbl_font)
                if self.plots['maximise']:
                    mng = plt.get_current_fig_manager()
                    if sys.platform == 'win32' or sys.platform == 'cygwin':
                        if plt.get_backend() == 'TkAgg':
                            mng.window.state('zoomed')
                        elif plt.get_backend() == 'Qt4Agg':
                            mng.window.showMaximized()
                    else:
                        mng.resize(*mng.window.maxsize())
                plt.show(block=True)
                for i in range(0, len(load)):
                    shortfall[0][i] = rgen[i] - load[i]
                for s in range(1, self.iterations + 1):
                    for i in range(0, len(load)):
                        shortfall[s][i] = rgen[i] - load[i] + h_storage[s - 1]
                plt.figure('shortfall')
                plt.grid(True)
                plt.title('Shortfall')
                sfx = plt.subplot(111)
                sfx.plot(x, shortfall[0], linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                for s in range(1, self.iterations + 1):
                    if h_storage[s - 1] > 1:
                        amt = '{:0,.0f}'.format(h_storage[s - 1])
                    else:
                        amt = '{:0,.1f}'.format(h_storage[s - 1])
                    lbl = 'iteration %s - add %s MW to generation' % (s, amt )
                    sfx.plot(x, shortfall[s], linewidth=self.other_width, label=lbl, color=colours[s])
                plt.axhline(0, color='black')
                plt.xticks(list(range(0, len(x), 168)))
                tick_spot = []
                for i in range(0, len(x), 168):
                    tick_spot.append(i + .5)
                box = sfx.get_position()
                sfx.set_position([box.x0, box.y0, box.width, box.height])
                sfx.set_xticks(tick_spot)
                sfx.set_xticklabels(day_labels, rotation='vertical')
                sfx.set_xlabel('Day of the year')
                sfx.set_ylabel('Power (MW)')
                plt.xlim([0, len(x)])
                sfx.legend(loc='best', prop=lbl_font)
                if self.plots['maximise']:
                    mng = plt.get_current_fig_manager()
                    if sys.platform == 'win32' or sys.platform == 'cygwin':
                        if plt.get_backend() == 'TkAgg':
                            mng.window.state('zoomed')
                        elif plt.get_backend() == 'Qt4Agg':
                            mng.window.showMaximized()
                    else:
                        mng.resize(*mng.window.maxsize())
                plt.show(block=True)
            else:
                for i in range(0, len(load)):
                    shortfall[0][i] = rgen[i] - load[i]
            shortstuff = []
            if self.plots['grid_losses']:
                vals = ['load', 'generation', 'transmitted', 'shortfall']
                short2 = [shortfall[0][0]]
                for i in range(1, len(self.x)):
                  #   short2.append(shortfall[0][i] - shortfall[0][i - 1])
                    short2.append(shortfall[0][i])
                for i in range(0, len(load)):
                    shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i), [load[i],
                                      generation[i], rgen[i], short2[i]], values=vals))
            else:
                vals = ['load', 'generation', 'shortfall']
                for i in range(0, len(load)):
                    shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i), [load[i],
                                      rgen[i], shortfall[0][i]], values=vals))
            vals.insert(0, 'period')
            vals.insert(0, 'hour')
            if self.plots['shortfall_detail'] and self.plots['save_plot']:
                dialog = displaytable.Table(shortstuff, title='Hourly Shortfall',
                                            save_folder=self.scenarios, fields=vals)
                dialog.exec_()
                del dialog
            if self.plots['save_match']:
                if self.pm_template:
                    saveMatch(self, shortstuff)
                else:
                    saveBalance(self, shortstuff)
            del shortstuff
        if self.plots['total']:
            maxy = 0
            if self.plots['cumulative']:
                cumulative = []
                for i in range(len(x24)):
                    cumulative.append(0.)
            if self.plots['gross_load']:
                gross_load = []
                for i in range(len(x24)):
                    gross_load.append(0.)
            if self.plots['save_plot']:
                sp_data = []
                sp_data.append(x24)
                sp_vals = ['hour']
            hdr = self.hdrs['total'].replace('Power - ', '')
            plt.figure(hdr + self.suffix)
            plt.grid(True)
            plt.title(self.hdrs['total'] + self.suffix)
            tx = plt.subplot(111)
            storage = None
            if self.plots['show_pct']:
                load_sum = 0.
                gen_sum = 0.
            for key in iter(sorted(l24.keys())):
                if key == 'Generation':
                    continue
                if self.plots['show_pct']:
                    for j in range(len(x24)):
                        if key[:4] == 'Load':
                            load_sum += l24[key][j]
                        elif key == 'Storage':
                            pass
                        else:
                            gen_sum += l24[key][j]
                            if self.plots['gross_load'] and key == 'Existing Rooftop PV':
                                load_sum += l24[key][j]
                maxy = max(maxy, max(l24[key]))
                lw = self.other_width
                if self.plots['cumulative'] and key[:4] != 'Load' and key != 'Storage':
                    lw = 1.0
                    for j in range(len(x24)):
                        cumulative[j] += l24[key][j]
                if self.plots['gross_load'] and (key[:4] == 'Load' or
                      key == 'Existing Rooftop PV'):
                    for j in range(len(x24)):
                        gross_load[j] += l24[key][j]
                if self.plots['shortfall'] and key[:4] == 'Load':
                    load = l24[key]
                if self.plots['shortfall'] and key == 'Storage':
                    storage = l24[key]
                tx.plot(x24, l24[key], linewidth=lw, label=shrinkKey(key), color=self.colours[key],
                        linestyle=self.linestyle[key])
                if self.plots['save_plot']:
                    sp_vals.append(key)
                    sp_data.append(l24[key])
            if self.plots['cumulative']:
                tx.plot(x24, cumulative, linewidth=self.other_width, label='Tot. Generation', color=self.colours['cumulative'])
                maxy = max(maxy, max(cumulative))
                if self.plots['save_plot']:
                    sp_vals.append('Tot. Generation')
                    sp_data.append(cumulative)
            if self.plots['gross_load'] and 'Existing Rooftop PV' in list(ydata.keys()):
                tx.plot(x24, gross_load, linewidth=1.0, label='Gross Load', color=self.colours['gross_load'])
                maxy = max(maxy, max(gross_load))
                if self.plots['save_plot']:
                    sp_vals.append('Gross Load')
                    sp_data.append(gross_load)
            try:
                rndup = pow(10, round(log10(maxy * 1.5) - 1)) / 2
                maxy = ceil(maxy / rndup) * rndup
            except:
                pass
            if self.plots['shortfall'] and self.do_load:
                load2 = []
                if storage is None:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] - l24[self.load_key][i])
                else:
                    for i in range(len(cumulative)):
                        load2.append(cumulative[i] + storage[i] - l24[self.load_key][i])
                tx.plot(x24, load2, linewidth=self.other_width, label='Shortfall', color=self.colours['shortfall'])
                plt.axhline(0, color='black')
                miny = min(load2)
                if rndup != 0 and miny < 0:
                    miny = -ceil(-miny / rndup) * rndup
                if self.plots['save_plot']:
                    sp_vals.append('Shortfall')
                    sp_data.append(load2)
            else:
                miny = 0
            if self.plots['save_plot']:
                titl = 'Total'
                decpts = [3] * len(sp_vals)
                decpts[0] = 0
                dialog = displaytable.Table(list(map(list, list(zip(*sp_data)))), title=titl, fields=sp_vals,
                                            save_folder=self.scenarios, decpts=decpts)
                dialog.exec_()
                del dialog, sp_data, sp_vals
            plt.ylim([miny, maxy])
            plt.xlim([1, 25])
            plt.xticks(list(range(0, 25, 4)))
          #   tx.legend(loc='lower left', numpoints = 2, prop=lbl_font)
            tx.set_xticklabels(labels)
            tx.set_xlabel('Hour of the Day')
            tx.set_ylabel('Power (MW)')
            if (len(ydata) + pc) > 9:
                 # Shrink current axis by 5%
                box = tx.get_position()
                tx.set_position([box.x0, box.y0, box.width * 0.95, box.height])
                 # Put a legend to the right of the current axis
                tx.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop=lbl_font)
            else:
                tx.legend(bbox_to_anchor=[0.5, -0.1], loc='center', ncol=(len(ydata) + pc),
                          prop=lbl_font)
            if self.plots['show_pct']:
                self.gen_pct = ' (%s%% of load)' % '{:0,.1f}'.format(gen_sum * 100. / load_sum)
                plt.title(self.hdrs['total'] + self.suffix + self.gen_pct)
            if self.plots['maximise']:
                mng = plt.get_current_fig_manager()
                if sys.platform == 'win32' or sys.platform == 'cygwin':
                    if plt.get_backend() == 'TkAgg':
                        mng.window.state('zoomed')
                    elif plt.get_backend() == 'Qt4Agg':
                        mng.window.showMaximized()
                else:
                    mng.resize(*mng.window.maxsize())
            if self.plots['block']:
                plt.show(block=True)
            else:
                plt.draw()
        if self.plots['month']:
            dayPlot(self, 'month', m24, mth_labels, mth_xlabels)
        if self.plots['season']:
            dayPlot(self, 'season', q24, ssn_labels, labels)
        if self.plots['period']:
            dayPlot(self, 'period', s24, smp_labels, labels)
        if not self.plots['block']:
            plt.show(block=True)

    def save_detail(self, data_file, techs, keys=None):
        if self.suffix != '':
            i = data_file.rfind('.')
            if i > 0:
                data_file = data_file[:i] + '_' + self.suffix + data_file[i:]
            else:
                data_file = data_file + '_' + self.suffix
        if data_file[-4:] == '.csv' or data_file[-4:] == '.xls' \
          or data_file[-5:] == '.xlsx':
            pass
        else:
            data_file += '.xls'
        data_file = QtWidgets.QFileDialog.getSaveFileName(None, 'Save power data file',
                    self.scenarios + data_file, 'Excel Files (*.xls*);;CSV Files (*.csv)')[0]
        if data_file == '':
            return
        if self.load_multiplier != 0:
            the_year = self.load_year
        else:
            the_year = self.base_year
        if data_file[-4:] == '.csv' or data_file[-4:] == '.xls' \
          or data_file[-5:] == '.xlsx':
            pass
        else:
            data_file += '.xls'
        if os.path.exists(data_file):
            if os.path.exists(data_file + '~'):
                os.remove(data_file + '~')
            os.rename(data_file, data_file + '~')
        if keys is None:
            keys = sorted(techs.keys())
        if data_file[-4:] == '.csv':
            tf = open(data_file, 'w')
            line = 'Hour,Period,'
            if self.load_multiplier != 0:
                the_year = self.load_year
            else:
                the_year = self.base_year
            max_outs = 0
            lines = []
            for i in range(8760):
                lines.append(str(i+1) + ',' + str(the_date(the_year, i)) + ',')
            for key in keys:
                if key[:4] == 'Load' and self.load_multiplier != 0:
                    line += 'Load ' + self.load_year + ','
                else:
                    line += key + ','
                for i in range(len(techs[key])):
                    lines[i] += str(round(techs[key][i], 3)) + ','
            tf.write(line + '\n')
            for i in range(len(lines)):
                tf.write(lines[i] + '\n')
            tf.close()
            del lines
        else:
            wb = xlwt.Workbook()
            ws = wb.add_sheet('Detail')
            ws.write(0, 0, 'Hour')
            ws.write(0, 1, 'Period')
            for i in range(len(self.x)):
                ws.write(i + 1, 0, i + 1)
                ws.write(i + 1, 1, the_date(the_year, i))
            if 16 * 275 > ws.col(1).width:
                ws.col(1).width = 16 * 275
            c = 2
            for key in keys:
                if key[:4] == 'Load' and self.load_multiplier != 0:
                    ws.write(0, c, 'Load ' + self.load_year)
                else:
                    ws.write(0, c, key)
                if len(key) * 275 > ws.col(c).width:
                    ws.col(c).width = len(key) * 275
                for r in range(len(techs[key])):
                    ws.write(r + 1, c, round(techs[key][r], 3))
                c += 1
            ws.set_panes_frozen(True)  # frozen headings instead of split panes
            ws.set_horz_split_pos(1)  # in general, freeze after last heading row
            ws.set_remove_splits(True)  # if user does unfreeze, dont leave a split there
            wb.save(data_file)
            del wb

#       __init__ for PowerModel
    def __init__(self, stations, year=None, status=None, visualise=None, loadonly=False, progress=None):
        self.something = visualise
        self.something.power_signal = self
        self.status = status
        self.stations = stations
        self.progress = progress
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.expert = False
        try:
            expert = config.get('Base', 'expert_mode')
            if expert in ['true', 'on', 'yes']:
                self.expert = True
        except:
            pass
        if year is None:
            try:
                self.base_year = config.get('Base', 'year')
            except:
                self.base_year = '2012'
        else:
            self.base_year = year
        parents = []
        try:
            parents = getParents(config.items('Parents'))
        except:
            pass
        try:
            scenario_prefix = config.get('Files', 'scenario_prefix')
        except:
            scenario_prefix = ''
        try:
            self.scenarios = config.get('Files', 'scenarios')
            if scenario_prefix != '' :
                self.scenarios += '/' + scenario_prefix
            for key, value in parents:
                self.scenarios = self.scenarios.replace(key, value)
            self.scenarios = self.scenarios.replace('$USER$', getUser())
            self.scenarios = self.scenarios.replace('$YEAR$', self.base_year)
            i = self.scenarios.rfind('/')
            self.scenarios = self.scenarios[:i + 1]
        except:
            self.scenarios = ''
        try:
            self.load_file = config.get('Files', 'load')
            for key, value in parents:
                self.load_file = self.load_file.replace(key, value)
            self.load_file = self.load_file.replace('$USER$', getUser())
            self.load_file = self.load_file.replace('$YEAR$', self.base_year)
        except:
            self.load_file = ''
        self.data_file = ''
        try:
            self.data_file = config.get('Files', 'data_file')
        except:
            try:
                self.data_file = config.get('Power', 'data_file')
            except:
                pass
        for key, value in parents:
           self.data_file = self.data_file.replace(key, value)
        self.data_file = self.data_file.replace('$USER$', getUser())
        self.data_file = self.data_file.replace('$YEAR$', self.base_year)
        try:
            helpfile = config.get('Files', 'help')
            for key, value in parents:
                helpfile = helpfile.replace(key, value)
            helpfile = helpfile.replace('$USER$', getUser())
            helpfile = helpfile.replace('$YEAR$', self.base_year)
        except:
            helpfile = ''
        if self.progress is None:
            self.show_progress = None
        else:
            progress_bar = True
            try:
                progress_bar = config.get('View', 'progress_bar')
                if progress_bar in ['false', 'no', 'off']:
                    self.show_progress = None
                else:
                    self.show_progress = True
                    try:
                        self.progress_bar = int(self.progress_bar)
                    except:
                        self.progress_bar = 0
            except:
                self.show_progress = True
                self.progress_bar = 0
#
#       choose what power data to collect (once only)
#
        self.plot_order = ['show_menu', 'actual', 'cumulative', 'by_station', 'adjust',
                           'show_load', 'shortfall', 'grid_losses', 'gross_load', 'save_plot', 'visualise',
                           'show_pct', 'maximise', 'block', 'by_day', 'by_month', 'by_season',
                           'by_period', 'hour', 'total', 'month', 'season', 'period',
                           'duration', 'augment', 'shortfall_detail', 'summary', 'save_data', 'save_detail',
                           'save_tech', 'save_match', 'financials']
        self.initials = ['actual', 'by_station', 'grid_losses', 'save_data', 'gross_load',
                         'summary', 'financials'] #, 'show_menu']
        self.hdrs = {'show_menu': 'Check / Uncheck all',
                'actual': 'Generation - use actual generation figures',
                'cumulative': 'Generation - total (cumulative)',
                'by_station': 'Generation - from chosen stations',
                'adjust': 'Generation - adjust generation',
                'show_load': 'Generation - show Load',
                'shortfall': 'Generation - show shortfall from Load',
                'grid_losses': 'Generation - reduce generation by grid losses',
                'gross_load': 'Add Existing Rooftop PV to Load (Gross Load)',
                'save_plot': 'Save plot data',
                'visualise': 'Visualise generation',
                'show_pct': 'Show generation as a percentage of load',
                'maximise': 'Maximise Plot windows',
                'block': 'Show plots one at a time',
                'by_day': 'Energy by day',
                'by_month': 'Energy by month',
                'by_season': 'Energy by season',
                'by_period': 'Energy by period',
                'hour': 'Power by hour',
                'total': 'Power - diurnal profile',
                'month': 'Power - diurnal profile by month',
                'season': 'Power - diurnal profile by season',
                'period': 'Power - diurnal profile by period',
                'duration': 'Power - Load duration',
                'augment': 'Power - augmented by hour',
                'shortfall_detail': 'Power - Shortfall analysis',
                'summary': 'Show Summary/Other Tables',
                'save_data': 'Save initial Hourly Data Output',
                'save_detail': 'Save Hourly Data Output by Station',
                'save_tech': 'Save Hourly Data Output by Technology',
                'save_match': 'Save Powermatch Inputs',
                'financials': 'Run Financial Models'}
        self.spacers = {'actual': 'Show in Plot',
                   'save_plot': 'Choose plots (all use a full year of data)',
                   'summary': 'Choose tables'}
        self.plots = {}
        for i in range(len(self.plot_order)):
            self.plots[self.plot_order[i]] = False
        self.load_year = self.base_year
        if loadonly:
            if self.load_file == '' or not os.path.exists(self.load_file):
                self.load_file = None
                return
            plot_order = ['show_menu', 'save_plot', 'maximise', 'block', 'by_day', 'by_month', 'by_season',
                           'by_period', 'hour', 'total', 'month', 'season', 'period']
            spacers = {'maximise': 'Choose plots (all use a full year of data)'}
            self.plots['show_load'] == True
            what_plots = whatPlots(self.plots, plot_order, self.hdrs, spacers, 0., self.base_year, self.load_year,
                                   0, [0, 0], [0, 0], [0, 0], [], initial=False, helpfile=helpfile)
            what_plots.exec_()
            return
        self.technologies = ''
        self.load_growth = 0.
        self.storage = [0., 0.]
        self.recharge = [0., 1.]
        self.discharge = [0., 1.]
        plot_opts = []
        try:
            plot_opts = config.items('Power')
        except:
            pass
        for key, value in plot_opts:
            if key == 'save_balance': # old name for save_match
                key = 'save_match'
            if key in self.plots:
                if value.lower() in ['true', 'yes', 'on']:
                    self.plots[key] = True
            elif key == 'load_growth':
                if value[-1] == '%':
                    self.load_growth = float(value[:-1]) / 100.
                else:
                    self.load_growth = float(value)
            elif key == 'storage':
                if ',' in value:
                    bits = value.split(',')
                    self.storage = [float(bits[0].strip()), float(bits[1].strip())]
                else:
                    self.storage = [float(value), 0.]
            elif key == 'technologies':
                self.technologies = value
            elif key == 'shortfall_iterations':
                self.iterations = int(value)
        try:
            storage = config.get('Storage', 'storage')
            if ',' in storage:
                bits = storage.split(',')
                self.storage = [float(bits[0].strip()), float(bits[1].strip())]
            else:
                self.storage = [float(storage), 0.]
        except:
            pass
        try:
            self.show_menu = self.plots['show_menu']
        except:
            self.show_menu = True
        try:
            self.discharge[0] = float(config.get('Storage', 'discharge_max'))
            self.discharge[1] = float(config.get('Storage', 'discharge_eff'))
            if self.discharge[1] < 0.5:
                self.discharge[1] = 1 - self.discharge[1]
            self.recharge[0] = float(config.get('Storage', 'recharge_max'))
            self.recharge[1] = float(config.get('Storage', 'recharge_eff'))
            if self.recharge[1] < 0.5:
                self.recharge[1] = 1 - self.recharge[1]
        except:
            pass
        if __name__ == '__main__':
            self.show_menu = True
            self.plots['save_data'] = True
        if not self.plots['save_data']:
            self.plot_order.remove('save_data')
        if len(self.stations) == 1:
            self.plot_order.remove('cumulative')
            self.plot_order.remove('by_station')
            self.plot_order.remove('gross_load')
      # check if we can find a load file
        if self.load_file == '' or not os.path.exists(self.load_file):
            self.can_do_load = False
            self.plot_order.remove('augment')
            self.plot_order.remove('duration')
            self.plot_order.remove('show_load')
            self.plot_order.remove('show_pct')
            self.plot_order.remove('shortfall')
            self.plot_order.remove('shortfall_detail')
        else:
            self.can_do_load = True
        if self.show_menu:
            if __name__ == '__main__':
                app = QtWidgets.QApplication(sys.argv)
            what_plots = whatPlots(self.plots, self.plot_order, self.hdrs, self.spacers,
                                   self.load_growth, self.base_year, self.load_year,
                                   self.iterations, self.storage, self.discharge,
                                   self.recharge, initial=True, helpfile=helpfile)
            what_plots.exec_()
            self.plots, self.load_growth, self.load_year, self.load_multiplier, self.iterations, \
              self.storage, self.discharge, self.recharge = what_plots.getValues()
            if self.plots is None:
                self.something.power_signal = None
                return
        self.selected = None
        if self.plots['by_station']:
            self.selected = []
            if len(stations) == 1:
                self.selected.append(stations[0].name)
            else:
                selected = whatStations(stations, self.plots['gross_load'],
                                        self.plots['actual'])
                selected.exec_()
                self.selected = selected.getValues()
                if self.selected is None:
                    return
#
#       collect the data (once only)
#
        self.stn_outs = []
        self.model = SuperPower(stations, self.plots, False, year=self.base_year,
                                selected=self.selected, status=status, progress=self.progress)
        self.model.getPower()
        if len(self.model.power_summary) == 0:
            return
        self.power_summary = self.model.power_summary
        self.ly, self.x = self.model.getLy()
        if self.plots['save_data'] or self.plots['financials'] or self.plots['save_detail']:
            self.stn_outs, self.stn_tech, self.stn_size, self.stn_pows, self.stn_grid, \
              self.stn_path = self.model.getStnOuts()
        elif self.plots['save_tech'] or self.plots['save_match']:
            self.stn_outs, self.stn_tech = self.model.getStnTech()
        elif self.plots['visualise']:
            self.stn_outs, self.stn_pows = self.model.getStnPows()
        self.suffix = ''
        if len(self.stations) == 1:
            self.suffix = ' - ' + self.stations[0].name
        elif len(self.stn_outs) == 1:
            self.suffix = ' - ' + self.stn_outs[0]
        elif self.plots['by_station']:
            if len(self.ly) == 1:
                self.suffix = ' - ' + list(self.ly.keys())[0]
            else:
                self.suffix = ' - Chosen Stations'
        if self.plots['save_data']:
            if self.data_file == '':
                data_file = 'Power_Table_%s.xls' % \
                            QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                            'yyyy-MM-dd_hhmm')
            else:
                data_file = self.data_file
            stnsh = {}
            for i in range(len(self.stn_outs)):
                stnsh[self.stn_outs[i]] = self.stn_pows[i][:]
            self.save_detail(data_file, stnsh)
            del stnsh
        if self.plots['summary']:
            fields = ['name', 'technology', 'capacity', 'cf', 'generation']
            sumfields = ['capacity', 'generation']
            if getattr(self.power_summary[0], 'transmitted') != None:
                fields.append('transmitted')
                sumfields.append('transmitted')
            dialog = displaytable.Table(self.power_summary, sumfields=sumfields,
                     units='capacity=MW generation=MWh transmitted=MWh', sumby='technology',
                     fields=fields, save_folder=self.scenarios)
            dialog.exec_()
            del dialog
        if self.plots['financials']:
            do_financials = True
        else:
            do_financials = False
        if self.plots['save_data'] or self.plots['summary']:
            show_summ = True
        else:
            show_summ = False
        do_plots = True
#
#       loop around processing plots
#
        if do_plots:
            if plt.get_backend() != 'TkAgg':
                plt.switch_backend('TkAgg')
            self.gen_pct = None
            self.load_data = None
            if self.plots['save_detail']:
                pass
            else:
                self.initials.append('save_detail')
                if not self.plots['save_tech']:
                    self.initials.append('save_tech')
                if not self.plots['visualise']:
                    self.initials.append('visualise')
            self.load_key = ''
            self.adjustby = None
            while True:
                if self.plots['visualise'] and self.something is not None:
                    vis2 = Visualise(self.stn_outs, self.stn_pows, self.something, year=self.base_year)
                    vis2.setWindowModality(Qt.Qt.WindowModal)
                    vis2.setWindowFlags(vis2.windowFlags() |
                                 Qt.Qt.WindowSystemMenuHint |
                                 Qt.Qt.WindowMinMaxButtonsHint)
                    vis2.exec_()
                wrkly = {}
                summs = {}
                if self.load_key != '':
                    try:
                        del wrkly[self.load_key]
                    except:
                        pass
                    self.load_key = ''
                if (self.plots['show_load'] or self.plots['save_match'] or self.plots['shortfall'] \
                    or self.plots['shortfall_detail']) and self.can_do_load:
                    if self.load_data is None:
                        tf = open(self.load_file, 'r')
                        lines = tf.readlines()
                        tf.close()
                        self.load_data = []
                        bit = lines[0].rstrip().split(',')
                        if len(bit) > 0: # multiple columns
                            for b in range(len(bit)):
                                if bit[b][:4].lower() == 'load':
                                    if bit[b].lower().find('kwh') > 0: # kWh not MWh
                                        for i in range(1, len(lines)):
                                            bit = lines[i].rstrip().split(',')
                                            self.load_data.append(float(bit[b]) * 0.001)
                                    else:
                                        for i in range(1, len(lines)):
                                            bit = lines[i].rstrip().split(',')
                                            self.load_data.append(float(bit[b]))
                        else:
                            for i in range(1, len(lines)):
                                self.load_data.append(float(lines[i].rstrip()))
                    if self.load_multiplier != 0:
                        key = 'Load ' + self.load_year
                    else:
                        key = 'Load'  # lines[0].rstrip()
                    self.load_key = key
                    wrkly[key] = []
                    if self.load_multiplier != 0:
                        for i in range(len(self.load_data)):
                            wrkly[key].append(self.load_data[i] * (1 + self.load_multiplier))
                    else:
                        wrkly[key] = self.load_data[:]
                else:
                    self.plots['show_pct'] = False
                if self.plots['adjust']:
                    if self.load_key == '':
                        if self.adjustby is None:
                            adjust = Adjustments(list(self.ly.keys()))
                        else:
                            adjust = Adjustments(self.adjustby)
                    else:
                        if self.adjustby is None:
                            adjust = Adjustments(list(self.ly.keys()), self.load_key, wrkly[self.load_key], self.ly,
                                                 self.load_year)
                        else:
                            adjust = Adjustments(self.adjustby, self.load_key, wrkly[self.load_key], self.ly, self.load_year)
                    adjust.exec_()
                    self.adjustby = adjust.getValues()
                else:
                    self.adjustby = None
                for key in self.ly:
                    if self.adjustby is None:
                        wrkly[key] = self.ly[key][:]
                    else:
                        wrkly[key] = []
                        if key == 'Generation':
                            for i in range(len(self.ly[key])):
                                wrkly[key].append(self.ly[key][i])
                        else:
                            for i in range(len(self.ly[key])):
                                wrkly[key].append(self.ly[key][i] * self.adjustby[key])
                if self.plots['shortfall'] or self.plots['shortfall_detail'] or self.plots['save_match']:
                    self.plots['show_load'] = True
                    self.plots['cumulative'] = True
                try:
                    del wrkly['Storage']
                except:
                    pass
                if self.load_data is None:
                    self.do_load = False
                else:
                    self.do_load = True
                if self.plots['show_load']:
                    total_gen = []
                    for i in range(len(self.x)):
                        total_gen.append(0.)
                    for key, value in wrkly.items():
                        if key == 'Generation':
                            continue
                        if key == 'Storage' or key == 'Excess':
                            continue
                        elif key[:4] == 'Load':
                            pass
                        else:
                            for i in range(len(value)):
                                total_gen[i] += value[i]
                    if self.storage[0] > 0:
                        wrkly['Storage'] = []
                        wrkly['Excess'] = []
                        for i in range(len(self.x)):
                            wrkly['Storage'].append(0.)
                            wrkly['Excess'].append(0.)
                        storage_cap = self.storage[0] * 1000.
                        if self.storage[1] > self.storage[0]:
                            storage_carry = self.storage[0] * 1000.
                        else:
                            storage_carry = self.storage[1] * 1000.
                        storage_bal = []
                        storage_losses = []
                        for i in range(len(self.x)):
                            gap = gape = total_gen[i] - wrkly[self.load_key][i]
                            storage_loss = 0.
                            if gap >= 0:  # excess generation
                                if self.recharge[0] > 0 and gap > self.recharge[0]:
                                    gap = self.recharge[0]
                                if storage_carry >= storage_cap:
                                    wrkly['Excess'][i] = gape
                                else:
                                    if storage_carry + gap > storage_cap:
                                        gap = (storage_cap - storage_carry) * (1 / self.recharge[1])
                                    storage_loss = gap - gap * self.recharge[1]
                                    storage_carry += gap - storage_loss
                                    if gape - gap > 0:
                                        wrkly['Excess'][i] = gape - gap
                                    if storage_carry > storage_cap:
                                        storage_carry = storage_cap
                            else:
                                if self.discharge[0] > 0 and -gap > self.discharge[0]:
                                    gap = -self.discharge[0]
                                if storage_carry > -gap / self.discharge[1]:  # extra storage
                                    wrkly['Storage'][i] = -gap
                                    storage_loss = gap * self.discharge[1] - gap
                                    storage_carry += gap - storage_loss
                                else:  # not enough storage
                                    if self.discharge[0] > 0 and storage_carry > self.discharge[0]:
                                        storage_carry = self.discharge[0]
                                    wrkly['Storage'][i] = storage_carry * (1 / (2 - self.discharge[1]))
                                    storage_loss = storage_carry - wrkly['Storage'][i]
                                    storage_carry = 0 # ???? bug ???
                            storage_bal.append(storage_carry)
                            storage_losses.append(storage_loss)
                        if self.plots['shortfall_detail']:
                            shortstuff = []
                            for i in range(len(self.x)):
                                shortfall = total_gen[i] + wrkly['Storage'][i] - wrkly[self.load_key][i]
                                if shortfall > 0:
                                    shortfall = 0
                                shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i),
                                                  [wrkly[self.load_key][i], total_gen[i],
                                                  wrkly['Storage'][i], storage_losses[i],
                                                  storage_bal[i], shortfall, wrkly['Excess'][i]],
                                                  values=['load', 'generation', 'storage_used',
                                                          'storage_loss', 'storage_balance',
                                                          'shortfall', 'excess']))
                            dialog = displaytable.Table(shortstuff, title='Storage',
                                                        save_folder=self.scenarios,
                                                        fields=['hour', 'period', 'load', 'generation',
                                                                'storage_used', 'storage_loss',
                                                                'storage_balance', 'shortfall', 'excess'])
                            dialog.exec_()
                            del dialog
                            del shortstuff
                        if show_summ:
                            summs['Shortfall'] = ['', '', 0., 0]
                            summs['Excess'] = ['', '', 0., 0]
                            for i in range(len(self.x)):
                                if total_gen[i] > wrkly[self.load_key][i]:
                                    summs['Excess'][2] += total_gen[i] - wrkly[self.load_key][i]
                                else:
                                    summs['Shortfall'][2] += total_gen[i]  - wrkly[self.load_key][i]
                            summs['Shortfall'][2] = round(summs['Shortfall'][2], 1)
                            summs['Excess'][2] = round(summs['Excess'][2], 1)
                    elif show_summ or self.plots['shortfall_detail']:
                        if self.plots['shortfall_detail']:
                            shortstuff = []
                            for i in range(len(self.x)):
                                if total_gen[i] > wrkly[self.load_key][i]:
                                    excess = total_gen[i] - wrkly[self.load_key][i]
                                    shortfall = 0
                                else:
                                    shortfall = total_gen[i]  - wrkly[self.load_key][i]
                                    excess = 0
                                shortstuff.append(ColumnData(i + 1, the_date(self.load_year, i),
                                                  [wrkly[self.load_key][i], total_gen[i],
                                                   shortfall, excess],
                                                  values=['load', 'generation',
                                                          'shortfall', 'excess']))
                            dialog = displaytable.Table(shortstuff, title='Hourly Shortfall',
                                                        save_folder=self.scenarios,
                                                        fields=['hour', 'period', 'load', 'generation',
                                                                'shortfall', 'excess'])
                            dialog.exec_()
                            del dialog
                            del shortstuff
                        else:
                            summs['Shortfall'] = ['', '', 0., 0]
                            summs['Excess'] = ['', '', 0., 0]
                            for i in range(len(self.x)):
                                if total_gen[i] > wrkly[self.load_key][i]:
                                    summs['Excess'][2] += total_gen[i] - wrkly[self.load_key][i]
                                else:
                                    summs['Shortfall'][2] += total_gen[i] - wrkly[self.load_key][i]
                            summs['Shortfall'][2] = round(summs['Shortfall'][2], 1)
                            summs['Excess'][2] = round(summs['Excess'][2], 1)
                if show_summ and self.adjustby is not None:
                    keys = []
                    for key in wrkly:
                        keys.append(key)
                        gen = 0.
                        for i in range(len(wrkly[key])):
                            gen += wrkly[key][i]
                        if key[:4] == 'Load':
                            incr = 1 + self.load_multiplier
                        else:
                            try:
                                incr = self.adjustby[key]
                            except:
                                incr = ''
                        try:
                            summs[key] = [0., round(incr, 2), round(gen, 1), 0]
                            if key[:4] == 'Load':
                                summs[key][0] = ''
                        except:
                            summs[key] = ['', '', round(gen, 1), 0]
                    keys.sort()
                    xtra = ['Generation', 'Load', 'Gen. - Load', 'Storage Capacity', 'Storage', 'Shortfall', 'Excess']
                    o = 0
                    gen = 0.
                    if self.storage[0] > 0:
                        summs['Storage Capacity'] = [self.storage[0] * 1000., '', '', 0]
                    for i in range(len(keys)):
                        if keys[i][:4] == 'Load':
                            xtra[1] = keys[i]
                        elif keys[i] in xtra:
                            continue
                        else:
                            o += 1
                            summs[keys[i]][3] = o
                            gen += summs[keys[i]][2]
                    if xtra[0] not in list(summs.keys()):
                        summs[xtra[0]] = ['', '', gen, 0]
                    if xtra[1] in list(summs.keys()):
                        summs[xtra[2]] = ['', '', round(gen - summs[xtra[1]][2], 1), 0]
                    for i in range(len(xtra)):
                        if xtra[i] in list(summs.keys()):
                            o += 1
                            summs[xtra[i]][3] = o
                    try:
                        summs['Storage Used'] = summs.pop('Storage')
                    except:
                        pass
                    try:
                        summs['Excess Gen.'] = summs.pop('Excess')
                    except:
                        pass
                    for it in self.power_summary:
                        if self.plots['by_station']:
                            try:
                                summs[it.name][0] = it.capacity
                            except:
                                pass
                        else:
                            try:
                                summs[it.technology][0] += it.capacity
                            except:
                                pass
                    for key, value in summs.items():
                        try:
                            value[0] = round(value[0], 2)
                        except:
                            pass
                    dialog = displaytable.Table(summs, title='Generation Summary',
                                                save_folder=self.scenarios,
                                                fields=['component', 'capacity', 'multiplier', 'generation', 'row'],
                                                units='generation=MWh', sortby='row')
                    dialog.exec_()
                    del dialog
                if self.plots['save_detail'] or self.plots['save_tech']:
                    dos = []
                    if self.plots['save_detail']:
                        dos.append('')
                    if self.plots['save_tech']:
                        dos.append('Technology_')
                    for l in range(len(dos)):
                        if self.data_file == '':
                            if year is None:
                                data_file = 'Power_Detail_%s%s.xls' % ( dos[l] ,
                                QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                                'yyyy-MM-dd_hhmm'))
                            else:
                                data_file = 'Power_Detail_%s%s_%s.xls' % ( dos[l] , str(year),
                                QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                                'yyyy-MM-dd_hhmm'))
                        else:
                             data_file = self.data_file
                        keys = []
                        keys2 = []
                        if dos[l] != '':
                            techs = {}
                            for key, value in iter(wrkly.items()):
                                try:
                                    i = self.stn_outs.index(key)
                                    if self.stn_tech[i] in list(techs.keys()):
                                        for j in range(len(value)):
                                            techs[self.stn_tech[i]][j] += value[j]
                                    else:
                                        techs[self.stn_tech[i]] = value[:]
                                        keys.append(self.stn_tech[i])
                                except:
                                    techs[key] = value[:]
                                    keys2.append(key)
                            keys.sort()
                            keys2.extend(keys) # put Load first
                            self.save_detail(data_file, techs, keys=keys2)
                            del techs
                        else:
                            for key in list(wrkly.keys()):
                                try:
                                    i = self.stn_outs.index(key)
                                    keys.append(self.stn_outs[i])
                                except:
                                    keys2.append(key)
                            keys.sort()
                            keys2.extend(keys) # put Load first
                            self.save_detail(data_file, wrkly, keys=keys2)
                self.showGraphs(wrkly, self.x)
                if __name__ == '__main__':
                    self.show_menu = True
                    self.plots['save_data'] = True
                if self.show_menu:
                    what_plots = whatPlots(self.plots, self.plot_order, self.hdrs, self.spacers,
                                 self.load_growth, self.base_year, self.load_year, self.iterations,
                                 self.storage, self.discharge, self.recharge, self.initials, helpfile=helpfile)
                    what_plots.exec_()
                    self.plots, self.load_growth, self.load_year, self.load_multiplier, \
                        self.iterations, self.storage, self.discharge, self.recharge = what_plots.getValues()
                    if self.plots is None:
                        break
                else:
                    break
#
#       loop around doing financials
#
         # run the financials model
        if do_financials:
            self.financial_parms = None
            while True:
                self.financials = FinancialModel(self.stn_outs, self.stn_tech, self.stn_size,
                                  self.stn_pows, self.stn_grid, self.stn_path, year=self.base_year,
                                  parms=self.financial_parms, status=self.status)
                if self.financials.stations is None:
                    break
                self.financial_parms = self.financials.getParms()
                fin_fields = ['name', 'technology', 'capacity', 'generation', 'cf',
                              'capital_cost', 'lcoe_real', 'lcoe_nominal', 'npv']
                fin_sumfields = ['capacity', 'generation', 'capital_cost', 'npv']
                fin_units = 'capacity=MW generation=MWh capital_cost=$ lcoe_real=c/kWh' + \
                            ' lcoe_nominal=c/kWh npv=$'
                tot_capital = 0.
                tot_capacity = 0.
                tot_generation = 0.
                tot_lcoe_real = [0., 0.]
                tot_lcoe_nom = [0., 0.]
                for stn in self.financials.stations:
                    tot_capital += stn.capital_cost
                    tot_capacity += stn.capacity
                    tot_generation += stn.generation
                for stn in self.financials.stations:
                    tot_lcoe_real[0] += stn.lcoe_real * (stn.generation / tot_generation)
                    tot_lcoe_nom[0] += stn.lcoe_nominal * (stn.generation / tot_generation)
                    tot_lcoe_real[1] += stn.lcoe_real * (stn.capacity / tot_capacity)
                    tot_lcoe_nom[1] += stn.lcoe_nominal * (stn.capacity / tot_capacity)
                    if stn.grid_cost > 0:
                        i = fin_fields.index('capital_cost')
                        fin_fields.insert(i + 1, 'grid_cost')
                        fin_sumfields.append('grid_cost')
                        fin_units += ' grid_cost=$'
                        break
                tot_fields = [['cf', tot_generation / tot_capacity / 8760],
                              ['lcoe_real', tot_lcoe_real[0]],
                              ['lcoe_nominal', tot_lcoe_nom[0]]]
                dialog = displaytable.Table(self.financials.stations, fields=fin_fields,
                         sumfields=fin_sumfields, units=fin_units, sumby='technology',
                         save_folder=self.scenarios, title='Financials', totfields=tot_fields)
                dialog.exec_()
                del dialog
        self.something.power_signal = None

    def getValues(self):
        try:
            return self.power_summary
        except:
            return None

    def getPct(self):
        return self.gen_pct

    @QtCore.pyqtSlot()
    def exit(self):
        self.something.power_signal = None
        return #exit() def getUser():
    if sys.platform == 'win32' or sys.platform == 'cygwin':   # windows
        return os.environ.get("USERNAME")

    elif sys.platform == 'darwin':   # osx64
        return os.environ.get("USERNAME")
    elif sys.platform == 'linux' or sys.platform == 'linux2':   # linux
        return pwd.getpwuid(os.geteuid()).pw_name
    else:
        return os.environ.get("USERNAME") def techClean(tech, full=False):
    cleantech = tech.replace('_', ' ').title()
    cleantech = cleantech.replace('Bm', 'BM')
    cleantech = cleantech.replace('Ccgt', 'CCGT')
    cleantech = cleantech.replace('Ccg', 'CCG')
    cleantech = cleantech.replace('Cst', 'CST')
    cleantech = cleantech.replace('Lng', 'LNG')
    cleantech = cleantech.replace('Ocgt', 'OCGT')
    cleantech = cleantech.replace('Ocg', 'OCG')
    cleantech = cleantech.replace('Phs', 'PHS')
    cleantech = cleantech.replace('Pv', 'PV')
    if full:
        alll = [['Cf', 'CF'], ['hi ', 'HI '], ['Lcoe', 'LCOE'], ['Mw', 'MW'],
                ['ni ', 'NI '], ['Npv', 'NPV'], ['Re', 'RE'], ['Tco2E', 'tCO2e']]
        for each in alll:
            cleantech = cleantech.replace(each[0], each[1])
    return cleantech class Station:
    def __init__(self, name, technology, lat, lon, capacity, turbine, rotor, no_turbines, area, scenario, generation=None,
                 power_file=None, grid_line=None, grid_len=None, grid_path_len=None, direction=None, tilt=None, storage_hours=None):
        self.name = name
        self.technology = technology
        self.lat = lat
        self.lon = lon
        self.capacity = capacity
        self.turbine = turbine
        self.rotor = rotor
        self.no_turbines = no_turbines
        self.area = area
        self.scenario = scenario
        self.generation = generation
        self.power_file = power_file
        self.grid_line = grid_line
        self.grid_len = grid_len
        self.grid_path_len = grid_path_len
        self.direction = direction
        self.storage_hours = storage_hours
        if tilt is not None:
            self.tilt = tilt class Stations:
    def get_config(self):
        config = configparser.RawConfigParser()
        if __name__ == '__main__':
            for i in range(1, len(sys.argv)):
                if sys.argv[i][-4:] == '.ini':
                    config_file = sys.argv[i]
                    break
        else:
            if len(sys.argv) > 1:
                config_file = sys.argv[1]
            else:
                config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        try:
            self.base_year = config.get('Base', 'year')
        except:
            self.base_year = '2012'
        parents = []
        try:
            parents = getParents(config.items('Parents'))
        except:
            pass
        try:
            self.sam_file = config.get('Files', 'sam_turbines')
            for key, value in parents:
                self.sam_file = self.sam_file.replace(key, value)
            self.sam_file = self.sam_file.replace('$USER$', getUser())
            self.sam_file = self.sam_file.replace('$YEAR$', self.base_year)
        except:
            self.sam_file = ''
        try:
            self.pow_dir = config.get('Files', 'pow_files')
            for key, value in parents:
                self.pow_dir = self.pow_dir.replace(key, value)
            self.pow_dir = self.pow_dir.replace('$USER$', getUser())
            self.pow_dir = self.pow_dir.replace('$YEAR$', self.base_year)
        except:
            self.pow_dir = ''
        self.fac_files = []
        try:
            fac_file = config.get('Files', 'grid_stations')
            for key, value in parents:
                fac_file = fac_file.replace(key, value)
            fac_file = fac_file.replace('$USER$', getUser())
            fac_file = fac_file.replace('$YEAR$', self.base_year)
            self.fac_files.append(fac_file)
        except:
            pass
        if self.stations2:
            try:
                fac_file = config.get('Files', 'grid_stations2')
                for key, value in parents:
                    fac_file = fac_file.replace(key, value)
                fac_file = fac_file.replace('$USER$', getUser())
                fac_file = fac_file.replace('$YEAR$', self.base_year)
                self.fac_files.append(fac_file)
            except:
                pass
        self.ignore_deleted = True
        try:
            if config.get('Grid', 'ignore_deleted_existing').lower() in ['false', 'off', 'no']:
                self.ignore_deleted = False
        except:
            pass
        self.technologies = ['']
        self.areas = {}
        try:
            technologies = config.get('Power', 'technologies')
            for item in technologies.split():
                itm = techClean(item)
                self.technologies.append(itm)
                try:
                    self.areas[itm] = float(config.get(itm, 'area'))
                except:
                    self.areas[itm] = 0.
        except:
            pass
        try:
            technologies = config.get('Power', 'fossil_technologies')
            technologies = technologies.split()
            for item in technologies:
                itm = techClean(item)
                try:
                    self.areas[itm] = float(config.get(itm, 'area'))
                except:
                    self.areas[itm] = 0.
        except:
            pass
        try:
            mapc = config.get('Map', 'map_choice')
        except:
            mapc = ''
        upper_left = [0., 0.]
        lower_right = [-90., 180.]
        try:
             upper_left = config.get('Map', 'upper_left' + mapc).split(',')
             upper_left[0] = float(upper_left[0].strip())
             upper_left[1] = float(upper_left[1].strip())
             lower_right = config.get('Map', 'lower_right' + mapc).split(',')
             lower_right[0] = float(lower_right[0].strip())
             lower_right[1] = float(lower_right[1].strip())
        except:
             try:
                 lower_left = config.get('Map', 'lower_left' + mapc).split(',')
                 upper_right = config.get('Map', 'upper_right' + mapc).split(',')
                 upper_left[0] = float(upper_right[0].strip())
                 upper_left[1] = float(lower_left[1].strip())
                 lower_right[0] = float(lower_left[0].strip())
                 lower_right[1] = float(upper_right[1].strip())
             except:
                 pass
        self.map_polygon = [upper_left, [upper_left[0], lower_right[1]], lower_right,
           [lower_right[0], upper_left[1]], upper_left]

    def haversine(self, lat1, lon1, lat2, lon2):
        """
        Calculate the great circle distance between two points
        on the earth (specified in decimal degrees)
        """
     # convert decimal degrees to radians
        lon1, lat1, lon2, lat2 = list(map(radians, [lon1, lat1, lon2, lat2]))

     # haversine formula
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
        c = 2 * asin(sqrt(a))

     # 6367 km is the radius of the Earth
        km = 6367 * c
        return km

    def __init__(self, code=False, fossil=False, existing=True, stations2=True):
        self.stations2 = stations2
        self.get_config()
        try:
            self.stations in locals()
        except:
            self.stations = []
        if not existing:
            return
        if not os.path.exists(self.sam_file):
            return
        sam = open(self.sam_file)
        sam_turbines = csv.DictReader(sam)
        for fac_file in self.fac_files:
            if os.path.exists(fac_file):
                if fac_file[-4:] == '.csv':
                    facile = open(fac_file)
                    facilities = csv.DictReader(facile)
                    for facility in facilities:
                        if self.ignore_deleted and facility['Balancing Status'] == 'Deleted':
                            continue
                        if facility['Longitude'] != '':
                            if not within_map(float(facility['Latitude']),
                              float(facility['Longitude']), self.map_polygon):
                                continue
                            if 'Facility Code' in facilities.fieldnames:   # IMO format
                                bit = facility['Facility Code'].split('_')
                                rotor = 0.
                                turbine = ''
                                no_turbines = 0
                                if bit[-1][:2] == 'WW' or bit[-1][:2] == 'WF':
                                    tech = 'Wind'
                                    turbine = facility['Turbine']
                                    if turbine[:7] == 'Enercon':
                                        bit = turbine[9:].split(' _')
                                        if len(bit) == 1:
                                            rotor = bit[0].split('_')[0]
                                        else:
                                            bit = bit[0].split('_')
                                            if len(bit) == 1:
                                                rotor = bit[0]
                                            else:
                                                if bit[1][-1] == 'm':
                                                    rotor = bit[1][:-1]
                                                else:
                                                    rotor = bit[0]
                                    else:
                                        turb = turbine.split(';')
                                        if len(turb) > 1:
                                            turbine = turb[1]
                                        else:
                                            turbine = turb[0]
                                        sam.seek(0)
                                        for turb in sam_turbines:
                                            if turb['Name'] == turbine:
                                                rotor = turb['Rotor Diameter']
                                                break
                                        else: # try and find .pow file
                                            pow_file = self.pow_dir + '/' + turbine + '.pow'
                                            if os.path.exists(pow_file):
                                                tf = open(pow_file, 'r')
                                                lines = tf.readlines()
                                                tf.close()
                                                rotor = float(lines[1].strip('" \t\n\r'))
                                                del lines
                                    no_turbines = int(facility['No. turbines'])
                                    try:
                                        rotor = float(rotor)
                                    except:
                                        pass
                                    area = self.areas[tech] * float(no_turbines) * pow((rotor * .001), 2)
                                elif bit[0] == 'MERSOLAR':
                                    tech = 'Tracking PV'
                                    area = self.areas[tech] * float(facility['Maximum Capacity (MW)'])
                                elif bit[-1][:2] == 'PV':
                                    tech = 'Fixed PV'
                                    area = self.areas[tech] * float(facility['Maximum Capacity (MW)'])
                                elif bit[-1] == 'PLANT' and bit[-2] == 'BIOMASS':
                                    tech = 'Biomass'
                                    area = self.areas[tech] * float(facility['Maximum Capacity (MW)'])
                                elif facility['Participant Code'] in ['CTE', 'LNDFLLGP', 'PERTHNRGY', 'WGRES']:
                                    tech = 'Biomass'
                                    area = self.areas[tech] * float(facility['Maximum Capacity (MW)'])
                                else:
                                    tech = 'Fossil '
                                    if 'Fossil' in facilities.fieldnames:
                                        tech += facility['Fossil']
                                    else:
                                        if bit[-1][:2] == 'GT' or bit[-1][0] == 'U':
                                            tech += 'OCGT'
                                        elif bit[-1][:2] == 'CC':
                                            tech += 'CCGT'
                                        elif bit[-1][:3] == 'COG':
                                            tech += 'Cogen'
                                        elif bit[0] == 'TESLA' or bit[-1] == 'WGP':
                                            tech += 'Distillate'
                                        elif bit[-2] == 'WGP':
                                            tech += 'Mixed'
                                        elif bit[-1][0] == 'G' and (bit[-1][1] >= '1' and bit[-1][1] <= '9'):
                                            tech += 'Coal'
                                        else:
                                            tech += 'Mixed'
                                           #  tech += 'Distillate'
                                    try:
                                        area = self.areas[tech] * float(facility['Maximum Capacity (MW)'])
                                    except:
                                        area = 0
                                if code:
                                    nice_name = facility['Facility Code']
                                else:
                                    nice_name = facility['Facility Name']
                                    if nice_name == '':
                                        name_split = facility['Facility Code'].split('_')
                                        if len(name_split) > 1:
                                            nice_name = ''
                                            for i in range(len(name_split) - 1):
                                                nice_name += name_split[i].title() + '_'
                                            nice_name += name_split[-1]
                                        else:
                                            nice_name = facility['Facility Code']
                                stn = self.Get_Station(nice_name)
                                if stn is None:   # new station?
                                    self.stations.append(Station(nice_name, tech,
                                        float(facility['Latitude']), float(facility['Longitude']),
                                        float(facility['Maximum Capacity (MW)']), turbine, rotor, no_turbines, area, 'Existing'))
                                    if tech == 'Fixed PV':
                                        try:
                                            if facility['Tilt'] != '':
                                                self.stations[-1].tilt = float(facility['Tilt'])
                                        except:
                                            pass
                                else:   # additional generator in existing station
                                    if stn.technology != tech:
                                        if stn.technology[:6] == 'Fossil' and tech[:6] == 'Fossil':
                                            stn.technology = 'Fossil Mixed'
                                    stn.capacity = stn.capacity + float(facility['Maximum Capacity (MW)'])
                                    stn.area += area
                                    stn.no_turbines = stn.no_turbines + no_turbines
                            else:   # SIREN format
                                try:
                                    turbs = int(facility['No. turbines'])
                                except:
                                    turbs = 0
                                self.stations.append(Station(facility['Station Name'],
                                             facility['Technology'],
                                             float(facility['Latitude']),
                                             float(facility['Longitude']),
                                             float(facility['Maximum Capacity (MW)']),
                                             facility['Turbine'],
                                             0.,
                                             turbs,
                                             float(facility['Area']),
                                             'Existing'))
                                if 'Wind' in self.stations[-1].technology:
                                    if self.stations[-1].rotor == 0 or self.stations[-1].rotor == '':
                                        rotor = 0
                                        if self.stations[-1].turbine[:7] == 'Enercon':
                                            bit = self.stations[-1].turbine[9:].split(' _')
                                            if len(bit) == 1:
                                                rotor = bit[0].split('_')[0]
                                            else:
                                                bit = bit[0].split('_')
                                                if len(bit) == 1:
                                                    rotor = bit[0]
                                                else:
                                                    if bit[1][-1] == 'm':
                                                        rotor = bit[1][:-1]
                                                    else:
                                                        rotor = bit[0]
                                        else:
                                            turb = self.stations[-1].turbine.split(';')
                                            if len(turb) > 1:
                                                sam.seek(0)
                                                turbine = turb[1]
                                                for turb in sam_turbines:
                                                    if turb['Name'] == turbine:
                                                        rotor = turb['Rotor Diameter']
                                    try:
                                        self.stations[-1].rotor = float(rotor)
                                    except:
                                        pass
                                if self.stations[-1].area == 0 or self.stations[-1].area == '':
                                    if 'Wind' in self.stations[-1].technology:
                                        self.stations[-1].area = self.areas[self.stations[-1].technology] * \
                                                                 float(self.stations[-1].no_turbines) * \
                                                                 pow((self.stations[-1].rotor * .001), 2)
                                    else:
                                        self.stations[-1].area = self.areas[self.stations[-1].technology] * \
                                                                 float(self.stations[-1].capacity)
                                try:
                                    if facility['Power File'] != '':
                                        self.stations[-1].power_file = facility['Power File']
                                except:
                                    pass
                                try:
                                    if facility['Grid Line'] != '':
                                        self.stations[-1].grid_line = facility['Grid Line']
                                except:
                                    pass
                                if 'PV' in self.stations[-1].technology:
                                    try:
                                        if facility['Direction'] != '':
                                            self.stations[-1].direction = facility['Direction']
                                    except:
                                        pass
                                    try:
                                        if facility['Tilt'] != '':
                                            self.stations[-1].tilt = float(facility['Tilt'])
                                    except:
                                        pass
                                if self.stations[-1].technology in ['CST', 'Solar Thermal']:
                                    try:
                                        if facility['Storage Hours'] != '':
                                            self.stations[-1].storage_hours = float(facility['Storage Hours'])
                                    except:
                                        pass
                    facile.close()
                else:   # assume excel and in our format
                    var = {}
                    workbook = xlrd.open_workbook(fac_file)
                    worksheet = workbook.sheet_by_index(0)
                    num_rows = worksheet.nrows - 1
                    num_cols = worksheet.ncols - 1
                    if worksheet.cell_value(0, 0) == 'Description:' or worksheet.cell_value(0, 0) == 'Comment:':
                        curr_row = 1
                        self.description = worksheet.cell_value(0, 1)
                    else:
                        curr_row = 0
                        self.description = ''
#                   get column names
                    curr_col = -1
                    while curr_col < num_cols:
                        curr_col += 1
                        var[worksheet.cell_value(curr_row, curr_col)] = curr_col
                    while curr_row < num_rows:
                        curr_row += 1
                        if not within_map(worksheet.cell_value(curr_row, var['Latitude']),
                          worksheet.cell_value(curr_row, var['Longitude']), self.map_polygon):
                            continue
                        self.stations.append(Station(str(worksheet.cell_value(curr_row, var['Station Name'])),
                                             str(worksheet.cell_value(curr_row, var['Technology'])),
                                             worksheet.cell_value(curr_row, var['Latitude']),
                                             worksheet.cell_value(curr_row, var['Longitude']),
                                             worksheet.cell_value(curr_row, var['Maximum Capacity (MW)']),
                                             str(worksheet.cell_value(curr_row, var['Turbine'])),
                                             worksheet.cell_value(curr_row, var['Rotor Diam']),
                                             worksheet.cell_value(curr_row, var['No. turbines']),
                                             worksheet.cell_value(curr_row, var['Area']),
                                             'Existing'))
                        if 'Wind' in self.stations[-1].technology:
                            if self.stations[-1].rotor == 0 or self.stations[-1].rotor == '':
                                rotor = 0
                                if self.stations[-1].turbine[:7] == 'Enercon':
                                    bit = self.stations[-1].turbine[9:].split(' _')
                                    if len(bit) == 1:
                                        rotor = bit[0].split('_')[0]
                                    else:
                                        bit = bit[0].split('_')
                                        if len(bit) == 1:
                                            rotor = bit[0]
                                        else:
                                            if bit[1][-1] == 'm':
                                                rotor = bit[1][:-1]
                                            else:
                                                rotor = bit[0]
                                else:
                                    turb = self.stations[-1].turbine.split(';')
                                    if len(turb) > 1:
                                        sam.seek(0)
                                        turbine = turb[1]
                                        for turb in sam_turbines:
                                            if turb['Name'] == turbine:
                                                rotor = turb['Rotor Diameter']
                                try:
                                    self.stations[-1].rotor = float(rotor)
                                except:
                                    pass
                        try:
                            if self.stations[-1].area == 0 or self.stations[-1].area == '':
                                if 'Wind' in self.stations[-1].technology:
                                    self.stations[-1].area = self.areas[self.stations[-1].technology] * \
                                                             float(self.stations[-1].no_turbines) * \
                                                             pow((self.stations[-1].rotor * .001), 2)
                                else:
                                    self.stations[-1].area = self.areas[self.stations[-1].technology] * \
                                                             float(self.stations[-1].capacity)
                        except:
                            self.stations[-1].area = 0.
                        try:
                            power_file = worksheet.cell_value(curr_row, var['Power File'])
                            if power_file != '':
                                self.stations[-1].power_file = power_file
                        except:
                            pass
                        try:
                            grid_line = worksheet.cell_value(curr_row, var['Grid Line'])
                            if grid_line != '':
                                self.stations[-1].grid_line = grid_line
                        except:
                            pass
                        if 'PV' in self.stations[-1].technology:
                            try:
                                direction = worksheet.cell_value(curr_row, var['Direction'])
                                if direction != '':
                                    self.stations[-1].direction = direction
                            except:
                                pass
                            try:
                                tilt = worksheet.cell_value(curr_row, var['Tilt'])
                                if tilt != '':
                                    self.stations[-1].tilt = tilt
                            except:
                                pass
                        if self.stations[-1].technology in ['CST', 'Solar Thermal']:
                            try:
                                storage_hours = worksheet.cell_value(curr_row, var['Storage Hours'])
                                if storage_hours != '':
                                    self.stations[-1].storage_hours = storage_hours
                            except:
                                pass
        sam.close()

    def Nearest(self, lat, lon, distance=False, fossil=False, ignore=None):
        hdr = ''
        distnce = 999999
        for station in self.stations:
            if station.technology[:6] == 'Fossil' and not fossil:
                continue
            dist = self.haversine(lat, lon, station.lat, station.lon)
            if dist < distnce:
                if ignore is not None and ignore == station.name:
                    continue
                hdr = station.name
                distnce = dist
        for station in self.stations:
            if station.name == hdr:
                if distance:
                    return station, distnce
                else:
                    return station
        return None

    def Stn_Location(self, name):
        for station in self.stations:
            if station.name == name:
                return str(station.lat) + ' ' + str(station.lon)
        return ''

    def Stn_Turbine(self, name):
        for station in self.stations:
            if station.name == name:
                return station.turbine
        return ''

    def Get_Station(self, name):
        for station in self.stations:
            if station.name == name:
                return station
        return None

    def Description(self):
        return self.description class WAScene(QtWidgets.QGraphicsScene):

    def get_config(self):
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        try:
            self.base_year = config.get('Base', 'year')
        except:
            self.base_year = '2012'
        self.existing = True
        try:
            existing = config.get('Base', 'existing')
            if existing.lower() in ['false', 'no', 'off']:
                self.existing = False
        except:
            pass
        try:
            self.model_name = config.get('Base', 'name')
        except:
            self.model_name = ''
        parents = []
        try:
            parents = getParents(config.items('Parents'))
        except:
            pass
        try:
            self.map = config.get('Map', 'map_choice')
        except:
            self.map = ''
        try:
            self.map_file = config.get('Files', 'map' + self.map)
            for key, value in parents:
                self.map_file = self.map_file.replace(key, value)
            self.map_file = self.map_file.replace('$USER$', getUser())
            self.map_file = self.map_file.replace('$YEAR$', self.base_year)
        except:
            try:
                self.map_file = config.get('Map', 'map' + self.map)
                for key, value in parents:
                    self.map_file = self.map_file.replace(key, value)
                self.map_file = self.map_file.replace('$USER$', getUser())
                self.map_file = self.map_file.replace('$YEAR$', self.base_year)
            except:
                self.map_file = ''
        try:
            self.projection = config.get('Map', 'projection' + self.map)
        except:
            try:
                self.projection = config.get('Map', 'projection')
            except:
                self.projection = 'EPSG:3857'
        self.map_upper_left = [0., 0.]
        self.map_lower_right = [-90., 180.]
        try:
             upper_left = config.get('Map', 'upper_left' + self.map).split(',')
             self.map_upper_left[0] = float(upper_left[0].strip())
             self.map_upper_left[1] = float(upper_left[1].strip())
             lower_right = config.get('Map', 'lower_right' + self.map).split(',')
             self.map_lower_right[0] = float(lower_right[0].strip())
             self.map_lower_right[1] = float(lower_right[1].strip())
        except:
             try:
                 lower_left = config.get('Map', 'lower_left' + self.map).split(',')
                 upper_right = config.get('Map', 'upper_right' + self.map).split(',')
                 self.map_upper_left[0] = float(upper_right[0].strip())
                 self.map_upper_left[1] = float(lower_left[1].strip())
                 self.map_lower_right[0] = float(lower_left[0].strip())
                 self.map_lower_right[1] = float(upper_right[1].strip())
             except:
                 pass
        self.map_polygon = [[self.map_upper_left[0], self.map_upper_left[1]],
                            [self.map_upper_left[0], self.map_lower_right[1]],
                            [self.map_lower_right[0], self.map_lower_right[1]],
                            [self.map_lower_right[0], self.map_upper_left[1]],
                            [self.map_upper_left[0], self.map_upper_left[1]]]
        self.scale = False
        try:
            scale = config.get('Map', 'scale' + self.map)
        except:
            scale = config.get('Map', 'scale')
        if scale.lower() in ['true', 'yes', 'on']:
            self.scale = True
        try:
            scenario_prefix = config.get('Files', 'scenario_prefix')
        except:
            scenario_prefix = ''
        try:
            self.scenarios = config.get('Files', 'scenarios')
            if scenario_prefix != '' :
                self.scenarios += '/' + scenario_prefix
            for key, value in parents:
                self.scenarios = self.scenarios.replace(key, value)
            self.scenarios = self.scenarios.replace('$USER$', getUser())
            self.scenarios = self.scenarios.replace('$YEAR$', self.base_year)
            i = self.scenarios.rfind('/')
            self.scenarios = self.scenarios[:i + 1]
        except:
            self.scenarios = ''
        try:
            self.scenario = config.get('Files', 'scenario')
            for key, value in parents:
                self.scenario = self.scenario.replace(key, value)
            self.scenario = self.scenario.replace('$USER$', getUser())
            self.scenario = self.scenario.replace('$YEAR$', self.base_year)
        except:
            self.scenario = ''
        try:
            self.resource_grid = config.get('Files', 'resource_grid')
            for key, value in parents:
                self.resource_grid = self.resource_grid.replace(key, value)
            self.resource_grid = self.resource_grid.replace('$USER$', getUser())
        except:
            self.resource_grid = ''
        self.colors = {}
        self.colors['background'] = 'darkBlue'
        self.colors['border'] = ''
        self.colors['grid_boundary'] = 'blue'
        self.colors['grid_trace'] = 'white'
        self.colors['ruler'] = 'white'
        self.colors['station'] = '#00FF00'
        self.colors['station_name'] = 'white'
        self.colors['town'] = 'red'
        self.colors['town_name'] = 'lightGray'
        technologies = config.get('Power', 'technologies')
        technologies = technologies.split()
        try:
            colours = config.items('Colors')
            for item, colour in colours:
                if item in technologies or (item[:6] == 'fossil' and item != 'fossil_name'):
                    itm = techClean(item)
                    self.colors[itm] = colour
                else:
                    self.colors[item] = colour
        except:
            pass
        self.areas = {}
        try:
            for item in technologies:
                itm = techClean(item)
                try:
                    self.areas[itm] = float(config.get(itm, 'area'))
                except:
                    self.areas[itm] = 0.
        except:
            pass
        try:
            technologies = config.get('Power', 'fossil_technologies')
            technologies = technologies.split()
            for item in technologies:
                itm = techClean(item)
                try:
                    self.areas[itm] = float(config.get(itm, 'area'))
                except:
                    self.areas[itm] = 0.
        except:
            pass
        if self.map != '':
            try:
                colours = config.items('Colors' + self.map)
                for item, colour in colours:
                    if item in technologies or (item[:6] == 'fossil' and item != 'fossil_name'):
                        itm = techClean(item)
                        self.colors[itm] = colour
                    else:
                        self.colors[item] = colour
            except:
                pass
        self.show_generation = False
        self.show_capacity = False
        try:
            show_capacity = config.get('View', 'capacity')
            if show_capacity.lower() in ['true', 'yes', 'on']:
                self.show_capacity = True
        except:
            pass
        self.show_capacity_fill = False
        self.capacity_opacity = 1.
        try:
            show_capacity_fill = config.get('View', 'capacity_fill')
            if show_capacity_fill.lower() in ['true', 'yes', 'on']:
                self.show_capacity_fill = True
            else:
                try:
                    self.capacity_opacity = float(show_capacity_fill)
                    self.show_capacity_fill = True
                    if self.capacity_opacity < 0. or self.capacity_opacity > 1.:
                        self.capacity_opacity = 1.
                except:
                    self.colors['border'] = ''
        except:
            pass
        try:
            capacity_area = config.get('View', 'capacity_area')
            self.capacity_area = float(capacity_area)
        except:
            self.capacity_area = 10.
        self.show_fossil = False
        try:
            show_fossil = config.get('View', 'fossil')
            if show_fossil.lower() in ['true', 'yes', 'on']:
                self.show_fossil = True
        except:
            pass
        self.show_station_name = True
        try:
            show_station_name = config.get('View', 'station_name')
            if show_station_name.lower() in ['false', 'no', 'off']:
                self.show_station_name = False
        except:
            pass
        self.show_legend = False
        self.show_ruler = False
        try:
            show_ruler = config.get('View', 'show_ruler')
            if show_ruler.lower() in ['true', 'yes', 'on']:
                self.show_ruler = True
        except:
            pass
        self.show_coord = False
        self.ruler = 100.
        self.ruler_ticks = 10.
        try:
            ruler = config.get('View', 'ruler')
            rule = ruler.split(',')
            self.ruler = float(rule[0])
            if len(rule) > 1:
                self.ruler_ticks = float(rule[1].strip())
        except:
            pass
        self.show_towns = True
        try:
            show_towns = config.get('View', 'show_towns')
            if show_towns.lower() in ['false', 'no', 'off']:
                self.show_towns = False
        except:
            pass
        self.center_on_click = False
        try:
            center_on_click = config.get('View', 'center_on_click')
            if center_on_click.lower() in ['true', 'yes', 'on']:
                self.center_on_click = True
        except:
            pass
        self.new_grid = False
        try:
            new_grid = config.get('View', 'new_grid')
            if new_grid.lower() in ['true', 'yes', 'on']:
                self.new_grid = True
        except:
            try:
                new_grid = config.get('Grid', 'new_grid')
                if new_grid.lower() in ['true', 'yes', 'on']:
                   self.new_grid = True
            except:
                pass
            pass
        self.existing_grid = True
        try:
            existing_grid = config.get('View', 'existing_grid')
            if existing_grid.lower() in ['false', 'no', 'off']:
                self.existing_grid = False
        except:
            try:
                existing_grid = config.get('Grid', 'existing_grid')
                if existing_grid.lower() in ['false', 'no', 'off']:
                   self.existing_grid = False
            except:
                pass
            pass
        try:
            self.existing_grid2 = True
        except:
            self.existing_grid2 = False
        self.trace_grid = True
        try:
            trace_grid = config.get('View', 'trace_grid')
            if trace_grid.lower() in ['false', 'no', 'off']:
                self.trace_grid = False
            #     self.existing_grid = False
        except:
            try:
                trace_grid = config.get('Grid', 'trace_grid')
                if trace_grid.lower() in ['false', 'no', 'off']:
                   self.trace_grid = False
                #    self.existing_grid = False
            except:
                pass
            pass
        self.cost_existing = False
        try:
            cost_existing = config.get('Grid', 'cost_existing')
            if cost_existing.lower() in ['true', 'yes', 'on']:
                self.cost_existing = True
        except:
            pass
        self.trace_existing = False
        try:
            trace_existing = config.get('View', 'trace_existing')
            if trace_existing.lower() in ['true', 'yes', 'on']:
                self.trace_existing = True
        except:
            try:
                trace_existing = config.get('Grid', 'trace_existing')
                if trace_existing.lower() in ['true', 'yes', 'on']:
                   self.trace_existing = True
            except:
                pass
        self.hide_map = False
        try:
            hide_map = config.get('View', 'hide_map')
            if hide_map.lower() in ['true', 'yes', 'on']:
                self.hide_map = True
        except:
            pass
        try:
            self.txt_ratio = float(config.get('View', 'txt_ratio')) / 10.
        except:
            self.txt_ratio = 0.01
        self.load_centre = None
        try:
            load_centre = config.get('Grid', 'load_centre')
            load_centre = load_centre.replace(' ', '')
            load_centre = load_centre.replace('(', '')
            load_centre = load_centre.replace('))', '')
            load_centre = load_centre.replace('),', ',')
            load_centre = load_centre.replace(')', '')
            load_centre = load_centre.split(',')
            try:
                float(load_centre[0])
                self.load_centre = [['1', float(load_centre[0]), float(load_centre[1])]]
                for j in range(2, len(load_centre), 2):
                    self.load_centre.append([str(j), float(load_centre[j]), float(load_centre[j + 1])])
            except:
                try:
                    self.load_centre = [[load_centre[0], float(load_centre[1]), float(load_centre[2])]]
                    for j in range(3, len(load_centre), 3):
                        self.load_centre.append([load_centre[j], float(load_centre[j + 1]),
                            float(load_centre[j + 2])])
                except:
                    pass
        except:
            pass
        self.station_square = False
        try:
            square = config.get('View', 'station_shape')
            if square[0].lower() == 's':
                self.station_square = True
        except:
            pass
        self.station_opacity = 1.
        try:
            self.station_opacity = float(config.get('View', 'station_opacity'))
            if self.station_opacity < 0. or self.station_opacity > 1.:
                self.station_opacity = 1.
        except:
            pass
        self.dispatchable = None
        self.line_loss = 0.
       #  self.subs_cost=0.
      #   self.subs_loss=0.
        try:
            itm = config.get('Grid', 'dispatchable')
            self.dispatchable = techClean(itm)
            line_loss = config.get('Grid', 'line_loss')
            if line_loss[-1] == '%':
                self.line_loss = float(line_loss[:-1]) / 100000.
            else:
                self.line_loss = float(line_loss) / 1000.
       #      line_cost = config.get('Grid', 'substation_cost')
        #     if line_cost[-1] == 'K':
         #        self.subs_cost = float(line_cost[:-1]) * pow(10, 3)
          #   elif line_cost[-1] == 'M':
           #      self.subs_cost = float(line_cost[:-1]) * pow(10, 6)
            # else:
             #    self.subs_cost = float(line_cost)
        #     line_loss = config.get('Grid', 'substation_loss')
        #     if line_loss[-1] == '%':
         #        self.subs_loss = float(line_loss[:-1]) / 100.
         #    else:
         #        self.subs_loss = float(line_loss)
        except:
            pass
        self.line_width = 0
        try:
            line_width = config.get('View', 'line_width')
            try:
                self.line_width = int(line_width)
            except:
                self.line_width = float(line_width)
        except:
            pass
        self.cst_tshours = 0
        try:
            self.cst_tshours = float(config.get('CST', 'tshours'))
        except:
            pass
        self.st_tshours = 0
        try:
            self.st_tshours = float(config.get('Solar Thermal', 'tshours'))
        except:
            pass

    def destinationxy(self, lon1, lat1, bearing, distance):
        """
        Given a start point, initial bearing, and distance, calculate
        the destination point and final bearing travelling along a
        (shortest distance) great circle arc
        """
        radius = 6367.   # km is the radius of the Earth
     # convert decimal degrees to radians
        ln1, lt1, baring = list(map(radians, [lon1, lat1, bearing]))
     # "reverse" haversine formula
        lat2 = asin(sin(lt1) * cos(distance / radius) +
                                cos(lt1) * sin(distance / radius) * cos(baring))
        lon2 = ln1 + atan2(sin(baring) * sin(distance / radius) * cos(lt1),
                                            cos(distance / radius) - sin(lt1) * sin(lat2))
        return degrees(lon2), degrees(lat2)

    def __init__(self):
        QtWidgets.QGraphicsScene.__init__(self)
        self.exitLoop = False
        self.loopMax = 0
        self.get_config()
        self.last_locn = None
        self.setBackgroundBrush(QtGui.QColor(self.colors['background']))
        if os.path.exists(self.map_file):
            war = QtGui.QImageReader(self.map_file)
            wa = war.read()
            pixMap = QtGui.QPixmap.fromImage(wa)
            if self.hide_map:
                pixMap.fill()
        else:
            ratio = abs(self.map_upper_left[1] - self.map_lower_right[1]) / \
                     abs(self.map_upper_left[0] - self.map_lower_right[0])
            pixMap = QtGui.QPixmap(200 * ratio, 200)
            if self.map != '':
                painter = QtGui.QPainter(pixMap)
                brush = QtGui.QBrush(QtGui.QColor('white'))
                painter.fillRect(QtCore.QRectF(0, 0, 200 * ratio, 200), brush)
                painter.setPen(QtGui.QColor('lightgray'))
                painter.drawText(QtCore.QRectF(0, 0, 200 * ratio, 200), QtCore.Qt.AlignCenter,
                                 'Map not found.')
                painter.end()
        self.addPixmap(pixMap)
        w = self.width()
        h = self.height()
        if isinstance(self.line_width, float):
            if self.line_width < 1:
                self.line_width = w * self.line_width
        self.upper_left = [0, 0, self.map_upper_left[1], self.map_upper_left[0]]
        self.lower_right = [w, h, self.map_lower_right[1], self.map_lower_right[0]]
        self.setSceneRect(-w * 0.05, -h * 0.05, w * 1.1, h * 1.1)
        self._positions = {}
        self._setupCoordTransform()
        self._gridGroup = QtWidgets.QGraphicsItemGroup()
        self._gridGroup2 = QtWidgets.QGraphicsItemGroup()
        self._setupGrid()
        self.addItem(self._gridGroup)
        if not self.existing_grid:
            self._gridGroup.setVisible(False)
        if self.existing_grid2:
            self.addItem(self._gridGroup2)
        self._coordGroup = QtWidgets.QGraphicsItemGroup()
        self._setupCoordGrid()
        self.addItem(self._coordGroup)
        if not self.show_coord:
            self._coordGroup.setVisible(False)
        self._townGroup = QtWidgets.QGraphicsItemGroup()
        self._setupTowns()
        self.addItem(self._townGroup)
        if not self.show_towns:
            self._townGroup.setVisible(False)
        self._scenarios = []
        self._capacityGroup = QtWidgets.QGraphicsItemGroup()
        self._generationGroup = QtWidgets.QGraphicsItemGroup()
        self._nameGroup = QtWidgets.QGraphicsItemGroup()
        self._fossilGroup = QtWidgets.QGraphicsItemGroup()
        self._fcapacityGroup = QtWidgets.QGraphicsItemGroup()
        self._fnameGroup = QtWidgets.QGraphicsItemGroup()
        self._setupStations()
        self.addItem(self._capacityGroup)
        if not self.show_capacity:
            self._capacityGroup.setVisible(False)
            self._fcapacityGroup.setVisible(False)
        self.addItem(self._generationGroup)
        if not self.show_generation:
            self._generationGroup.setVisible(False)
        self.addItem(self._fossilGroup)
        self.addItem(self._fcapacityGroup)
        self.addItem(self._fnameGroup)
        if not self.show_fossil:
            self._fossilGroup.setVisible(False)
            self._fcapacityGroup.setVisible(False)
            self._fnameGroup.setVisible(False)
        self.addItem(self._nameGroup)
        if not self.show_station_name:
            self._nameGroup.setVisible(False)
            self._fnameGroup.setVisible(False)
        self._plot_cache = {}

    def _setupCoordTransform(self):
        self._proj = pyproj.Proj('+init=' + self.projection)   # LatLon with WGS84 datum used by GPS units and Google Earth
        x1, y1, lon1, lat1 = self.upper_left
        x2, y2, lon2, lat2 = self.lower_right
        ul = self._proj(lon1, lat1)
        lr = self._proj(lon2, lat2)
        self._lat_scale = y2 / (lr[1] - ul[1])
        self._lon_scale = x2 / (lr[0] - ul[0])
        self._orig_lat = ul[1]
        self._orig_lon = ul[0]

    def _setupCoordGrid(self):
        bnds = [45., 90., 180.]
        degs = [2.5, 5., 10.]
        mlt = 1
        color = QtGui.QColor()
        color.setNamedColor((self.colors['town_name']))
        pen = QtGui.QPen(color, self.line_width)
        pen.setJoinStyle(QtCore.Qt.RoundJoin)
        pen.setCapStyle(QtCore.Qt.RoundCap)
        step1 = abs((self.map_upper_left[0] - self.map_lower_right[0]))
        step2 = abs((self.map_upper_left[1] - self.map_lower_right[1]))
        step = min(step1, step2)
        while step < bnds[0] * mlt:
            mlt = mlt / 10.
        if step > bnds[2] * mlt:
            step = degs[2] * mlt
        elif step > bnds[1] * mlt:
            step = degs[1] * mlt
        else:
            step = degs[0] * mlt
        lat = step * round((self.map_lower_right[0] + step / 2.) / step)
        while lat <= self.map_upper_left[0]:
            fromm = self.mapFromLonLat(QtCore.QPointF(self.map_upper_left[1], lat))
            too = self.mapFromLonLat(QtCore.QPointF(self.map_lower_right[1], lat))
            item = QtWidgets.QGraphicsLineItem(fromm.x(), fromm.y(), too.x(), too.y())
            item.setPen(pen)
            item.setZValue(3)
            self._coordGroup.addToGroup(item)
            lat += step
        lon = step * round((self.map_upper_left[1] + step / 2.) / step)
        while lon <= self.map_lower_right[1]:
            fromm = self.mapFromLonLat(QtCore.QPointF(lon, self.map_upper_left[0]))
            too = self.mapFromLonLat(QtCore.QPointF(lon, self.map_lower_right[0]))
            item = QtWidgets.QGraphicsLineItem(fromm.x(), fromm.y(), too.x(), too.y())
            item.setPen(pen)
            item.setZValue(3)
            self._coordGroup.addToGroup(item)
            lon += step
        return

    def _setupTowns(self):
        self._towns = {}
        self._towns = Towns(ul_lat=self.upper_left[3], ul_lon=self.upper_left[2],
                      lr_lat=self.lower_right[3], lr_lon=self.lower_right[2])
        for st in self._towns.towns:
            p = self.mapFromLonLat(QtCore.QPointF(st.lon, st.lat))
            el = QtWidgets.QGraphicsEllipseItem(p.x() - 1, p.y() - 1, 2, 2)   # here to adjust town circles
            el.setBrush(QtGui.QColor(self.colors['town']))
            el.setPen(QtGui.QColor(self.colors['town']))
            el.setZValue(0)
            self._townGroup.addToGroup(el)
            txt = QtWidgets.QGraphicsSimpleTextItem(st.name)
            new_font = txt.font()
            new_font.setPointSizeF(self.width() * (self.txt_ratio / 2.))
            txt.setFont(new_font)
            txt.setPos(p + QtCore.QPointF(1.5, -0.5))
            txt.setBrush(QtGui.QColor(self.colors['town_name']))
            txt.setZValue(0)
            self._townGroup.addToGroup(txt)
        return

    def _setupStations(self):
        self._current_name = QtWidgets.QGraphicsSimpleTextItem('')
        new_font = self._current_name.font()
        new_font.setPointSizeF(self.width() * self.txt_ratio)
        self._current_name.setFont(new_font)
        self._current_name.setZValue(2)
        self.addItem(self._current_name)
        self._stations = {}
        self._station_positions = {}
        self._stationGroups = {}
        self._stationLabels = []
        self._stationCircles = {}
        for key, value in self.colors.items():
            self._stationCircles[key] = []
        if self.existing:
            self._stations = Stations()
            for st in self._stations.stations:
                self.addStation(st)
            self._scenarios.append(['Existing', False, 'Existing stations'])
        else:
            self._stations = Stations(existing=False)
        if self.scenario != '':
            self._setupScenario(self.scenario)

    def _setupScenario(self, scenario):
        i = scenario.rfind('/')
        if i > 0:
            scen_file = scenario
            scen_filter = scenario[i + 1:]
        else:
            scen_file = self.scenarios + scenario
            scen_filter = scenario
        if os.path.exists(scen_file):
            description = ''
            if scen_file[-4:] == '.xls' or scen_file[-5:] == '.xlsx' or \
             scen_file[-5:] == '.xls~' or scen_file[-6:] == '.xlsx~':
                var = {}
                workbook = xlrd.open_workbook(scen_file)
                worksheet = workbook.sheet_by_index(0)
                num_rows = worksheet.nrows - 1
                num_cols = worksheet.ncols - 1
                if worksheet.cell_value(0, 0) == 'Description:' or worksheet.cell_value(0, 0) == 'Comment:':
                    curr_row = 1
                    description = worksheet.cell_value(0, 1)
                else:
                    curr_row = 0
#               get column names
                curr_col = -1
                while curr_col < num_cols:
                    curr_col += 1
                    var[worksheet.cell_value(curr_row, curr_col)] = curr_col
                while curr_row < num_rows:
                    curr_row += 1
                    try:
                        new_st = Station(str(worksheet.cell_value(curr_row, var['Station Name'])),
                                         str(worksheet.cell_value(curr_row, var['Technology'])),
                                         worksheet.cell_value(curr_row, var['Latitude']),
                                         worksheet.cell_value(curr_row, var['Longitude']),
                                         worksheet.cell_value(curr_row, var['Maximum Capacity (MW)']),
                                         str(worksheet.cell_value(curr_row, var['Turbine'])),
                                         worksheet.cell_value(curr_row, var['Rotor Diam']),
                                         worksheet.cell_value(curr_row, var['No. turbines']),
                                         worksheet.cell_value(curr_row, var['Area']),
                                         scen_filter)
                        name_ok = False
                        new_name = new_st.name
                        ctr = 0
                        while not name_ok:
                            for i in range(len(self._stations.stations)):
                                if self._stations.stations[i].name == new_name:
                                    ctr += 1
                                    new_name = new_st.name + ' ' + str(ctr)
                                    break
                            else:
                                name_ok = True
                        if new_name != new_st.name:
                            new_st.name = new_name
                        if new_st.area == 0 or new_st.area == '':
                            if new_st.technology == 'Wind':
                                new_st.area = self.areas[new_st.technology] * float(new_st.no_turbines) * \
                                              pow((new_st.rotor * .001), 2)
                            else:
                                new_st.area = self.areas[new_st.technology] * float(new_st.capacity)
                        try:
                            power_file = worksheet.cell_value(curr_row, var['Power File'])
                            if power_file != '':
                                new_st.power_file = power_file
                        except:
                            pass
                        try:
                            grid_line = worksheet.cell_value(curr_row, var['Grid Line'])
                            if grid_line != '':
                                new_st.grid_line = grid_line
                        except:
                            pass
                        try:
                            direction = worksheet.cell_value(curr_row, var['Direction'])
                            if direction != '':
                                new_st.direction = direction
                        except:
                            pass
                        try:
                            tilt = worksheet.cell_value(curr_row, var['Tilt'])
                            if tilt != '':
                                setattr(new_st, 'tilt', tilt)
                        except:
                            pass
                        try:
                            storage_hours = worksheet.cell_value(curr_row, var['Storage Hours'])
                            if storage_hours != '':
                                setattr(new_st, 'storage_hours', storage_hours)
                        except:
                            pass
                        self._stations.stations.append(new_st)
                        self.addStation(self._stations.stations[-1])
                    except:
                        pass
            else:
                scene = open(scen_file)
                line = scene.readline()
                if len(line) > 9 and line[:9] ==  'Comment:,' or len(line) > 13 and line[:13] == 'Description:,':
                    if line[:9] ==  'Comment:,':
                        description = line[9:]
                    else:
                        description = line[13:]
                    if description[0] == '"':
                        i = description.rfind('"')
                        description = description[1:i - 1]
                    else:
                        bits = line.split(',')
                        description = bits[1]
                else:
                    scene.seek(0)
                new_stations = csv.DictReader(scene)
                for st in new_stations:
                    new_st = Station(st['Station Name'], st['Technology'], float(st['Latitude']),
                             float(st['Longitude']), float(st['Maximum Capacity (MW)']),
                             st['Turbine'], float(st['Rotor Diam']), int(st['No. turbines']), float(st['Area']), scen_filter)
                    if new_st.area == 0:
                        if new_st.technology == 'Wind':
                            new_st.area = self.areas[new_st.technology] * float(new_st.no_turbines) * \
                                          pow((new_st.rotor * .001), 2)
                        else:
                            new_st.area = self.areas[new_st.technology] * float(new_st.capacity)
                    self._stations.stations.append(new_st)
                    self.addStation(self._stations.stations[-1])
                scene.close()
            self._scenarios.append([scen_filter, False, description])

    def _setupGrid(self):
        def do_them(lines, width=self.line_width, grid2=False):
            for line in lines:
                color = QtGui.QColor()
                color.setNamedColor(line.style)
                pen = QtGui.QPen(color, width)
                pen.setJoinStyle(QtCore.Qt.RoundJoin)
                pen.setCapStyle(QtCore.Qt.RoundCap)
                start = self.mapFromLonLat(QtCore.QPointF(line.coordinates[0][1], line.coordinates[0][0]))
                for pt in range(1, len(line.coordinates)):
                    end = self.mapFromLonLat(QtCore.QPointF(line.coordinates[pt][1], line.coordinates[pt][0]))
                    # FIXME Can't identify the QGraphicsScene in the arguments of the QGraphicsItem
                    ln = QtWidgets.QGraphicsLineItem(QtCore.QLineF(start, end))
                    ln.setPen(pen)
                    ln.setZValue(0)
                    self.addItem(ln)
                    if grid2:
                        self._gridGroup2.addToGroup(ln)
                    else:
                        self._gridGroup.addToGroup(ln)
                    start = end
            return
        self.lines = Grid()
        do_them(self.lines.lines)
        self.grid_lines = len(self.lines.lines)
        lines = Grid_Boundary()
        if len(lines.lines) > 0:
            lines.lines[0].style = self.colors['grid_boundary']
            do_them(lines.lines, width=0)
        if self.existing_grid2:
            lines2 = Grid(grid2=True)
            do_them(lines2.lines, grid2=True)

    def addStation(self, st):
        self._stationGroups[st.name] = []
        p = self.mapFromLonLat(QtCore.QPointF(st.lon, st.lat))
        size = -1
        if self.station_square:
            if self.scale:
                try:
                    size = sqrt(st.area) / 2.
                except:
                    if st.technology == 'Wind':
                        size = self.areas[st.technology] * float(st.no_turbines) * pow((float(st.rotor) * .001), 2)
                    else:
                        size = self.areas[st.technology] * float(st.capacity)
                e = self.destinationxy(st.lon, st.lat, 90., size)
                w = self.destinationxy(st.lon, st.lat, 270., size)
                n = self.destinationxy(st.lon, st.lat, 0., size)
                s = self.destinationxy(st.lon, st.lat, 180., size)
                p2 = self.mapFromLonLat(QtCore.QPointF(w[0], n[1]))
                pe = self.mapFromLonLat(QtCore.QPointF(e[0], n[1]))
                ps = self.mapFromLonLat(QtCore.QPointF(w[0], s[1]))
                x_d = pe.x() - p2.x()
                y_d = ps.y() - p2.y()
                el = QtWidgets.QGraphicsRectItem(p2.x(), p2.y(), x_d, y_d)
            else:
                el = QtWidgets.QGraphicsRectItem(p.x() - 1.5, p.y() - 1.5, 3, 3)   # here to adjust station squares when not scaling
        else:
            if self.scale:
                try:
                    size = sqrt(st.area / pi) * 2.   # need diameter
                except:
                    if st.technology == 'Wind':
                        size = sqrt(self.areas[st.technology] *
                                    float(st.no_turbines) * pow((float(st.rotor) *
                                                                 .001), 2) / pi) * 2.
                    else:
                        size = sqrt(self.areas[st.technology] * float(st.capacity) / pi) * 2.
                east = self.destinationxy(st.lon, st.lat, 90., size)
                pe = self.mapFromLonLat(QtCore.QPointF(east[0], st.lat))
                north = self.destinationxy(st.lon, st.lat, 0., size)
                pn = self.mapFromLonLat(QtCore.QPointF(st.lon, north[1]))
                x_d = p.x() - pe.x()
                y_d = pn.y() - p.y()
                el = QtWidgets.QGraphicsEllipseItem(p.x() - x_d / 2, p.y() - y_d / 2, x_d, y_d)
            else:
                el = QtWidgets.QGraphicsEllipseItem(p.x() - 1.5, p.y() - 1.5, 3, 3)   # here to adjust station circles when not scaling
        try:
            el.setBrush(QtGui.QColor(self.colors[st.technology]))
        except:
            self.colors[st.technology] = 'gray'
            el.setBrush(QtGui.QColor('gray'))
        if self.station_opacity < 1.:
            el.setOpacity(self.station_opacity)
        if self.colors['border'] != '':
            el.setPen(QtGui.QColor(self.colors['border']))
        else:
            el.setPen(QtGui.QColor(self.colors[st.technology]))
        el.setZValue(1)
        self.addItem(el)
        self._stationGroups[st.name].append(el)
        try:
            self._stationCircles[st.technology].append(el)
        except:
            self._stationCircles[st.technology] = [(el)]
        if st.technology[:6] == 'Fossil':
            self._fossilGroup.addToGroup(el)
        size = sqrt(float(st.capacity) * self.capacity_area / pi)
        east = self.destinationxy(st.lon, st.lat, 90., size)
        pe = self.mapFromLonLat(QtCore.QPointF(east[0], st.lat))
        north = self.destinationxy(st.lon, st.lat, 0., size)
        pn = self.mapFromLonLat(QtCore.QPointF(st.lon, north[1]))
        x_d = p.x() - pe.x()
        y_d = pn.y() - p.y()
        el = QtWidgets.QGraphicsEllipseItem(p.x() - x_d / 2, p.y() - y_d / 2, x_d, y_d)
        if self.show_capacity_fill:
            el.setBrush(QtGui.QColor(self.colors[st.technology]))
            el.setOpacity(self.capacity_opacity)
        if self.colors['border'] != '':
            el.setPen(QtGui.QColor(self.colors['border']))
        else:
            el.setPen(QtGui.QColor(self.colors[st.technology]))
        el.setZValue(1)
        self.addItem(el)
        self._stationGroups[st.name].append(el)
        self._stationCircles[st.technology].append(el)
        if st.technology[:6] == 'Fossil':
            self._fcapacityGroup.addToGroup(el)
        else:
            self._capacityGroup.addToGroup(el)
        self.addLine(st)
        txt = QtWidgets.QGraphicsSimpleTextItem(st.name)
        new_font = txt.font()
        new_font.setPointSizeF(self.width() * self.txt_ratio)
        txt.setFont(new_font)
        txt.setPos(p + QtCore.QPointF(1.5, -0.5))
        if st.technology[:6] == 'Fossil':
            txt.setBrush(QtGui.QColor(self.colors['fossil_name']))
        else:
            txt.setBrush(QtGui.QColor(self.colors['station_name']))
        txt.setZValue(2)
        self.addItem(txt)
        self._stationGroups[st.name].append(txt)
        self._stationLabels.append(txt)
        if st.technology[:6] == 'Fossil':
            self._fnameGroup.addToGroup(txt)
        else:
            self._nameGroup.addToGroup(txt)
        return

    def addGeneration(self, st):
        if (st.technology[:6] != 'Fossil' or self.show_fossil) and st.generation > 0:
            p = self.mapFromLonLat(QtCore.QPointF(st.lon, st.lat))
            size = sqrt(float(st.generation) * (self.capacity_area / 2000) / pi)
            east = self.destinationxy(st.lon, st.lat, 90., size)
            pe = self.mapFromLonLat(QtCore.QPointF(east[0], st.lat))
            north = self.destinationxy(st.lon, st.lat, 0., size)
            pn = self.mapFromLonLat(QtCore.QPointF(st.lon, north[1]))
            x_d = p.x() - pe.x()
            y_d = pn.y() - p.y()
            el = QtWidgets.QGraphicsEllipseItem(p.x() - x_d / 2, p.y() - y_d / 2, x_d, y_d)
            if self.show_capacity_fill:
                brush = QtGui.QBrush()
                brush.setColor(QtGui.QColor(self.colors[st.technology]))
            #     brush.setStyle(QtCore.Qt.Dense1Pattern)
                brush.setStyle(QtCore.Qt.SolidPattern)
                el.setBrush(brush)
                el.setOpacity(self.capacity_opacity)
            if self.colors['border'] != '':
                el.setPen(QtGui.QColor(self.colors['border']))
            else:
                el.setPen(QtGui.QColor(self.colors[st.technology]))
            el.setZValue(1)
            self.addItem(el)
            self._stationGroups[st.name].append(el)
            self._stationCircles[st.technology].append(el)
            self._generationGroup.addToGroup(el)

    def addLine(self, st):
        if st.technology == 'Rooftop PV':
            return
        if self.new_grid and (st.scenario != 'Existing' or self.trace_existing):
            dims = [[st.lat, st.lon]]
            grid_len = 0.
            grid_path_len = 0.
            gridn = ''
            if st.grid_line is not None:
                gridn = st.grid_line.replace('(', '')
                gridn = gridn.replace('))', '')
                gridn = gridn.replace('),', ',')
                gridn = gridn.replace(')', '')
                gridn = gridn.split(',')
                for j in range(2, len(gridn), 2):
                    dims.append([float(gridn[j]), float(gridn[j + 1])])
                    grid_len += self.lines.actualDistance(dims[-2][0], dims[-2][1], dims[-1][0], dims[-1][1])
            grid_point = self.lines.gridConnect(dims[-1][0], dims[-1][1])
            if grid_point[0] == -1:
                if self.load_centre is not None:   # start with a load centre
                    nearest = 99999
                    j = -1
                    for i in range(len(self.load_centre)):
                        thisone = self.lines.actualDistance(self.load_centre[i][1], self.load_centre[i][2],
                                  dims[-1][0], dims[-1][1])
                        if thisone < nearest:
                            nearest = thisone
                            j = i
                    grid_point[0] = nearest
                    grid_point[1] = self.load_centre[j][1]
                    grid_point[2] = self.load_centre[j][2]
                    grid_point[3] = -1
                else:
                    try:
                        nearest, dist = self._stations.Nearest(dims[-1][0], dims[-1][1], distance=True, fossil=True,
                                        ignore=st.name)
                    except:
                        return
                    grid_point[0] = dist
                    grid_point[1] = nearest.lat
                    grid_point[2] = nearest.lon
                    grid_point[3] = -1
            if grid_point[0] > 0 or len(gridn) > 1:
                grid_len += grid_point[0]
                dims.append([grid_point[1], grid_point[2]])
                if st.technology in self.dispatchable:
                    dispatchable = 'Y'
                else:
                    dispatchable = ''
                l = Line(st.name, self.colors['new_grid'], dims, round(grid_len, 1), grid_point[3], dispatchable, 0,
                    0.)
            #     l.peak_loss = round(st.capacity * self.line_loss * l.length + self.subs_loss * st.capacity, 3)
              #   subs_cost = self.subs_cost * st.capacity
                if l.dispatchable == 'Y':
                    cost, l.line_table = self.lines.Line_Cost(st.capacity, st.capacity)
                else:
                    cost, l.line_table = self.lines.Line_Cost(st.capacity, 0.)
                l.line_cost = round(l.length * cost, 0)
                next = grid_point[3]
                self.lines.lines.append(l)
                if self.trace_grid and self.load_centre is not None:
                    nearest = 99999
                    j = -1
                    for i in range(len(self.load_centre)):
                        thisone = self.lines.actualDistance(self.load_centre[i][1], self.load_centre[i][2],
                                  dims[0][0], dims[0][1])
                        if thisone < nearest:
                            nearest = thisone
                            j = i
                    path = Shortest(self.lines.lines, dims[0], [self.load_centre[j][1],
                           self.load_centre[j][2]], self.grid_lines)
                    line = path.getLines()
                    for li in line:
                        if self.lines.lines[li].peak_load is None:
                            self.lines.lines[li].peak_load = 0.
                        if self.lines.lines[li].peak_loss is None:
                            self.lines.lines[li].peak_loss = 0.
                        self.lines.lines[li].peak_loss += round((st.capacity * self.line_loss * self.lines.lines[li].length), 3)
                        self.lines.lines[li].peak_load += st.capacity
                        if dispatchable == 'Y':
                            self.lines.lines[li].dispatchable = 'Y'
                            if self.lines.lines[li].peak_dispatchable is None:
                                self.lines.lines[li].peak_dispatchable = 0.
                            self.lines.lines[li].peak_dispatchable += st.capacity
                    route = path.getPath()
#                   check we don't go through another load_centre
                    if len(self.load_centre) > 1:
                        for co in range(len(route) - 1, 0, -1):
                            for i in range(len(self.load_centre)):
                                if route[co][0] == self.load_centre[i][1] and \
                                  route[co][1] == self.load_centre[i][2]:
                                    route = route[i:]
                                    break
                    for i in range(1, len(route)):
                        grid_path_len += self.lines.actualDistance(route[i - 1][0], route[i - 1][1],
                                         route[i][0], route[i][1])
                else:
                    if self.lines.lines[next].peak_load is None:
                        self.lines.lines[next].peak_load = 0.
                        self.lines.lines[next].peak_loss = 0.
                    self.lines.lines[next].peak_load += st.capacity
                    if dispatchable == 'Y':
                        if self.lines.lines[next].peak_dispatchable is None:
                            self.lines.lines[next].peak_dispatchable = 0.
                        self.lines.lines[next].peak_dispatchable += st.capacity
                    try:
                        self.lines.lines[next].peak_loss += round((st.capacity * self.line_loss * l.length), 3)
                    except:
                        pass
                color = QtGui.QColor()
                color.setNamedColor(self.lines.lines[-1].style)
                pen = QtGui.QPen(color, self.line_width)
                pen.setJoinStyle(QtCore.Qt.RoundJoin)
                pen.setCapStyle(QtCore.Qt.RoundCap)
                start = self.mapFromLonLat(QtCore.QPointF(l.coordinates[0][1],
                  l.coordinates[0][0]))
                for i in range(1, len(l.coordinates)):
                    end = self.mapFromLonLat(QtCore.QPointF(l.coordinates[i][1],
                      l.coordinates[i][0]))
                    # FIXME Can't identify the QGraphicsScene in the arguments of the QGraphicsItem
                    ln = QtWidgets.QGraphicsLineItem(QtCore.QLineF(start, end))
                    ln.setPen(pen)
                    ln.setZValue(0)
                    self.addItem(ln)
                    self._stationGroups[st.name].append(ln)
                    start = end
            if grid_len > 0:
                st.grid_len = grid_len
            if grid_path_len > 0:
                st.grid_path_len = grid_path_len

    def refreshGrid(self):
        for i in range(self.grid_lines):
            if self.lines.lines[i].peak_load is not None:
                self.lines.lines[i].peak_dispatchable = 0.
                self.lines.lines[i].peak_load = 0.
                self.lines.lines[i].peak_loss = 0.
        if self.new_grid:
            for i in range(len(self.lines.lines) - 1, self.grid_lines - 1, -1):
                if self.lines.lines[i].peak_load is not None:
                    self.lines.lines[i].peak_dispatchable = 0.
                    self.lines.lines[i].peak_load = 0.
                    self.lines.lines[i].peak_loss = 0.
                if self.lines.lines[i].length > 0:
                    try:
                        for j in range(len(self._stationGroups[self.lines.lines[i].name])):
                            if isinstance(self._stationGroups[self.lines.lines[i].name][j], QtWidgets.QGraphicsLineItem):
                                self.removeItem(self._stationGroups[self.lines.lines[i].name][j])
                                del self._stationGroups[self.lines.lines[i].name][j]
                                break
                    except:
                        pass
                    del self.lines.lines[i]
            for st in self._stations.stations:
                self.addLine(st)

    def changeDate(self, d):
        return
        d = datetime.date(d.year(), d.month(), d.day())
        for st in list(self._stations.values()):
            st.changeDate(d)
        self._power_tot.changeDate(d)

    def mapToLonLat(self, p, decpts=4):
        x = p.x() / self._lon_scale + self._orig_lon
        y = p.y() / self._lat_scale + self._orig_lat
        lon, lat = self._proj(x, y, inverse=True)
        return QtCore.QPointF(round(lon, decpts), round(lat, decpts))

    def mapFromLonLat(self, p):
        lon, lat = p.x(), p.y()
        x, y = self._proj(lon, lat)
        x = (x - self._orig_lon) * self._lon_scale
        y = (y - self._orig_lat) * self._lat_scale
        return QtCore.QPointF(x, y)

    def positions(self):
        try:
            return self._positions
        except:
            return

    def stationPositions(self):
        return self._station_positions

    def toggleTotal(self, start):
        if self._power_tot.infoVisible():
            self._power_tot.hideInfo()
        else:
            self._power_tot.showInfo(0, start)

    def powerPlotImage(self, name):
        return self._stations[name].powerPlotImage() class EdtDialog(QtWidgets.QDialog):
    def __init__(self, in_file, parent=None):
        self.in_file = in_file
        try:
            s = open(self.in_file, 'r').read()
            bits = s.split('\n')
            ln = 0
            for lin in bits:
                if len(lin) > ln:
                    ln = len(lin)
            ln2 = len(bits)
        except:
            if self.in_file[self.in_file.rfind('.'):] == '.ini':
                s = ''
            else:
                s = ''
            ln = 36
            ln2 = 5
        QtWidgets.QDialog.__init__(self, parent)
        self.saveButton = QtWidgets.QPushButton(self.tr('&Save'))
        self.cancelButton = QtWidgets.QPushButton(self.tr('Cancel'))
        buttonLayout = QtWidgets.QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(self.saveButton)
        buttonLayout.addWidget(self.cancelButton)
        self.saveButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)
        self.widget = QtWidgets.QPlainTextEdit()
        highlight = inisyntax.IniHighlighter(self.widget.document())
        if sys.platform == 'linux' or sys.platform == 'linux2':
            self.widget.setFont(QtGui.QFont('Ubuntu Mono 13', 12))
        else:
            self.widget.setFont(QtGui.QFont('Courier New', 12))
        fnt = self.widget.fontMetrics()
        ln = (ln + 5) * fnt.maxWidth()
        ln2 = (ln2 + 4) * fnt.height()
        screen = QDesktopWidget().availableGeometry()
        if ln > screen.width() * .67:
            ln = int(screen.width() * .67)
        if ln2 > screen.height() * .67:
            ln2 = int(screen.height() * .67)
        self.widget.resize(ln, ln2)
        self.widget.setPlainText(s)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.widget)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)
        self.setWindowTitle('SIREN - Edit - ' + self.in_file[self.in_file.rfind('/') + 1:])
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        size = self.geometry()
        self.setGeometry(1, 1, ln + 10, ln2 + 35)
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
            (screen.height() - size.height()) / 2)
        self.widget.show()

    def accept(self):
        t = self.widget.toPlainText()
        bits = t.split('\n')
        if self.in_file[self.in_file.rfind('.'):] != '.ini':
            bits.sort()
            while len(bits[0]) == 0:
                del bits[0]
        s = open(self.in_file, 'w')
        for lin in bits:
            if len(lin) > 0:
                s.write(lin + '\n')
        s.close()
        self.close() class EditTech():
    def __init__(self, save_folder, ini_file=None):
        config = configparser.RawConfigParser()
        if ini_file is not None:
            config_file = ini_file
        elif len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        technologies = config.get('Power', 'technologies')
        technologies += ' ' + config.get('Power', 'fossil_technologies')
        technologies = technologies.split()
        for i in range(len(technologies)):
            technologies[i] = techClean(technologies[i])
        technologies = sorted(technologies)
        tech_dict = {}
        for technology in technologies:
            area = 0.
            capital_cost = ''
            o_m_cost = ''
            try:
                area = float(config.get(technology, 'area'))
            except:
                pass
            try:
                capital_cost = config.get(technology, 'capital_cost')
                if capital_cost[-1] == 'K':
                    capital_cost = float(capital_cost[:-1]) * pow(10, 3)
                elif capital_cost[-1] == 'M':
                    capital_cost = float(capital_cost[:-1]) * pow(10, 6)
                else:
                    capital_cost = float(capital_cost)
            except:
                pass
            try:
                o_m_cost = config.get(technology, 'o_m_cost')
                if o_m_cost[-1] == 'K':
                    o_m_cost = float(o_m_cost[:-1]) * pow(10, 3)
                elif o_m_cost[-1] == 'M':
                    o_m_cost = float(o_m_cost[:-1]) * pow(10, 6)
                else:
                    o_m_cost = float(o_m_cost)
            except:
                pass
            tech_dict[technology] = [area, capital_cost, o_m_cost]
        dialog = Table(tech_dict, fields=['technology', 'area', 'capital_cost', 'o_m_cost'],
                 save_folder=save_folder, title='Technologies', edit=True)
        dialog.exec_()
        values = dialog.getValues()
        if values is None:
            return
        SaveIni(values) class EditSect():
    def __init__(self, section, save_folder, ini_file=None):
        self.section = section
        config = configparser.RawConfigParser()
        if ini_file is not None:
            config_file = ini_file
        elif len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        section_items = config.items(self.section)
        section_dict = {}
        for key, value in section_items:
            section_dict[key] = value
        dialog = Table(section_dict, fields=['property', 'value'], title=self.section + ' Parameters',
                 save_folder=save_folder, edit=True)
        dialog.exec_()
        values = dialog.getValues()
        if values is None:
            return
        section_dict = {}
        section_items = []
        for key in values:
            try:
                section_items.append(key + '=' + values[key][0][6:])
            except:
                section_items.append(key + '=')
        section_dict[self.section] = section_items
        SaveIni(section_dict, ini_file=config_file) class SaveIni():
    def __init__(self, values, ini_file=None):
        if ini_file is not None:
            config_file = ini_file
        elif len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        try:
            inf = open(config_file, 'r')
            lines = inf.readlines()
            inf.close()
        except:
            lines = []
        del_lines = []
        for section in values:
            in_section = False
            properties = values[section]
            props = []
            for i in range(len(properties)):
                props.append(properties[i].split('=')[0])
            for i in range(len(lines)):
                if lines[i][:len(section) + 2] == '[' + section + ']':
                    in_section = True
                elif in_section:
                    if lines[i][0] == '[':
                        i -= 1
                        break
                    elif lines[i][0] != ';' and lines[i][0] != '#':
                        bits = lines[i].split('=')
                        for j in range(len(properties) - 1, -1, -1):
                            if bits[0] == props[j]:
                                if properties[j] == props[j] + '=' \
                                  or properties[j] == props[j]: # delete empty values
                                    del_lines.append(i)
                                else:
                                    lines[i] = properties[j] + '\n'
                                del properties[j]
                                del props[j]
            if len(properties) > 0:
                if not in_section:
                    lines.append('[' + section + ']\n')
                    i += 1
                for j in range(len(properties)):
                    k = properties[j].find('=')
                    if k > 0 and k != len(properties[j]) - 1:
                        lines.insert(i + 1, properties[j] + '\n')
                        i += 1
        if os.path.exists(config_file + '~'):
            os.remove(config_file + '~')
        try:
            os.rename(config_file, config_file + '~')
        except:
            pass
        sou = open(config_file, 'w')
        for i in range(len(lines)):
            if i in del_lines:
                pass
            else:
                sou.write(lines[i])
        sou.close() class Shortest:
    def isBetween(self, a, b, c):
        crossproduct = (c[1] - a[1]) * (b[0] - a[0]) - (c[0] - a[0]) * (b[1] - a[1])
        if abs(crossproduct) > 0.0001:  # sys.float_info.epsilon:
            return False    # (or != 0 if using integers)
        dotproduct = (c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1])
        if dotproduct < 0:
            return False
        squaredlengthba = (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1])
        if dotproduct > squaredlengthba:
            return False
        return True

    def Distance(self, y1, x1, y2, x2):
# find the differences between the coordinates
        dy = y2 - y1
        dx = x2 - x1
        ra13 = pow(sin(dy / 2.), 2) + cos(y1) * cos(y2) * pow(sin(dx / 2.), 2)
        return 2 * asin(min(1, sqrt(ra13)))

    def actualDistance(self, y1d, x1d, y2d, x2d):
        x1 = radians(x1d)
        y1 = radians(y1d)
        x2 = radians(x2d)
        y2 = radians(y2d)
        dst = self.Distance(y1, x1, y2, x2)
        return round(abs(dst) * RADIUS, 2)

    def __init__(self, lines, source, target, grid):
        self.source = source
        self.target = target
        self.lines = lines
        self.grid = grid # existing grid lines count
        self.edges = {}
        self.g = Graph()
        for li in range(len(self.lines)):
            vert1 = str(self.lines[li].coordinates[0])
            for pt in range(1, len(self.lines[li].coordinates)):
                vert2 = str(self.lines[li].coordinates[pt])
                dist = self.actualDistance(self.lines[li].coordinates[pt][0], self.lines[li].coordinates[pt][1],
                       self.lines[li].coordinates[pt - 1][0], self.lines[li].coordinates[pt - 1][1])
                self.g.add_edge(vert1, vert2, dist)
                self.edges[vert1 + vert2] = li
                vert1 = vert2
        for li in range(self.grid, len(self.lines)):
            for l2 in range(len(self.lines)):
                if li == l2:
                    continue
                for pt in range(1, len(self.lines[l2].coordinates)):
                    if self.lines[l2].coordinates[pt - 1] == self.lines[li].coordinates[-1] or \
                      self.lines[l2].coordinates[pt] == self.lines[li].coordinates[-1]:
                        continue
                    if self.isBetween(self.lines[l2].coordinates[pt - 1], self.lines[l2].coordinates[pt],
                      self.lines[li].coordinates[-1]):
                        dist = self.actualDistance(self.lines[l2].coordinates[pt - 1][0], self.lines[l2].coordinates[pt - 1][1],
                               self.lines[li].coordinates[-1][0], self.lines[li].coordinates[-1][1])
                        vert1 = str(self.lines[l2].coordinates[pt - 1])
                        vert2 = str(self.lines[li].coordinates[-1])
                        self.g.add_edge(vert1, vert2, dist)
                        self.edges[vert1 + vert2] = l2
                        dist = self.actualDistance(self.lines[l2].coordinates[pt][0], self.lines[l2].coordinates[pt][1],
                               self.lines[li].coordinates[-1][0], self.lines[li].coordinates[-1][1])
                        vert1 = str(self.lines[l2].coordinates[pt])
                        vert2 = str(self.lines[li].coordinates[-1])
                        self.g.add_edge(vert1, vert2, dist)
                        self.edges[vert1 + vert2] = l2
                        break
     #    print 'Graph data:'
      #   print 'source', self.source, 'target', self.target
       #  for v in self.g:
        #     for w in v.get_connections():
         #        vid = v.get_id()
          #       wid = w.get_id()
           #      print '(%s ,%s, %s)'  % (vid, wid, str(v.get_weight(w)))
        if self.g.get_vertex(str(self.source)) is None:
            self.g.add_vertex(str(self.source))
        dijkstra(self.g, self.g.get_vertex(str(self.source)))
        target = self.g.get_vertex(str(self.target))
        try:
            self.path = [target.get_id()]
            shortest(target, self.path)
        except:
            self.path = []

    def getPath(self):
        the_path = []
        for i in range(len(self.path)):
            it = self.path[i].replace('[', '')
            it = it.replace(']', '')
            it = it.replace(' ', '')
            bit = it.split(',')
            the_path.append([float(bit[0]), float(bit[1])])
        return the_path

    def getLines(self):
        the_lines = []
        for i in range(1, len(self.path)):
            try:
                the_lines.append(self.edges[self.path[i - 1] + self.path[i]])
            except:
                try:
                    the_lines.append(self.edges[self.path[i] + self.path[i - 1]])
                except:
                    pass
        the_lines = list(set(the_lines))
        return the_lines class Credits(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, initial=False):
        super(Credits, self).__init__()
        self.initial = initial
        self.initUI()

    def initUI(self):
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.restorewindows = False
        try:
            rw = config.get('Windows', 'restorewindows')
            if rw.lower() in ['true', 'yes', 'on']:
                self.restorewindows = True
        except:
            pass
        self.be_open = True
        self.grid = QtWidgets.QGridLayout()
        pixmap = QtGui.QPixmap('sen_logo_2.png')
        lbl = QtWidgets.QLabel(self)
        lbl.setPixmap(pixmap)
        self.grid.addWidget(lbl)
        if os.path.exists('credits.html'):
            web = QtWidgets.QTextEdit()
            htf = open('credits.html', 'r')
            html = htf.read()
            html = html.replace('[VERSION]', fileVersion())
            html = html.replace('[VERSION-YEAR]', fileVersion(year=True))
            htf.close()
            if html[:5] == '<html' or html[:15] == '<!DOCTYPE html>':
                web.setHtml(html)
            else:
                web.setPlainText(html)
            web.setReadOnly(True)
            small = QtGui.QFont()
            small.setPointSize(10)
            web.setFont(small)
            self.grid.addWidget(web, 1, 0)
        else:
            bold = QtGui.QFont()
            bold.setBold(True)
            labels = []
            labels.append("SIREN - SEN's Interactive Renewable Energy Network tool")
            labels.append('Copyright (C) 2015-' + fileVersion(year=True) + ' Sustainable Energy Now Inc., Angus King')
            labels.append('Release:' + fileVersion())
            labels.append('SIREN is free software: you can redistribute it and/or modify it under the terms of the' +
                          ' GNU Affero General Public License. The program is distributed WITHOUT ANY WARRANTY')
            labels.append('The SEN SAM simulation is used to calculate energy generation for renewable energy' +
                          ' power stations using SAM models.')
            labels.append('To get started press F1 (menu option Help -> Help) to view the SIREN Help file.')
            labels.append('Capabilities, assumptions, limitations (ie transmission, geographic capabilities,' +
                          ' etc), verification')
            labels.append('Contact angus@ozsolarwind.com for more information or alternative modelling' +
                          ' capabilities/suggestions needed')
            labels.append('We acknowledge US DOE, NASA and OpenStreetMap as follows (press Ctrl+I, menu option' +
                          ' Help -> About, for more details):')
            labels.append('SIREN uses System Advisor Model (SAM) modules for energy calculations. SAM is provided' +
                          ' by NREL for the US DOE')
            labels.append('SIREN may use weather data obtained from MERRA-2 data, a NASA atmospheric data set')
            labels.append('SIREN may use a map derived from OpenStreetMap (MapQuest) Open Aerial Tiles')
            for i in range(len(labels)):
                labl = QtWidgets.QLabel(labels[i])
                labl.setWordWrap(True)
                if i == 0:
                    labl.setFont(bold)
                self.grid.addWidget(labl)
        frame = QtWidgets.QFrame()
        frame.setLayout(self.grid)
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(frame)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.scroll)
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.close)
        QtWidgets.QShortcut(QtGui.QKeySequence('F1'), self, self.help)
        QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+I'), self, self.about)
        screen = QtWidgets.QDesktopWidget().availableGeometry()
        if sys.platform == 'win32' or sys.platform == 'cygwin':
            pct = 0.85
        else:
            pct = 0.90
        h = int(screen.height() * pct)
        self.resize(pixmap.width() + 55, h)
        frameGm = self.frameGeometry()
        screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
        tlPoint = QtWidgets.QApplication.desktop().availableGeometry(screen).topLeft()
        frameGm.moveTopLeft(tlPoint)
        self.move(frameGm.topLeft())
        self.setWindowTitle('SIREN - Credits')
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        if self.restorewindows:
            try:
                rw = config.get('Windows', 'credits_size').split(',')
                self.resize(int(rw[0]), int(rw[1]))
                mp = config.get('Windows', 'credits_pos').split(',')
                self.move(int(mp[0]), int(mp[1]))
            except:
                pass
        self.show()

    @QtCore.pyqtSlot()
    def help(self):
        self.procStart.emit('help')

    def about(self):
        self.procStart.emit('about')

    def exit(self):
        self.be_open = False
        self.close()

    def closeEvent(self, event):
        if self.be_open:
            reply = QtWidgets.QMessageBox.question(self, 'SIREN Credits',
                    'Do you want to close Credits window?', QtWidgets.QMessageBox.Yes |
                    QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
            if reply == QtWidgets.QMessageBox.Yes:
                pass
            else:
                event.ignore()
                return
        if self.restorewindows:
            updates = {}
            lines = []
            add = int((self.frameSize().width() - self.size().width()) / 2)  # need to account for border
            lines.append('credits_pos=%s,%s' % (str(self.pos().x() + add), str(self.pos().y() + add)))
            lines.append('credits_size=%s,%s' % (str(self.width()), str(self.height())))
            updates['Windows'] = lines
            editini.SaveIni(updates)
        if self.be_open:
            self.procStart.emit('goodbye')
        event.accept() def fileVersion(program=None, year=False):
    ver = '?'
    ver_yr = '????'
    if program == None:
        check = sys.argv[0]
    else:
        s = program.rfind('.')
        if s > 0 and program[s:] == '.html':
            check = program
        elif s < len(program) - 4:
            check = program + sys.argv[0][sys.argv[0].rfind('.'):]
        else:
            check = program
    if check[-3:] == '.py':
        try:
            modtime = datetime.fromtimestamp(os.path.getmtime(check))
            ver = '3.0.%04d.%d%02d' % (modtime.year, modtime.month, modtime.day)
            ver_yr = '%04d' % modtime.year
        except:
            pass
    elif check[-5:] == '.html':
        try:
            modtime = datetime.fromtimestamp(os.path.getmtime(check))
            ver = '3.0.%04d.%d%02d' % (modtime.year, modtime.month, modtime.day)
            ver_yr = '%04d' % modtime.year
        except:
            pass
    else:
        if sys.platform == 'win32' or sys.platform == 'cygwin':
            try:
                if check.find('\\') >= 0:  # if full path
                    info = GetFileVersionInfo(check, '\\')
                else:
                    info = GetFileVersionInfo(os.getcwd() + '\\' + check, '\\')
                ms = info['ProductVersionMS']
              #  ls = info['FileVersionLS']
                ls = info['ProductVersionLS']
                ver = str(HIWORD(ms)) + '.' + str(LOWORD(ms)) + '.' + str(HIWORD(ls)) + '.' + str(LOWORD(ls))
                ver_yr = str(HIWORD(ls))
            except:
                try:
                    info = os.path.getmtime(os.getcwd() + '\\' + check)
                    ver = '3.0.' + datetime.fromtimestamp(info).strftime('%Y.%m%d')
                    ver_yr = datetime.fromtimestamp(info).strftime('%Y')
                    if ver[9] == '0':
                        ver = ver[:9] + ver[10:]
                except:
                    pass
    if year:
        return ver_yr
    else:
        return ver def getModelFile(*args):
    def set_models_locn(ini_file):
        app = QtWidgets.QApplication.instance()
        if app is None:
            app = QtWidgets.QApplication(sys.argv)
        if sys.platform == 'win32' or sys.platform == 'cygwin':
            fldr_div = '\\'
        else:
            fldr_div = '/'
        siren_dir = '.' + fldr_div
        newdir = QtWidgets.QFileDialog.getExistingDirectory(None,
                 'SIREN. Choose location for SIREN Model (Preferences) files',
                 '', QtWidgets.QFileDialog.ShowDirsOnly)
        if newdir != '':
            mydir = os.path.abspath(__file__)
            if sys.platform == 'win32' or sys.platform == 'cygwin':
                newdir = newdir.replace('/', fldr_div)
            mydir = mydir[:mydir.rfind(fldr_div)]
            that_len = len(commonprefix([newdir, mydir], chr=fldr_div))
            if that_len > 0:
                bits = newdir[that_len:].split(fldr_div)
                if that_len < len(mydir): # go up the tree
                    pfx = ('..' + fldr_div) * (len(bits) - 1)
                else:
                    pfx = ''
                siren_dir = pfx + newdir[that_len + 1:]
                if siren_dir == '':
                    siren_dir = '.'
                if siren_dir[-1] != fldr_div:
                    siren_dir += fldr_div
            else:
                siren_dir = newdir
            mf = open('siren_models_location.txt', 'w')
            mf.write(siren_dir)
            mf.close()
            updir = mydir[:mydir.rfind(fldr_div) + 1]
            if os.path.exists(updir + 'siren_sample') \
              and os.path.exists(mydir + fldr_div + 'SIREN.ini') \
              and not os.path.exists(siren_dir + 'SIREN.ini'): # has the sample
                msgbox = QtWidgets.QMessageBox()
                msgbox.setWindowTitle('SIREN - Copy File')
                msgbox.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
                msgbox.setText('SIREN sample_files folder found')
                msgbox.setInformativeText('Do you want to copy the sample SIREN Model (Y)?')
                msgbox.setDetailedText('It seems you have the siren sample files. ' + \
                    "If you reply 'Y'es the sample preferences file, SIREN.ini, will " + \
                    'be copied to '+ siren_dir + '.')
                msgbox.setIcon(QtWidgets.QMessageBox.Question)
                msgbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
                reply = msgbox.exec_()
                if reply == QtWidgets.QMessageBox.Yes:
                    if os.path.exists(siren_dir + 'SIREN.ini'):
                        if os.path.exists(siren_dir + 'SIREN.ini~'):
                            os.remove(siren_dir + 'SIREN.ini~')
                        os.rename(siren_dir + 'SIREN.ini', siren_dir + 'SIREN.ini~')
                    copy(mydir + fldr_div +  'SIREN.ini', siren_dir + 'SIREN.ini')
        return siren_dir + ini_file

    siren_dir = ''
    if len(args) > 0:
        ini_file = args[0]
        if os.path.exists('siren_models_location.txt'):
            mf = open('siren_models_location.txt', 'r')
            siren_dir = mf.readline()
            mf.close()
            siren_dir = siren_dir.strip('\n')
            siren_dir = siren_dir + ini_file
            return siren_dir
        else:
            return ini_file
    ini_file = ''
    if os.path.exists('siren_models_location.txt'):
        mf = open('siren_models_location.txt', 'r')
        siren_dir = mf.readline()
        mf.close()
        siren_dir = siren_dir.strip('\n')
        if not(os.path.exists(siren_dir)):
            app = QtWidgets.QApplication.instance()
            if app is None:
                app = QtWidgets.QApplication(sys.argv)
            msgbox = QtWidgets.QMessageBox()
            msgbox.setWindowTitle("SIREN - Can't find Models")
            msgbox.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
            msgbox.setText('SIREN Models folder missing')
            msgbox.setInformativeText('Do you want to reset the Models location (Y)?')
            msgbox.setDetailedText("Can't find " + siren_dir + '. ' + \
                "If you reply 'Y'es you can choose a new location for the Models.")
            msgbox.setIcon(QtWidgets.QMessageBox.Question)
            msgbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
            reply = msgbox.exec_()
            if reply == QtWidgets.QMessageBox.Yes:
                siren_dir = set_models_locn(ini_file)
            else:
                sys.exit(8)
        siren_dir = siren_dir + ini_file
    else:
        siren_dir = set_models_locn(ini_file)
    return siren_dir def dust(pyd, pxd, y1d, x1d, y2d, x2d):   # debug
    if y1d == y2d and x1d == x2d:
        return [-1]
    px = radians(pxd)
    py = radians(pyd)
    x1 = radians(x1d)
    y1 = radians(y1d)
    x2 = radians(x2d)
    y2 = radians(y2d)
    p_x = x2 - x1
    p_y = y2 - y1
    something = p_x * p_x + p_y * p_y
    u = ((px - x1) * p_x + (py - y1) * p_y) / float(something)
    if u > 1:
        u = 1
    elif u < 0:
        u = 0
    x = x1 + u * p_x
    y = y1 + u * p_y
    dx = x - px
    dy = y - py
    dist = sqrt(dx * dx + dy * dy)
    return [round(abs(dist) * RADIUS, 3), round(degrees(y), 6), round(degrees(x), 6)] def getParents(aparents):
    parents = []
    for key, value in aparents:
        for key2, value2 in aparents:
            if key2 == key:
                continue
            value = value.replace(key2, value2)
        for key2, value2 in parents:
            if key2 == key:
                continue
            value = value.replace(key2, value2)
        parents.append((key, value))
    return parents class Resource(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, year=None, scene=None):
        super(Resource, self).__init__()
        self.year = year
        self.scene = scene
        self.resource_items = []
        self.be_open = True
        self.colours = {'dhi': ['DHI (Diffuse)', '#717100', '#ffff00', None],
                        'dni': ['DNI (Normal)', '#734c00', '#ff5500', None],
                        'ghi': ['GHI (Direct)', '#8b0000', '#ff0000', None],
                        'temp': ['Temperature', '#0d52e7', '#e8001f', None],
                        'wind': ['Wind Speed', '#82b2ff', '#0000b6', None],
                        'wind50': ['Wind @ 50m', '#82b2ff', '#0000b6', None]}
        self.hourly = False
        self.daily = False
        self.ignore = False
        self.detail = ['Daily By Month']
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        if self.year is None:
            try:
                self.year = config.get('Base', 'year')
            except:
                pass
        self.map = ''
        try:
            tmap = config.get('Map', 'map_choice')
        except:
            tmap = ''
      # get default colours
        for key in self.colours:
            try:
                self.colours[key][1] = config.get('Colors', key + '_low')
            except:
                pass
            try:
                self.colours[key][2] = config.get('Colors', key + '_high')
            except:
                pass
        if tmap != '':
          # get this maps colours
            for key in self.colours:
                try:
                    self.colours[key][1] = config.get('Colors' + tmap, key + '_low')
                    self.map = tmap
                except:
                    pass
                try:
                    self.colours[key][2] = config.get('Colors' + tmap, key + '_high')
                    self.map = tmap
                except:
                    pass
        self.seasons = []
        self.periods = []
        try:
            items = config.items('Power')
            for item, values in items:
                if item[:6] == 'season':
                    if item == 'season':
                        continue
                    bits = values.split(',')
                    self.seasons.append(bits[0])
                elif item[:6] == 'period':
                    if item == 'period':
                        continue
                    bits = values.split(',')
                    self.periods.append(bits[0])
        except:
            pass
        if len(self.seasons) == 0:
            self.seasons = ['Summer', 'Autumn', 'Winter', 'Spring']
        if len(self.periods) == 0:
            self.periods = ['Winter', 'Summer']
        for i in range(len(self.periods)):
            for j in range(len(self.seasons)):
                if self.periods[i] == self.seasons[j]:
                    self.periods[i] += '2'
                    break
        try:
            self.helpfile = config.get('Files', 'help')
        except:
            self.helpfile = ''
        try:
            opacity = float(config.get('View', 'resource_opacity'))
        except:
            opacity = .5
        try:
            period = config.get('View', 'resource_period')
        except:
            period = self.year
        try:
            steps = int(config.get('View', 'resource_steps'))
        except:
            steps = 2
        try:
            max_steps = int(config.get('View', 'resource_max_steps'))
        except:
            max_steps = 10
        try:
            variable = config.get('View', 'resource_variable')
        except:
            variable = self.colours['ghi'][0]
        try:
            variable = config.get('View', 'resource_rainfall')
            if variable.lower() in ['true', 'yes', 'on']:
                self.colours['rain'] = ['Rainfall', '#e6e7e6', '#005500', None]
        except:
            pass
        self.restorewindows = False
        try:
            rw = config.get('Windows', 'restorewindows')
            if rw.lower() in ['true', 'yes', 'on']:
                self.restorewindows = True
        except:
            pass
        yrf = rreplace(self.scene.resource_grid, '$YEAR$', self.year, 1)
        yrf = yrf.replace('$YEAR$', self.year)
        if not os.path.exists(yrf):
            self.be_open = False
            return
        mrf = rreplace(self.scene.resource_grid, '$YEAR$', self.year + '-01', 1)
        mrf = mrf.replace('$YEAR$', self.year)
        if os.path.exists(mrf):
            self.hourly = True
            self.detail.append('Hourly by Month')
        drf = rreplace(self.scene.resource_grid, '$YEAR$', self.year + '-01-01', 1)
        drf = drf.replace('$YEAR$', self.year)
        if os.path.exists(drf):
            self.daily = True
            self.detail.append('Hourly by Day')
        self.resource_file = ""
        self.the_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        self.mth_index = [0]
        for i in range(len(self.the_days) - 1):
            self.mth_index.append(self.mth_index[-1] + self.the_days[i] * 24)
        self.btn = []
        self.grid = QtWidgets.QGridLayout()
        row = 0
        self.detailCombo = QtWidgets.QComboBox()
        self.periodCombo = QtWidgets.QComboBox()
        self.dayCombo = QtWidgets.QComboBox()
        self.hourCombo = QtWidgets.QComboBox()
        for det in self.detail:
            self.detailCombo.addItem(det)
        if len(self.detail) > 1:
            self.grid.addWidget(QtWidgets.QLabel('Weather Detail:'), row, 0)
            self.grid.addWidget(self.detailCombo, row, 1, 1, 2)
            self.detailCombo.currentIndexChanged[str].connect(self.changeDetail)
            row += 1
        self.grid.addWidget(QtWidgets.QLabel('Weather Period:'), row, 0)
        self.periodCombo.currentIndexChanged[str].connect(self.periodChange)
        self.grid.addWidget(self.periodCombo, row, 1, 1, 2)
        self.dayCombo.currentIndexChanged[str].connect(self.periodChange)
        self.dayCombo.hide()
        self.grid.addWidget(self.dayCombo, row, 3, 1, 2)
        self.hourCombo.currentIndexChanged[str].connect(self.periodChange)
        self.hourCombo.hide()
        self.grid.addWidget(self.hourCombo, row, 5, 1, 3)
        row += 1
        prev = QtWidgets.QPushButton('<', self)
        width = prev.fontMetrics().boundingRect('<').width() + 10
        prev.setMaximumWidth(width)
        self.grid.addWidget(prev, row, 0)
        prev.clicked.connect(self.prevClicked)
        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider.valueChanged.connect(self.slideChanged)
        self.grid.addWidget(self.slider, row, 1, 1, 5)
        next = QtWidgets.QPushButton('>', self)
        width = next.fontMetrics().boundingRect('>').width() + 10
        next.setMaximumWidth(width)
        self.grid.addWidget(next, row, 7)
        next.clicked.connect(self.nextClicked)
        row += 1
        self.do_loop = False
        self.grid.addWidget(QtWidgets.QLabel('Period Loop (secs):'), row, 0)
        self.loopSpin = QtWidgets.QDoubleSpinBox()
        self.loopSpin.setRange(0., 10.)
        self.loopSpin.setDecimals(1)
        self.loopSpin.setSingleStep(.2)
        self.loopSpin.setValue(0.)
        self.loopSpin.valueChanged[str].connect(self.loopChanged)
        self.grid.addWidget(self.loopSpin, row, 1, 1, 2)
        self.loop = QtWidgets.QPushButton('Loop', self)
        self.grid.addWidget(self.loop, row, 3, 1, 4)
        self.loop.clicked.connect(self.loopClicked)
        row += 1
        self.grid.addWidget(QtWidgets.QLabel('Weather Variable:'), row, 0)
        self.whatCombo = QtWidgets.QComboBox()
        for key in sorted(self.colours):
            self.whatCombo.addItem(self.colours[key][0])
            if variable == self.colours[key][0]:
                self.whatCombo.setCurrentIndex(self.whatCombo.count() - 1)
        self.whatCombo.currentIndexChanged[str].connect(self.periodChange)
        self.grid.addWidget(self.whatCombo, row, 1, 1, 2)
        if len(self.detail) > 1:
            self.detailCombo.currentIndexChanged[str].connect(self.changeDetail)
        row += 1
        self.grid.addWidget(QtWidgets.QLabel('Colour Steps:'), row, 0)
        self.stepSpin = QtWidgets.QSpinBox()
        self.stepSpin.setRange(0, max_steps)
        self.stepSpin.setValue(steps)
        self.stepSpin.valueChanged[str].connect(self.stepChanged)
        self.grid.addWidget(self.stepSpin, row, 1, 1, 2)
        row += 1
        self.grid.addWidget(QtWidgets.QLabel('Opacity:'), row, 0)
        self.opacitySpin = QtWidgets.QDoubleSpinBox()
        self.opacitySpin.setRange(0, 1.)
        self.opacitySpin.setDecimals(2)
        self.opacitySpin.setSingleStep(.05)
        self.opacitySpin.setValue(opacity)
        self.opacitySpin.valueChanged[str].connect(self.opacityChanged)
        self.grid.addWidget(self.opacitySpin, row, 1, 1, 2)
        self.grid.addWidget(QtWidgets.QLabel('Grid only:'), row, 3)
        self.grid_only = QtWidgets.QCheckBox()
        self.grid_only.setCheckState(QtCore.Qt.Unchecked)
        self.grid.addWidget(self.grid_only, row, 4)
        row += 1
        self.grid.addWidget(QtWidgets.QLabel('Low Colour'), row, 1)
        self.grid.addWidget(QtWidgets.QLabel('High Colour'), row, 2)
        row += 1
        self.gradients = []
        value = self.palette().color(QtGui.QPalette.Window)
        self.first_row = row
        for key in sorted(self.colours):
            self.gradients.append([])
            for i in range(self.stepSpin.maximum() + 1):
                self.gradients[-1].append(QtWidgets.QLabel('__'))
                self.gradients[-1][-1].setStyleSheet('QLabel {background-color: %s; color: %s;}' %
                                                    (value.name(), value.name()))
                self.grid.addWidget(self.gradients[-1][-1], row, i + 3)
            row += 1
        row = self.first_row
        for key in sorted(self.colours):
            self.grid.addWidget(QtWidgets.QLabel(self.colours[key][0]), row, 0)
            if self.colours[key][1] != '':
                value = QtGui.QColor(self.colours[key][1])
                self.btn.append(QtWidgets.QPushButton(key + '_1', self))
                self.btn[-1].clicked.connect(self.colourChanged)
                self.btn[-1].setStyleSheet('QPushButton {background-color: %s; color: %s;}' %
                                 (value.name(), value.name()))
                self.grid.addWidget(self.btn[-1], row, 1)
            if self.colours[key][2] != '':
                value = QtGui.QColor(self.colours[key][2])
                self.btn.append(QtWidgets.QPushButton(key + '_2', self))
                self.btn[-1].clicked.connect(self.colourChanged)
                self.btn[-1].setStyleSheet('QPushButton {background-color: %s; color: %s;}' %
                                 (value.name(), value.name()))
                self.grid.addWidget(self.btn[-1], row, 2)
            if self.stepSpin.value() > 0:
                colors = gradient(self.colours[key][1], self.colours[key][2], self.stepSpin.value())
                for i in range(len(colors)):
                    value = QtGui.QColor(colors[i])
                    self.gradients[row - self.first_row][i].setStyleSheet('QLabel {background-color: %s; color: %s;}' %
                                    (value.name(), value.name()))
            row += 1
        quit = QtWidgets.QPushButton('Quit', self)
        self.grid.addWidget(quit, row, 0)
        quit.clicked.connect(self.quitClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.quitClicked)
        doit = QtWidgets.QPushButton('Show', self)
        self.grid.addWidget(doit, row, 1)
        doit.clicked.connect(self.showClicked)
        hide = QtWidgets.QPushButton('Hide', self)
        self.grid.addWidget(hide, row, 2)
        hide.clicked.connect(self.hideClicked)
        save = QtWidgets.QPushButton('Save', self)
        self.grid.addWidget(save, row, 3, 1, 4)
        save.clicked.connect(self.saveClicked)
        help = QtWidgets.QPushButton('Help', self)
        self.grid.addWidget(help, row, 7, 1, 4)
        help.clicked.connect(self.helpClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('F1'), self, self.helpClicked)
        frame = QtWidgets.QFrame()
        frame.setLayout(self.grid)
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(frame)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.scroll)
        self.setWindowTitle('SIREN - Renewable Resource Overlay')
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        self.stepChanged('a')
        if sys.platform == 'win32' or sys.platform == 'cygwin':
            move_right = False
        else:
            move_right = True
        if self.restorewindows:
            try:
                rw = config.get('Windows', 'resource_size').split(',')
                self.resize(int(rw[0]), int(rw[1]))
                mp = config.get('Windows', 'resource_pos').split(',')
                self.move(int(mp[0]), int(mp[1]))
                move_right = False
            except:
                pass
        if move_right:
            frameGm = self.frameGeometry()
            screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
            trPoint = QtWidgets.QApplication.desktop().availableGeometry(screen).topRight()
            frameGm.moveTopRight(trPoint)
            self.move(frameGm.topRight())
        QtWidgets.QShortcut(QtGui.QKeySequence('pgup'), self, self.prevClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('pgdown'), self, self.nextClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl++'), self, self.nextClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+-'), self, self.prevClicked)
        self.setPeriod()
        self.resourceGrid()
        self.show()

    def loopChanged(self, val):
        return

    def changeDetail(self):
        self.setPeriod()
        self.resourceGrid()

    def helpClicked(self):
        dialog = displayobject.AnObject(QtWidgets.QDialog(), self.helpfile, title='Resource Help', section='resource')
        dialog.exec_()

    def nextClicked(self):
        if self.slider.value() == self.slider.maximum():
            self.slider.setValue(0)
        else:
            self.slider.setValue(self.slider.value() + 1)

    def prevClicked(self):
        if self.slider.value() == self.slider.minimum():
            self.slider.setValue(self.slider.maximum())
        else:
            self.slider.setValue(self.slider.value() - 1)

    def slideChanged(self, val):
        self.ignore = True
        if self.detailCombo.currentText() == 'Daily By Month':
            self.periodCombo.setCurrentIndex(val)
        else:
            period = divmod(val, 24)
            if self.detailCombo.currentText() == 'Hourly by Month':
                self.periodCombo.setCurrentIndex(period[0])
            elif self.detailCombo.currentText() == 'Hourly by Day':
                for m in range(len(self.mth_index) -1, -1, -1):
                    if val >= self.mth_index[m]:
                        break
                self.periodCombo.setCurrentIndex(m)
                period = divmod(val - self.mth_index[m], 24)
                if m != self.dayCombo.currentIndex:
                    self.setDayItems(m)
                self.dayCombo.setCurrentIndex(period[0])
            self.hourCombo.setCurrentIndex(period[1])
        self.ignore = False
        self.resourceGrid()

    def loopClicked(self):
        if self.loop.text() == 'Stop':
            self.do_loop = False
            self.scene.exitLoop = False
            self.detailCombo.setEnabled(True)
            self.periodCombo.setEnabled(True)
            self.dayCombo.setEnabled(True)
            self.hourCombo.setEnabled(True)
            self.loop.setText('Loop')
        else:
            self.do_loop = True
            self.detailCombo.setEnabled(False)
            self.periodCombo.setEnabled(False)
            self.dayCombo.setEnabled(False)
            self.hourCombo.setEnabled(False)
            self.loop.setText('Stop')
            self.periodChange()

    def periodChange(self, value=None):
        if self.ignore:
            return
        if self.periodCombo.currentIndex() < 0:
            per_ndx = 0
        else:
            per_ndx = self.periodCombo.currentIndex()
        if self.detailCombo.currentText() != 'Hourly by Day' or self.dayCombo.currentIndex() < 0:
            day_ndx = 0
        else:
            day_ndx = self.dayCombo.currentIndex()
            if day_ndx > self.the_days[per_ndx] - 1:
                day_ndx = self.the_days[per_ndx] - 1
        if self.hourCombo.currentIndex() < 0:
            hr_ndx = 0
        else:
            hr_ndx = self.hourCombo.currentIndex()
        if self.detailCombo.currentText() == 'Daily By Month':
            val = per_ndx
        elif self.detailCombo.currentText() == 'Hourly by Month':
            val = per_ndx * 24 + hr_ndx
        elif self.detailCombo.currentText() == 'Hourly by Day':
            val = day_ndx * 24 + self.mth_index[per_ndx] + hr_ndx
        while val <= self.slider.maximum():
            self.slider.setValue(val)
            QtCore.QCoreApplication.processEvents()
            QtCore.QCoreApplication.flush()
            if not self.do_loop or self.scene.exitLoop:
                break
            val += 1
            if val < self.slider.maximum():
                self.slider.setValue(val)
        if self.do_loop:
            self.do_loop = False
            self.detailCombo.setEnabled(True)
            self.periodCombo.setEnabled(True)
            self.dayCombo.setEnabled(True)
            self.hourCombo.setEnabled(True)
            self.loop.setText('Loop')
            if not self.scene.exitLoop:
                self.slider.setValue(0)
        self.scene.exitLoop = False

    def setDayItems(self, mth):
        if self.dayCombo.count() > 0:
            self.dayCombo.clear()
        if mth < 0 or mth >= len(self.the_days):
            rnge = 31
        else:
            rnge = self.the_days[mth]
        for d in range(rnge):
            self.dayCombo.addItem('{0:02d}'.format(d + 1))

    def setPeriod(self):
        if self.periodCombo.count() > 0:
            self.periodCombo.clear()
        if self.dayCombo.count() > 0:
            self.dayCombo.clear()
        if self.hourCombo.count() > 0:
            self.hourCombo.clear()
        if self.detailCombo.currentText() == 'Daily By Month':
            self.periodCombo.addItem(self.year)
        for i in range(12):
            self.periodCombo.addItem(self.year + '-' + '{0:02d}'.format(i + 1))
        if self.detailCombo.currentText() == 'Daily By Month':
            for i in range(len(self.seasons)):
                self.periodCombo.addItem(self.year + '-' + self.seasons[i])
            for i in range(len(self.periods)):
                self.periodCombo.addItem(self.year + '-' + self.periods[i])
            self.dayCombo.hide()
            self.hourCombo.hide()
            self.slider.setMaximum(self.periodCombo.count() - 1)
        else:
            for j in range(24):
                self.hourCombo.addItem('{0:02d}'.format(j + 1) + ':00')
                self.hourCombo.show()
            if self.detailCombo.currentText() == 'Hourly by Month':
                self.slider.setMaximum(self.periodCombo.count() * 24 - 1)
                self.dayCombo.hide()
            elif self.detailCombo.currentText() == 'Hourly by Day':
                self.setDayItems(0)
                self.slider.setMaximum(365 * 24 - 1)
                self.dayCombo.show()
                self.dayCombo.setCurrentIndex(0)
            self.hourCombo.show()
            self.hourCombo.setCurrentIndex(0)
        self.periodCombo.setCurrentIndex(0)
        self.slider.setValue(0)

    def opacityChanged(self, val):
        return
      #  print '(522)', self.opacitySpin.value(), val
      #  self.resourceGrid()

    def stepChanged(self, val):
        value = self.palette().color(QtGui.QPalette.Window)
        for i in range(len(self.gradients)):
            for j in range(len(self.gradients[i])):
                self.gradients[i][j].setStyleSheet('QLabel {background-color: %s; color: %s;}' %
                                                    (value.name(), value.name()))
        if self.stepSpin.value() > 0:
            row = self.first_row
            for key in sorted(self.colours):
                self.colours[key][3] = gradient(self.colours[key][1], self.colours[key][2], self.stepSpin.value())
                for i in range(len(self.colours[key][3])):
                    value = QtGui.QColor(self.colours[key][3][i])
                    value.setAlphaF(self.opacitySpin.value())
                    self.gradients[row - self.first_row][i].setStyleSheet(
                                  'QLabel {background-color: %s; color: %s; opacity: 50}' %
                                  (value.name(), value.name()))
                    val = []
                    for j in range(3):
                        val.append(str(int(self.colours[key][3][i][j * 2 + 1:j * 2 + 3], base=16)))
                    val.append(str(self.opacitySpin.value() * 100))
                    it = 'QLabel {background-color: rgba(%s,%s,%s,%s%%); color: rgba(%s,%s,%s,%s%%)}' % \
                         (val[0], val[1], val[2], val[3], val[0], val[1], val[2], val[3])
                    self.gradients[row - self.first_row][i].setStyleSheet(it)
                row += 1
        self.resourceGrid()

    @QtCore.pyqtSlot()
    def exit(self):
        self.be_open = False
        self.close()

    def closeEvent(self, event):
     #   self.clear_Resource()
        if self.restorewindows:
            updates = {}
            lines = []
            add = int((self.frameSize().width() - self.size().width()) / 2)   # need to account for border
            lines.append('resource_pos=%s,%s' % (str(self.pos().x() + add), str(self.pos().y() + add)))
            lines.append('resource_size=%s,%s' % (str(self.width()), str(self.height())))
            updates['Windows'] = lines
            SaveIni(updates)
        if self.do_loop:
            self.scene.exitLoop = True
        if self.be_open:
            self.procStart.emit('goodbye')
        self.hideClicked()
        event.accept()

    def quitClicked(self):
        self.close()

    def showClicked(self):
        self.resourceGrid()

    def hideClicked(self):
        self.clear_Resource()

    def saveClicked(self):
        updates = {}
        colour_lines = []
        for key in self.colours:
            colour_lines.append('%s_high=%s' % (key, self.colours[key][2]))
            colour_lines.append('%s_low=%s' % (key, self.colours[key][1]))
        updates['Colors' + self.map] = colour_lines
        view_lines = []
        view_lines.append('resource_opacity=%s' % str(self.opacitySpin.value()))
        view_lines.append('resource_period=$YEAR$%s' % self.periodCombo.currentText()[4:])
        view_lines.append('resource_steps=%s' % str(self.stepSpin.value()))
        view_lines.append('resource_variable=%s' % self.whatCombo.currentText())
        updates['View'] = view_lines
        SaveIni(updates)

    def colourChanged(self):
        sender = self.sender().text().split('_')
        key = sender[0]
        ndx = int(sender[1])
        if self.colours[key][ndx] != '':
            value = QtGui.QColor(self.colours[key][ndx])
            col = QtWidgets.QColorDialog.getColor(value)
        else:
            col = QtWidgets.QColorDialog.getColor(QtGui.QColor(''))
        if col.isValid():
            self.colours[key][ndx] = col.name()
            for i in range(len(self.btn)):
                if self.btn[i] == self.sender():
                    self.btn[i].setStyleSheet('QPushButton {background-color: %s; color: %s;}' % (col.name(), col.name()))
                    break
            self.stepChanged('a')

    def clear_Resource(self):
        try:
            for i in range(len(self.resource_items)):
                self.scene.removeItem(self.resource_items[i])
            del self.resource_items
        except:
            pass

    def resourceGrid(self):
        def in_map(a_min, a_max, b_min, b_max):
            return (a_min <= b_max) and (b_min <= a_max)
        self.clear_Resource()
        for key in self.colours:
            if self.colours[key][0] == self.whatCombo.currentText():
                colours = self.colours[key][3]
                break
        period = self.periodCombo.currentText()
        if self.detailCombo.currentText() == 'Daily By Month':
            pass
        else:
            if self.detailCombo.currentText() == 'Hourly by Day':
                period += '-' + self.dayCombo.currentText()
            period += '_' + self.hourCombo.currentText()
        variable = self.whatCombo.currentText()
        steps = self.stepSpin.value()
        opacity = self.opacitySpin.value()
        i = period.find('_')
        if i > 0:
            new_file = rreplace(self.scene.resource_grid, '$YEAR$', period[:i], 1)
            new_file = new_file.replace('$YEAR$', period[:4])
        else:
            new_file = self.scene.resource_grid.replace('$YEAR$', period[:4])
        self.resource_items = []
        if new_file[-4:] == '.xls' or new_file[-5:] == '.xlsx':
            if new_file != self.resource_file:
                if os.path.exists(new_file):
                    self.resource_var = {}
                    workbook = xlrd.open_workbook(new_file)
                    self.resource_worksheet = workbook.sheet_by_index(0)
                    num_cols = self.resource_worksheet.ncols - 1
#                   get column names
                    curr_col = -1
                    while curr_col < num_cols:
                        curr_col += 1
                        self.resource_var[self.resource_worksheet.cell_value(0, curr_col)] = curr_col
                    self.resource_file = new_file
                else:
                    return
            num_rows = self.resource_worksheet.nrows - 1
            num_cols = self.resource_worksheet.ncols - 1
            lo_valu = 99999.
            hi_valu = 0.
            calc_minmax = True
            cells = []
            curr_row = 1
            if self.resource_worksheet.cell_value(curr_row, self.resource_var['Period']) == 'Min.' and \
              self.resource_worksheet.cell_value(curr_row + 1, self.resource_var['Period']) == 'Max.':
                calc_minmax = False
                lo_valu = self.resource_worksheet.cell_value(curr_row, self.resource_var[variable])
                hi_valu = self.resource_worksheet.cell_value(curr_row + 1, self.resource_var[variable])
                curr_row += 1
            while curr_row < num_rows:
                curr_row += 1
                a_lat = float(self.resource_worksheet.cell_value(curr_row, self.resource_var['Latitude']))
                a_lon = float(self.resource_worksheet.cell_value(curr_row, self.resource_var['Longitude']))
                if in_map(a_lat - 0.25, a_lat + 0.25, self.scene.map_lower_right[0],
                          self.scene.map_upper_left[0]) \
                  and in_map(a_lon - 0.3333, a_lon + 0.3333,
                          self.scene.map_upper_left[1], self.scene.map_lower_right[1]):
                    try:
                        if self.resource_worksheet.cell_value(curr_row, self.resource_var['Period']) == period:
                            cells.append([float(self.resource_worksheet.cell_value(curr_row, self.resource_var['Latitude'])),
                                         float(self.resource_worksheet.cell_value(curr_row, self.resource_var['Longitude'])),
                                         self.resource_worksheet.cell_value(curr_row, self.resource_var[variable])])
                        if calc_minmax:
                            if self.resource_worksheet.cell_value(curr_row, self.resource_var[variable]) < lo_valu:
                                lo_valu = self.resource_worksheet.cell_value(curr_row, self.resource_var[variable])
                            if self.resource_worksheet.cell_value(curr_row, self.resource_var[variable]) > hi_valu:
                                hi_valu = self.resource_worksheet.cell_value(curr_row, self.resource_var[variable])
                    except:
                        pass
        else:
            if os.path.exists(new_file):
                resource = open(new_file)
                things = csv.DictReader(resource)
                for cell in things:
                    a_lat = float(cell['Latitude'])
                    a_lon = float(cell['Longitude'])
                    if in_map(a_lat - 0.25, a_lat + 0.25, self.scene().map_lower_right[0],
                              self.scene().map_upper_left[0]) \
                      and in_map(a_lon - 0.3333, a_lon + 0.3333,
                              self.scene().map_upper_left[1], self.scene().map_lower_right[1]):
                        if cell['Period'] == period:
                            cells.append(cell['Latitude'], cell['Longitude'], cell[variable])
                        if cell[variable] < lo_valu:
                            lo_valu = cell[variable]
                        if cell[variable] > hi_valu:
                            hi_valu = cell[variable]
                resource.close()
            else:
                return
        if steps > 0:
            incr = (hi_valu - lo_valu) / steps
        else:
            lo_colour = []
            hi_colour = []
            for i in range(3):
                lo_1 = int(colours[0][i * 2 + 1:i * 2 + 3], base=16)
                lo_colour.append(lo_1)
                hi_1 = int(colours[-1][i * 2 + 1:i * 2 + 3], base=16)
                hi_colour.append(hi_1)
        lo_per = 99999.
        hi_per = 0.
        lons = []
        lon_cell = .3125
        for cell in cells:
            if cell[1] not in lons:
                lons.append(cell[1])
        if len(lons) > 1:
            lons = sorted(lons)
            lon_cell = (lons[1] - lons[0]) / 2.
            del lons
        for cell in cells:
            p = self.scene.mapFromLonLat(QtCore.QPointF(cell[1] - lon_cell, cell[0] + .25))
            pe = self.scene.mapFromLonLat(QtCore.QPointF(cell[1] + lon_cell, cell[0] + .25))
            ps = self.scene.mapFromLonLat(QtCore.QPointF(cell[1] - lon_cell, cell[0] - .25))
            x_d = pe.x() - p.x()
            y_d = ps.y() - p.y()
            self.resource_items.append(QtWidgets.QGraphicsRectItem(p.x(), p.y(), x_d, y_d))
            if steps > 0:
                step = int(round((cell[2] - lo_valu) / incr))
                a_colour = QtGui.QColor(colours[step])
            else:
                colr = []
                pct = (cell[2] - lo_valu) / (hi_valu - lo_valu)
                for i in range(3):
                    colr.append(((hi_colour[i] - lo_colour[i]) * pct + lo_colour[i]) / 255.)
                a_colour = QtGui.QColor()
                a_colour.setRgbF(colr[0], colr[1], colr[2])
            if not self.grid_only.isChecked():
                if cell[2] >= lo_valu:
                    if cell[2] > 0 or variable == 'temp':
                        self.resource_items[-1].setBrush(a_colour)
            self.resource_items[-1].setPen(a_colour)
            self.resource_items[-1].setOpacity(opacity)
            self.resource_items[-1].setZValue(1)
            self.scene.addItem(self.resource_items[-1])
            if cell[2] < lo_per:
                lo_per = cell[2]
            if cell[2] > hi_per:
                hi_per = cell[2]
        QtCore.QCoreApplication.processEvents()
        QtCore.QCoreApplication.flush()
        if self.do_loop and not self.scene.exitLoop:
            if self.loopSpin.value() > 0:
                time.sleep(self.loopSpin.value())
    QtCore.QCoreApplication.processEvents()
    QtCore.QCoreApplication.flush() class FloatLegend(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, techdata, stations, flags):
        super(FloatLegend, self).__init__()
        self.stations = stations
        self.techdata = techdata
        self.flags = flags
        self.initUI()

    def initUI(self):
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.restorewindows = False
        try:
            rw = config.get('Windows', 'restorewindows')
            if rw.lower() in ['true', 'yes', 'on']:
                self.restorewindows = True
        except:
            pass
        self.be_open = True
        self.grid = QtWidgets.QGridLayout()
        tech_sizes = {}
        txt_lens = [10, 0]
        for st in self.stations:
            if st.technology[:6] == 'Fossil' and not self.flags[3]:
                continue
            if st.technology not in tech_sizes:
                tech_sizes[st.technology] = 0.
            if st.technology == 'Wind':
                tech_sizes[st.technology] += self.techdata[st.technology][0] * float(st.no_turbines) * pow((st.rotor * .001), 2)
            else:
                tech_sizes[st.technology] += self.techdata[st.technology][0] * float(st.capacity)
            txt_lens[0] = max(txt_lens[0], len(st.technology))
        total_area = 0.
        row = 0
        for key, value in iter(sorted(tech_sizes.items())):
            labl = QtWidgets.QLabel('__')
            colr = QtGui.QColor(self.techdata[key][1])
            labl.setStyleSheet('QLabel {background-color: %s; color: %s;}' % (colr.name(), colr.name()))
            self.grid.addWidget(labl, row, 0)
            self.grid.addWidget(QtWidgets.QLabel(key), row, 1)
            total_area += value
            area = '%s sq. Km' % '{:0.1f}'.format(value)
            txt_lens[1] = max(txt_lens[1], len(area))
            self.grid.addWidget(QtWidgets.QLabel(area), row, 2)
            self.grid.setRowStretch(row, 0)
            row += 1
        self.grid.setColumnStretch(0, 0)
        self.grid.setColumnStretch(1, 1)
        self.grid.addWidget(QtWidgets.QLabel('Total Area'), row, 1)
        area = '%s sq. Km' % '{:0.1f}'.format(total_area)
        txt_lens[1] = max(txt_lens[1], len(area))
        self.grid.addWidget(QtWidgets.QLabel(area), row, 2)
        self.grid.setRowStretch(row, 1)
        row += 1
        if self.flags[0]:
            txt = 'Circles show relative capacity in MW'
        elif self.flags[1]:
            txt = 'Circles show relative generation in MWh'
        else:
            txt = 'Station '
            if self.flags[2]:
                txt += 'Squares'
            else:
                txt += 'Circles'
            txt += ' show estimated area in sq. Km'
        if len(txt) > (txt_lens[0] + txt_lens[1]):
            txts = txt.split()
            txt = txts[0]
            ln = len(txt)
            for i in range(1, len(txts)):
                if ln + len(txts[i]) > (txt_lens[0] + txt_lens[1]):
                    txt += '\n'
                    txt += txts[i]
                    ln = len(txts[i])
                else:
                    txt += ' ' + txts[i]
                    ln += len(txts[i]) + 1
        self.grid.addWidget(QtWidgets.QLabel(txt), row, 1, 1, 2)
        self.grid.setRowStretch(row, 1)
        row += 1
        quit = QtWidgets.QPushButton('Quit', self)
        self.grid.addWidget(quit, row, 1)
        self.grid.setRowStretch(row, 1)
        self.grid.setVerticalSpacing(10)
        quit.clicked.connect(self.quitClicked)
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.quitClicked)
        frame = QtWidgets.QFrame()
        frame.setLayout(self.grid)
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(frame)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.scroll)
        self.setWindowTitle('SIREN - Legend')
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        screen = QtWidgets.QApplication.desktop().primaryScreen()
        scr_right = QtWidgets.QApplication.desktop().availableGeometry(screen).right()
        scr_bottom = QtWidgets.QApplication.desktop().availableGeometry(screen).bottom()
        win_width = self.sizeHint().width()
        win_height = self.sizeHint().height()
        if self.restorewindows:
            try:
                rw = config.get('Windows', 'legend_size').split(',')
                lst_width = int(rw[0])
                lst_height = int(rw[1])
                mp = config.get('Windows', 'legend_pos').split(',')
                lst_left = int(mp[0])
                lst_top = int(mp[1])
                lst_right = lst_left + lst_width
                lst_bottom = lst_top + lst_height
                screen = QtWidgets.QApplication.desktop().screenNumber(QtCore.QPoint(lst_left, lst_top))
                scr_right = QtWidgets.QApplication.desktop().availableGeometry(screen).right()
                scr_left = QtWidgets.QApplication.desktop().availableGeometry(screen).left()
                if lst_right < scr_right:
                    if (lst_right - win_width) >= scr_left:
                        scr_right = lst_right
                    else:
                        scr_right = scr_left + win_width
                scr_bottom = QtWidgets.QApplication.desktop().availableGeometry(screen).bottom()
                scr_top = QtWidgets.QApplication.desktop().availableGeometry(screen).top()
                if lst_bottom < scr_bottom:
                    if (lst_bottom - win_height) >= scr_top:
                        scr_bottom = lst_bottom
                    else:
                        scr_bottom = scr_top + win_height
            except:
                pass
        win_left = scr_right - win_width
        win_top = scr_bottom - win_height
        self.resize(win_width, win_height)
        self.move(win_left, win_top)
        self.show()

    @QtCore.pyqtSlot()
    def exit(self):
        self.be_open = False
        self.close()

    def closeEvent(self, event):
        if self.restorewindows:
            updates = {}
            lines = []
            add = int((self.frameSize().width() - self.size().width()) / 2)   # need to account for border
            lines.append('legend_pos=%s,%s' % (str(self.pos().x() + add), str(self.pos().y() + add)))
            lines.append('legend_size=%s,%s' % (str(self.width()), str(self.height())))
            updates['Windows'] = lines
            SaveIni(updates)
        if self.be_open:
            self.procStart.emit('goodbye')
        event.accept()

    def quitClicked(self):
        self.close() class FloatMenu(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)
    procAction = QtCore.pyqtSignal(QtWidgets.QAction)

    def __init__(self, menubar):
        super(FloatMenu, self).__init__()
        self.menubar = menubar
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.restorewindows = False
        try:
            rw = config.get('Windows', 'restorewindows')
            if rw.lower() in ['true', 'yes', 'on']:
                self.restorewindows = True
        except:
            pass
        try:
            open_menus = config.get('Windows', 'menu_open').split(',')
        except:
            open_menus = ''
        self.be_open = True
        self.menus = []
        for lvl1 in self.menubar.actions():
            if lvl1.text().find('&') >= 0:
                try:
                    self.menus.append([lvl1.text().replace('&', ''), lvl1.icon(), None, []])
                except:
                    self.menus.append([lvl1.text().replace('&', ''), None, None, []])
                try:
                    for lvl2 in lvl1.menu().actions():
                        if lvl2.text().find('&') >= 0:
                            try:
                                self.menus[-1][-1].append([lvl2.text().replace('&', ''), lvl2.icon(), None, []])
                            except:
                                self.menus[-1][-1].append([lvl2.text().replace('&', ''), None, None, []])
                            try:
                                for lvl3 in lvl2.menu().actions():
                                    self.menus[-1][-1][-1][-1].append([lvl3.text(),
                                        lvl3.icon(), lvl3, '3'])
                            except:
                                pass
                        else:
                            self.thisaction = lvl2
                            self.menus[-1][-1].append([lvl2.text(), lvl2.icon(), lvl2, '2'])
                except:
                    pass
            else:
                self.menus.append([lvl1.text(), lvl1.icon(), lvl1.actions()[0], '1'])
        self.grid = QtWidgets.QGridLayout()
        ctr = 0
        self.butn = []
        self.topmenus = {}
        self.buttons = {}
        for i in range(len(self.menus)):
            self.butn.append(QtWidgets.QPushButton(self.menus[i][0], self))
            self.butn[-1].setIcon(self.menus[i][1])
            self.butn[-1].setStyleSheet('QPushButton {color: #005fb6; border: 2px solid #e65900;' +
                               ' border-radius: 6px;}')
            self.butn[-1].clicked.connect(self.menuClicked)
            self.grid.addWidget(self.butn[-1], ctr, 0, 1, 3)
            ctr += 1
            self.topmenus[self.menus[i][0]] = [False, ctr, 0]
            if type(self.menus[i][3]) is list:
                for j in range(len(self.menus[i][3])):
                    self.butn.append(QtWidgets.QPushButton(self.menus[i][3][j][0], self))
                    self.butn[-1].setIcon(self.menus[i][3][j][1])
                #     self.butn[-1].setStyleSheet('QPushButton {Text-align:left;}')
                    self.butn[-1].clicked.connect(self.buttonClicked)
                    self.butn[-1].hide()
                    self.buttons[self.menus[i][3][j][0]] = self.menus[i][3][j][2]
                    self.grid.addWidget(self.butn[-1], ctr, 1, 1, 2)
                    ctr += 1
                    if type(self.menus[i][3][j][3]) is list:
                        for k in range(len(self.menus[i][3][j][3])):
                            self.butn.append(QtWidgets.QPushButton(self.menus[i][3][j][3][k][0], self))
                            self.butn[-1].setIcon(self.menus[i][3][j][3][k][1])
                          #   self.butn[-1].setStyleSheet('QPushButton {Text-align:left;}')
                            self.butn[-1].clicked.connect(self.buttonClicked)
                            self.butn[-1].hide()
                            self.buttons[self.menus[i][3][j][3][k][0]] = self.menus[i][3][j][3][k][2]
                            self.grid.addWidget(self.butn[-1], ctr, 2)
                            ctr += 1
            self.topmenus[self.menus[i][0]][2] = ctr
        quit = QtWidgets.QPushButton('Quit Menu', self)
        self.grid.addWidget(quit, ctr, 0)
        quit.clicked.connect(self.close)
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.close)
        for mnu in open_menus:
            strt = self.topmenus[mnu][1]
            stop = self.topmenus[mnu][2]
            for j in range(strt, stop):
                self.butn[j].show()
            self.topmenus[mnu][0] = True
        frame = QtWidgets.QFrame()
        frame.setLayout(self.grid)
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(frame)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.scroll)
        self.setWindowTitle('SIREN - Menu')
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        if self.restorewindows:
            try:
                rw = config.get('Windows', 'menu_size').split(',')
                self.resize(int(rw[0]), int(rw[1]))
                mp = config.get('Windows', 'menu_pos').split(',')
                self.move(int(mp[0]), int(mp[1]))
            except:
                pass
        self.show()

    def menuClicked(self, event):
        sender = self.sender()
        strt = self.topmenus[sender.text()][1]
        stop = self.topmenus[sender.text()][2]
        if self.topmenus[sender.text()][0]:
            for j in range(strt, stop):
                self.butn[j].hide()
            self.topmenus[sender.text()][0] = False
        else:
            for j in range(strt, stop):
                self.butn[j].show()
            self.topmenus[sender.text()][0] = True

 #   @QtCore.pyqtSlot(QtWidgets.QAction)
    def buttonClicked(self, event):
        sender = self.sender()
        self.thetext = sender.text()
        self.procAction.emit(self.buttons[sender.text()])

    @QtCore.pyqtSlot()
    def exit(self):
        self.be_open = False
        self.close()

    def text(self):
        return self.thetext

    def closeEvent(self, event):
        if self.restorewindows:
            updates = {}
            lines = []
            add = int((self.frameSize().width() - self.size().width()) / 2)   # need to account for border
            lines.append('menu_pos=%s,%s' % (str(self.pos().x() + add), str(self.pos().y() + add)))
            lines.append('menu_size=%s,%s' % (str(self.width()), str(self.height())))
            open_menus = ''
            for key in list(self.topmenus.keys()):
                if self.topmenus[key][0]:
                    open_menus += ',' + key
            if open_menus != '':
                lines.append('menu_open=%s' % open_menus[1:])
            updates['Windows'] = lines
            SaveIni(updates)
        if self.be_open:
            self.procStart.emit('goodbye')
        event.accept() class FloatStatus(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, mainwindow, scenarios_folder, scenarios, program='SIREN'):
        super(FloatStatus, self).__init__()
        self.mainwindow = mainwindow
        self.scenarios_folder = scenarios_folder
        self.scenarios = scenarios
        self.program = program
        if scenarios is None:
            self.full_log = False
        else:
            self.full_log = True
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            self.config_file = sys.argv[1]
        else:
            self.config_file = getModelFile('SIREN.ini')
        config.read(self.config_file)
        self.restorewindows = False
        self.logged = False
        try:
            rw = config.get('Windows', 'restorewindows')
            if rw.lower() in ['true', 'yes', 'on']:
                self.restorewindows = True
        except:
            pass
        self.log_status = True
        try:
            rw = config.get('Windows', 'log_status')
            if rw.lower() in ['false', 'no', 'off']:
                self.log_status = False
        except:
            pass
        self.be_open = True
        max_line = 0
        lines1 = ''
        lines2 = ''
        max_line = 0
        line_cnt1 = 1
        line_cnt2 = 0
        if self.full_log:
            try:
                for line in self.scenarios:
                    lines1 += line[0] + '\n'
                    line_cnt1 += 1
                    if len(line[0]) > max_line:
                        max_line = len(line[0])
                if self.log_status or not self.log_status:
                    ssc_api = ssc.API()
                    comment = 'SAM SDK Core: Version = %s. Build info = %s.' \
                              % (ssc_api.version(), ssc_api.build_info().decode())
                    line = '%s. SIREN log started\n          Preference File: %s' + \
                           '\n          Working directory: %s' + \
                           '\n          Scenarios folder: %s\n          %s'
                    lines2 = line % (QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(), 'hh:mm:ss'), \
                             self.config_file, os.getcwd(), self.scenarios_folder, comment)
                    line_cnt2 = 1
                    if len(lines2) > max_line:
                        max_line = len(lines2)
                else:
                    line_cnt2 = 0
            except:
                pass
        else:
            line = '%s. %s log started\n          Preference File: %s' + \
                   '\n          Working directory: %s' + \
                   '\n          Scenarios folder: %s'
            lines2 = line % (QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(), 'hh:mm:ss'), \
                     self.program, self.config_file, os.getcwd(), self.scenarios_folder)
            line_cnt2 = 1
            max_line = len(lines2)
        self.saveButton = QtWidgets.QPushButton(self.tr('Save Log'))
        self.saveButton.clicked.connect(self.save)
        self.quitButton = QtWidgets.QPushButton('Quit')
        self.quitButton.clicked.connect(self.close)
        QtWidgets.QShortcut(QtGui.QKeySequence('q'), self, self.close)
        buttonLayout = QtWidgets.QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(self.quitButton)
        buttonLayout.addWidget(self.saveButton)
        self.scenarios = QtWidgets.QPlainTextEdit()
        self.scenarios.setFont(QtGui.QFont('Courier New', 10))
        fnt = self.scenarios.fontMetrics()
        self.scenarios.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Expanding))
        self.scenarios.setPlainText(lines1)
        self.scenarios.setReadOnly(True)
        screen = QtWidgets.QDesktopWidget().availableGeometry()
        ln = (max_line + 5) * fnt.maxWidth()
        if ln > screen.width() * .80:
            ln = int(screen.width() * .80)
        h1 = (line_cnt1 + 1) * fnt.height()
        if self.log_status:
            self.loglines = QtWidgets.QPlainTextEdit()
            self.loglines.setFont(QtGui.QFont('Courier New', 10))
            h2 = (line_cnt2 + 2) * fnt.height()
            if h1 + h2 > screen.height() * .80:
       #      h1 = max(int(screen.height() * float(h1 / h2)), int(fnt.height()))
                h2 = int(screen.height() * .80) - h1
            self.loglines.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                QtWidgets.QSizePolicy.Expanding))
            self.loglines.setPlainText(lines2)
            self.loglines.setReadOnly(True)
            self.loglines.resize(ln, h2)
        self.scenarios.resize(ln, h1)
        self.scenarios.setFixedHeight(h1)
        layout = QtWidgets.QVBoxLayout()
        if self.full_log:
            layout.addWidget(QtWidgets.QLabel('Open scenarios'))
            layout.addWidget(self.scenarios)
        if self.log_status:
            layout.addWidget(QtWidgets.QLabel('Session log'))
            layout.addWidget(self.loglines)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)
        self.setWindowTitle(self.program + ' - Status - ' + self.config_file)
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        if self.restorewindows:
            try:
                rw = config.get('Windows', 'log_size').split(',')
                self.resize(int(rw[0]), int(rw[1]))
                mp = config.get('Windows', 'log_pos').split(',')
                self.move(int(mp[0]), int(mp[1]))
            except:
                pass
        self.show()

    def save(self):
        save_filename = self.scenarios_folder + self.program + '_Log_' + self.config_file[:-4]
        save_filename += '_' + QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(), 'yyyy-MM-dd_hhmm')
        save_filename += '.txt'
        fileName = QtWidgets.QFileDialog.getSaveFileName(self, self.tr("QFileDialog.getSaveFileName()"),
                   save_filename, self.tr("All Files (*);;Text Files (*.txt)"))[0]
         # save scenarios list and log
        if fileName != '':
            if not self.full_log and not self.log_status:
                return
            s = open(fileName, 'w')
            if self.full_log:
                s.write('Scenarios:\n')
                t = self.scenarios.toPlainText()
                bits = t.split('\n')
                for lin in bits:
                    if len(lin) > 0:
                        s.write(' ' * 10 + lin + '\n')
            if self.log_status:
                s.write('\nSession log:\n\n')
                t = self.loglines.toPlainText()
                bits = t.split('\n')
                for lin in bits:
                    if len(lin) > 0:
                        s.write(lin + '\n')
            s.close()
            self.logged = False

    @QtCore.pyqtSlot()
    def exit(self):
        if self.log_status:
            self.log(self.program + ' log stopped')
        self.be_open = False
        self.close()

    @QtCore.pyqtSlot()
    def log(self, text):
        self.loglines.appendPlainText(QtCore.QDateTime.toString(QtCore.QDateTime.currentDateTime(),
                                'hh:mm:ss. ') + text)
        self.logged = True

    @QtCore.pyqtSlot()
    def log2(self, text):
        self.loglines.appendPlainText(text)
        self.logged = True

    @QtCore.pyqtSlot()
    def updateScenarios(self, scenarios):
        lines1 = ''
        for line in scenarios:
            lines1 += line[0] + '\n'
        self.scenarios.setPlainText(lines1)

    def closeEvent(self, event):
        if self.logged:
            reply = QtWidgets.QMessageBox.question(self, self.program + ' Status',
                    'Do you want to save Session log?', QtWidgets.QMessageBox.Yes |
                    QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
            if reply == QtWidgets.QMessageBox.Yes:
                self.save()
        if self.restorewindows:
            updates = {}
            lines = []
            add = int((self.frameSize().width() - self.size().width()) / 2)   # need to account for border
            lines.append('log_pos=%s,%s' % (str(self.pos().x() + add), str(self.pos().y() + add)))
            lines.append('log_size=%s,%s' % (str(self.width()), str(self.height())))
            updates['Windows'] = lines
            SaveIni(updates)
        if self.be_open:
            self.procStart.emit('goodbye')
        event.accept() class ProgressBar(QtWidgets.QDialog):
    procStart = QtCore.pyqtSignal(str)
   # progress = QtCore.pyqtSignal(int, str)
  #  srange = QtCore.pyqtSignal(int, int)

    def __init__(self, minimum=0, maximum=100, msg=None, title=None):
        super(ProgressBar, self).__init__()
    #    self.mainwindow = mainwindow
        self.log_progress = True
        self.be_open = True
        self.progressbar = QtWidgets.QProgressBar()
        self.progressbar.setMinimum(minimum)
        self.progressbar.setMaximum(maximum)
        self.progressbar.setStyleSheet('QProgressBar {border: 1px solid grey; border-radius: 2px; text-align: center;}' \
                                       + 'QProgressBar::chunk { background-color: #6891c6;}')
        self.button = QtWidgets.QPushButton('Stop')
        self.button.clicked.connect(self.stopit)
        if msg == None:
             msg = 'Note: Solar Thermal Stations take a while to process'
        self.progress_msg = QtWidgets.QLabel(msg)
        main_layout = QtWidgets.QGridLayout()
        main_layout.addWidget(self.button, 0, 0)
        main_layout.addWidget(self.progressbar, 0, 1)
        main_layout.addWidget(self.progress_msg, 1, 1)
        self.setLayout(main_layout)
        if title == None:
            title = 'SIREN - Power Model Progress'
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon('sen_icon32.ico'))
        self.resize(250, 30)
        self.setVisible(False)
        self.show()

    @QtCore.pyqtSlot()
    def stopit(self):
        self.be_open = False

    @QtCore.pyqtSlot()
    def exit(self):
        self.progress_msg.setText('Stop received')
        self.be_open = False
        self.close()

    @QtCore.pyqtSlot(int)
    @QtCore.pyqtSlot(int, int)
    def barRange(self, minimum, maximum, msg=None):
        self.progressbar.setMinimum(minimum)
        self.progressbar.setMaximum(maximum)
        if msg == None:
            msg = 'Note: Solar Thermal Stations take a while to process'
        self.progress_msg.setText(msg)
        self.be_open = True
        self.setVisible(True)

    @QtCore.pyqtSlot(int, str)
    def barProgress(self, ctr, message=''):
        if ctr < 0 or ctr == self.progressbar.maximum():
            self.setVisible(False)
        else:
            if ctr % 2:
                self.progressbar.setStyleSheet('QProgressBar {border: 1px solid grey; border-radius: 2px; text-align: center;}' \
                                             + 'QProgressBar::chunk { background-color: #6891c6;}')
            else:
                self.progressbar.setStyleSheet('QProgressBar {border: 1px solid grey; border-radius: 2px; text-align: center;}' \
                                             + 'QProgressBar::chunk { background-color: #CB6720;}')
            self.progressbar.setValue(ctr)
            self.progress_msg.setText(message)

    def closeEvent(self, event):
        if self.be_open:
            self.procStart.emit('goodbye')
        event.accept() class Icons:
    def __init__(self):
        config = configparser.RawConfigParser()
        if len(sys.argv) > 1:
            config_file = sys.argv[1]
        else:
            config_file = getModelFile('SIREN.ini')
        config.read(config_file)
        self.icons = {'Biomass': 'biomass_g.png', 'CST': 'solar_g.png', 'Fossil': 'fossil_g.png',
                      'Geothermal': 'hot_rocks_g.png', 'Hydro': 'hydro_g.png',
                      'Other': 'question.png', 'PV': 'solar_pv_g.png',
                      'Solar Thermal': 'solar_g.png', 'Wave': 'wave_g.png', 'Wind': 'wind_g.png'}
        try:
            technologies = config.get('Power', 'technologies').split()
            for tec in technologies:
                tec = techClean(tec)
                try:
                    self.icons[tec] = config.get(tec, 'icon')
                except:
                    pass
            technologies = config.get('Power', 'fossil_technologies').split()
            for tec in technologies:
                tec = techClean(tec)
                try:
                    self.icons[tec] = config.get(tec, 'icon')
                except:
                    pass
        except:
            pass

    def getIcon(self, technology):
        if technology in list(self.icons.keys()):
            return self.icons[technology]
        tech = technology
        if technology == 'Biogas':
            tech = 'Biomass'
        elif 'PV' in technology:
            tech = 'PV'
        elif technology[:6] == 'Fossil':
            tech = 'Fossil'
        try:
            return self.icons[tech]
        except:
            return 'question.png'
import csv
import math
import os
import sys
import time
import matplotlib
import webbrowser
import xlrd
import xlwt
import configparser  # decode .ini file
import ssc
import subprocess
import displaytable
import displayobject
import newstation
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
from colours import Colours
from plotweather import PlotWeather
from powermodel import PowerModel
from senuser import getUser, techClean
from station import Station, Stations
from wascene import WAScene
from editini import EdtDialog, EditTech, EditSect, SaveIni
from dijkstra_4 import Shortest
from credits import Credits, fileVersion
from getmodels import getModelFile
from grid import dust
from parents import getParents
from viewresource import Resource
from floaters import FloatLegend, FloatMenu, FloatStatus, ProgressBar
from sirenicons import Icons
                    scen = self.view.scene()._scenarios[i][0]
                    self.removeScenario(scen)
                self.subMenu.clear()
                self.subMenu2.clear()
            self.view.scene()._setupScenario(fname)
            i = fname.rfind('/')
            scen_filter = fname[i + 1:]
            comment = 'Added scenario %s' % (scen_filter)
            subFile = QtWidgets.QAction(QtGui.QIcon('minus.png'), scen_filter, self)
            subFile.setStatusTip('Remove Scenario ' + scen_filter)
            subFile.triggered.connect(self.removeScenario)
            self.subMenu.addAction(subFile)
            subFile2 = QtWidgets.QAction(QtGui.QIcon('edit.png'), scen_filter, self)
            subFile2.setStatusTip('Edit Description for ' + scen_filter)
            subFile2.triggered.connect(self.editDescription)
            self.subMenu2.addAction(subFile2)
            self.reshow_FloatMenu()
            self.reshow_FloatLegend()
            if self.floatstatus:
                self.floatstatus.updateScenarios(self.view.scene()._scenarios)
            self.altered_stations = True
            self.view.statusmsg.emit(comment)
        else:
            i = fname.rfind('/')
            scen_filter = fname[i + 1:]
            comment = 'Scenario not found: %s' % (scen_filter)
            self.view.statusmsg.emit(comment)

    def center(self):
        frameGm = self.frameGeometry()
        screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
        centerPoint = QtWidgets.QApplication.desktop().availableGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

    def showHelp(self):
        if self.leave_help_open:
            webbrowser.open_new(self.helpfile)
        else:
            dialog = displayobject.AnObject(QtWidgets.QDialog(), self.helpfile, title='Help')
            dialog.exec_()

    def showCredits(self, initial=False):
        if self.credits is None:
            self.credits = Credits(initial)
            self.credits.setWindowModality(QtCore.Qt.WindowModal)
            self.credits.setWindowFlags(self.credits.windowFlags() |
                         QtCore.Qt.WindowSystemMenuHint |
                         QtCore.Qt.WindowMinMaxButtonsHint)
            self.credits.procStart.connect(self.getCredits)
            self.credits.show()
     #        self.credits.exec_()

    @QtCore.pyqtSlot(str)
    def getCredits(self, text):
        if text == 'goodbye':
            self.credits = None
        elif text == 'help':
            self.showHelp()
        elif text == 'about':
            self.showAbout()

    @QtCore.pyqtSlot(str)
    def startCredit(self):
        self.showCredits()

    def show_FloatStatus(self):
        if self.floatstatus is None:
            self.floatstatus = FloatStatus(self, self.view.scene().scenarios, self.view.scene()._scenarios)
            self.floatstatus.setWindowModality(QtCore.Qt.WindowModal)
            self.floatstatus.setWindowFlags(self.floatstatus.windowFlags() |
                         QtCore.Qt.WindowSystemMenuHint |
                         QtCore.Qt.WindowMinMaxButtonsHint)
            self.floatstatus.procStart.connect(self.getStatus)
        #    if self.log_status:
         #       self.floatstatus.log.connect(self.floatstatus.log)
          #      self.floatstatus.log2.connect(self.floatstatus.log2)
        #    self.floatstatus.scenarios.connect(self.floatstatus.updateScenarios)
            self.floatstatus.show()
            self.activateWindow()

    @QtCore.pyqtSlot(str)
    def getStatus(self, text):
        if text == 'goodbye':
            self.floatstatus = None

    def show_ProgressBar(self):
        if self.progressbar is None:
            self.progressbar = ProgressBar()
            self.progressbar.setWindowModality(QtCore.Qt.WindowModal)
         #   self.progressbar.connect(self.progressbar.progress)
          #  self.progressbar.connect(self.progressbar.srange)
            self.progressbar.show()
            self.progressbar.setVisible(False)
            self.activateWindow()

    def showAbout(self):
        dialog = displayobject.AnObject(QtWidgets.QDialog(), self.aboutfile, title='About SENs SAM Model')
        dialog.exec_()

    def setStatusText(self, text):
        if text == self.statusBar().currentMessage():
            return
        if self.floatstatus and self.log_status:
            if text[0] != '(':
                self.floatstatus.log(text)
      #   self.statusBar().clearMessage()
        self.statusBar().showMessage(text)

    def go_To(self):
        menu = QtWidgets.QMenu()
        stns = []
        stns_to_show = 0
        for station in self.view.scene()._stations.stations:
             if station.technology[:6] == 'Fossil' and not self.view.scene().show_fossil:
                 continue
             stns_to_show += 1
        try:
            self.icons
        except:

            self.icons = Icons()