text:
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import TemplateView
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from django.db.models import Case, When
from django.core.cache import cache

from common.selection import SimpleSelection, Selection, SelectionItem
from common import definitions
from structure.models import Structure, StructureModel, StructureComplexModel
from protein.models import Protein, ProteinFamily, ProteinSegment, Species, ProteinSource, ProteinSet, ProteinGProtein, ProteinGProteinPair
from residue.models import ResidueGenericNumber, ResidueNumberingScheme, ResidueGenericNumberEquivalent, ResiduePositionSet
from interaction.forms import PDBform
from construct.tool import FileUploadForm

import inspect
from collections import OrderedDict
from io import BytesIO
import xlsxwriter, xlrd
import time
import json

class AbsTargetSelection(TemplateView):
    """An abstract class for the target selection page used in many apps. To use it in another app, create a class
    based view for that app that extends this class"""
    template_name = 'common/targetselection.html'

    type_of_selection = 'targets'
    selection_only_receptors = False
    step = 1
    number_of_steps = 2
    title = 'SELECT TARGETS'
    description = 'Select targets by searching or browsing in the middle column. You can select entire target' \
        + ' families or individual targets.\n\nYou can also enter the list of UNIPROT names of the targets (one per line) and click "Add targets" button to add those.\n\nSelected targets will appear in the right column, where you can edit' \
        + ' the list.\n\nOnce you have selected all your targets, click the green button.'
    documentation_url = settings.DOCUMENTATION_URL
    docs = False
    filters = True
    target_input = True
    default_species = 'Human'
    default_slug = '000'
    numbering_schemes = False
    search = True
    family_tree = True
    redirect_on_select = False
    filter_gprotein = False
    selection_heading = False
    buttons = {
        'continue': {
            'label': 'Continue to next step',
            'url': '#',
            'color': 'success',
        },
    }
    # OrderedDict to preserve the order of the boxes
    selection_boxes = OrderedDict([
        ('reference', False),
        ('targets', True),
        ('segments', False),
    ])

    # proteins and families
    #try - except block prevents manage.py from crashing - circular dependencies between protein - common
    try:
        if ProteinFamily.objects.filter(slug=default_slug).exists():
            ppf = ProteinFamily.objects.get(slug=default_slug)
            pfs = ProteinFamily.objects.filter(parent=ppf.id)
            ps = Protein.objects.filter(family=ppf)
            psets = ProteinSet.objects.all().prefetch_related('proteins')
            tree_indent_level = []
            action = 'expand'
            # remove the parent family (for all other families than the root of the tree, the parent should be shown)
            del ppf
    except Exception as e:
        pass

    # species
    sps = Species.objects.all()

    # g proteins
    gprots = ProteinGProtein.objects.all()

    # numbering schemes
    gns = ResidueNumberingScheme.objects.exclude(slug=settings.DEFAULT_NUMBERING_SCHEME).exclude(slug='cgn')

    def get_context_data(self, **kwargs):
        """get context from parent class (really only relevant for children of this class, as TemplateView does
        not have any context variables)"""
        context = super().get_context_data(**kwargs)

        # get selection from session and add to context
        # get simple selection from session
        simple_selection = self.request.session.get('selection', False)

        # create full selection and import simple selection (if it exists)
        selection = Selection()

        # on the first page of a workflow, clear the selection (or dont' import from the session)
        if self.step is not 1:
            if simple_selection:
                selection.importer(simple_selection)

        # default species selection
        if self.default_species:
            sp = Species.objects.get(common_name=self.default_species)
            o = SelectionItem('species', sp)
            selection.species = [o]

        # update session
        simple_selection = selection.exporter()
        self.request.session['selection'] = simple_selection

        context['selection'] = {}
        for selection_box, include in self.selection_boxes.items():
            if include:
                context['selection'][selection_box] = selection.dict(selection_box)['selection'][selection_box]

        if self.filters:
            context['selection']['species'] = selection.species
            context['selection']['annotation'] = selection.annotation
            context['selection']['g_proteins'] = selection.g_proteins
            context['selection']['pref_g_proteins'] = selection.pref_g_proteins

        # get attributes of this class and add them to the context
        attributes = inspect.getmembers(self, lambda a:not(inspect.isroutine(a)))
        for a in attributes:
            if not(a[0].startswith('__') and a[0].endswith('__')):
                context[a[0]] = a[1]
        return context

class AbsReferenceSelection(AbsTargetSelection):
    type_of_selection = 'reference'
    step = 1
    number_of_steps = 3
    title = 'SELECT A REFERENCE TARGET'
    description = 'Select a reference target by searching or browsing in the right column.\n\nThe reference will be compared to the targets you select later in the workflow.\n\nOnce you have selected your reference target, you will be redirected to the next step.'
    redirect_on_select = True
    selection_boxes = OrderedDict([
        ('reference', True),
        ('targets', False),
        ('segments', False),
    ])
    psets = [] # protein sets not applicable for this selection

class AbsBrowseSelection(AbsTargetSelection):
    type_of_selection = 'browse'
    step = 1
    number_of_steps = 1
    title = 'SELECT A TARGET OR FAMILY'
    description = 'Select a target or family by searching or browsing in the right column.'
    psets = [] # protein sets not applicable for this selection

class AbsSegmentSelection(TemplateView):
    """An abstract class for the segment selection page used in many apps. To use it in another app, create a class
    based view for that app that extends this class"""
    template_name = 'common/segmentselection.html'

    step = 2
    number_of_steps = 2
    title = 'SELECT SEQUENCE SEGMENTS'
    description = 'Select sequence segments in the middle column. You can expand helices and select individual' \
        + ' residues by clicking on the down arrows next to each helix.\n\nSelected segments will appear in the' \
        + ' right column, where you can edit the list.\n\nOnce you have selected all your segments, click the green' \
        + ' button.'
    documentation_url = settings.DOCUMENTATION_URL
    docs = False
    segment_list = True
    structure_upload = False
    upload_form = PDBform()
    position_type = 'residue'
    buttons = {
        'continue': {
            'label': 'Show alignment',
            'url': '/alignment/render',
            'color': 'success',
        },
    }
    # OrderedDict to preserve the order of the boxes
    selection_boxes = OrderedDict([
        ('reference', False),
        ('targets', True),
        ('segments', True),
    ])

    try:
        rsets = ResiduePositionSet.objects.filter(protein_group='gpcr').prefetch_related('residue_position').order_by('set_type','name')
    except Exception as e:
        pass

    ss = ProteinSegment.objects.filter(partial=False, proteinfamily='GPCR').prefetch_related('generic_numbers')
    ss_cats = ss.values_list('category').order_by('category').distinct('category')
    action = 'expand'

    amino_acid_groups = definitions.AMINO_ACID_GROUPS
    amino_acid_group_names = definitions.AMINO_ACID_GROUP_NAMES

    def get_context_data(self, **kwargs):
        """get context from parent class (really only relevant for child classes of this class, as TemplateView does
        not have any context variables)"""
        context = super().get_context_data(**kwargs)

        # get selection from session and add to context
        # get simple selection from session
        simple_selection = self.request.session.get('selection', False)

        # create full selection and import simple selection (if it exists)
        selection = Selection()
        if simple_selection:
            selection.importer(simple_selection)

        # context['selection'] = selection
        context['selection'] = {}
        context['selection']['site_residue_groups'] = selection.site_residue_groups
        context['selection']['active_site_residue_group'] = selection.active_site_residue_group
        for selection_box, include in self.selection_boxes.items():
            if include:
                context['selection'][selection_box] = selection.dict(selection_box)['selection'][selection_box]

        # get attributes of this class and add them to the context
        attributes = inspect.getmembers(self, lambda a:not(inspect.isroutine(a)))
        for a in attributes:
            if not(a[0].startswith('__') and a[0].endswith('__')):
                context[a[0]] = a[1]
        return context

class AbsMiscSelection(TemplateView):
    """An abstract class for selection pages of other types than target- and segmentselection"""
    template_name = 'common/miscselection.html'
    step = 3
    number_of_steps = 3
    title = ''
    description = ''
    documentation_url = settings.DOCUMENTATION_URL
    docs = False
    buttons = {}
    tree_settings = False
    blast_input = False

    # OrderedDict to preserve the order of the boxes
    selection_boxes = OrderedDict([
        ('targets', True),
        ('segments', True),
    ])
    def get_context_data(self, **kwargs):
        """get context from parent class (really only relevant for child classes of this class, as TemplateView does
        not have any context variables)"""
        context = super().get_context_data(**kwargs)

        # get selection from session and add to context
        # get simple selection from session
        simple_selection = self.request.session.get('selection', False)

        # create full selection and import simple selection (if it exists)
        selection = Selection()

        # on the first page of a workflow, clear the selection (or dont' import from the session)
        if self.step is not 1:
            if simple_selection:
                selection.importer(simple_selection)

        context['selection'] = {}
        context['selection']['tree_settings'] = selection.tree_settings

        for selection_box, include in self.selection_boxes.items():
            if include:
                context['selection'][selection_box] = selection.dict(selection_box)['selection'][selection_box]

        # get attributes of this class and add them to the context
        attributes = inspect.getmembers(self, lambda a:not(inspect.isroutine(a)))
        for a in attributes:
            if not(a[0].startswith('__') and a[0].endswith('__')):
                context[a[0]] = a[1]
        return context

def AddToSelection(request):
    """Receives a selection request, adds the selected item to session, and returns the updated selection"""
    selection_type = request.GET['selection_type']
    selection_subtype = request.GET['selection_subtype']
    selection_id = request.GET['selection_id']
    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # process selected object
    o = []
    if selection_type == 'reference' or selection_type == 'targets':
        # print(selection_type, selection_subtype, selection_id)
        if selection_subtype == 'protein':
            o.append(Protein.objects.get(pk=selection_id))
        if selection_subtype == 'protein_entry':
            o.append(Protein.objects.get(entry_name=selection_id))
            print("Added {}".format(Protein.objects.get(entry_name=selection_id).name))

        elif selection_subtype == 'protein_set':
            selection_subtype = 'protein'
            pset = ProteinSet.objects.get(pk=selection_id)
            for protein in pset.proteins.all():
                o.append(protein)

        elif selection_subtype == 'family':
            o.append(ProteinFamily.objects.get(pk=selection_id))

        elif selection_subtype == 'set':
            o.append(ProteinSet.objects.get(pk=selection_id))

        elif selection_subtype == 'structure':
            if 'refined' in selection_id:
                sel1, sel2 = selection_id.split('_')
                o.append(Structure.objects.get(pdb_code__index=sel1.upper()+'_refined'))
            else:
                o.append(Structure.objects.get(pdb_code__index=selection_id.upper()))

        elif selection_subtype == 'structure_many':
            selection_subtype = 'structure'
            for pdb_code in selection_id.split(","):
                if 'refined' in pdb_code:
                    sel1, sel2 = pdb_code.split('_')
                    o.append(Structure.objects.get(pdb_code__index=sel1.upper()+'_refined'))
                else:
                    o.append(Structure.objects.get(pdb_code__index=pdb_code.upper()))

        # elif selection_subtype == 'structure_model_Inactive':
        #     entry_name = '_'.join(selection_id.split('_')[:-1])
        #     o.append(StructureModel.objects.defer('pdb').filter(protein__entry_name=entry_name, state__name='Inactive')[0])
        # elif selection_subtype == 'structure_model_Intermediate':
        #     entry_name = '_'.join(selection_id.split('_')[:-1])
        #     o.append(StructureModel.objects.defer('pdb').filter(protein__entry_name=entry_name, state__name='Intermediate')[0])
        # elif selection_subtype == 'structure_model_Active':
        #     entry_name = '_'.join(selection_id.split('_')[:-1])
        #     o.append(StructureModel.objects.defer('pdb').filter(protein__entry_name=entry_name, state__name='Active')[0])

        elif selection_subtype == 'structure_complex_receptor':
            o.append(StructureComplexModel.objects.filter(receptor_protein__entry_name=selection_id)[0])

        elif selection_subtype == 'structure_complex_signprot':
            o.append(StructureComplexModel.objects.filter(sign_protein__entry_name=selection_id)[0])

        elif selection_subtype == 'structure_model':
            state = selection_id.split('_')[-1]
            entry_name = '_'.join(selection_id.split('_')[:-1])
            # print(entry_name, state)
            o.append(StructureModel.objects.filter(protein__entry_name=entry_name, state__name=state)[0])

        elif selection_subtype == 'structure_models_many':
            selection_subtype = 'structure_model'
            for model in selection_id.split(","):
                if 'refined' in model:
                    sel1, sel2 = model.split('_')
                    o.append(Structure.objects.get(pdb_code__index=sel1.upper()+'_refined'))
                else:
                    state = model.split('_')[-1]
                    entry_name = '_'.join(model.split('_')[:-1])
                    o.append(StructureModel.objects.get(protein__entry_name=entry_name, state__name=state))

    elif selection_type == 'segments':
        if selection_subtype == 'residue':
            o.append(ResidueGenericNumberEquivalent.objects.get(pk=selection_id))
        elif selection_subtype == 'residue_position_set':
            selection_subtype = 'residue'
            rset = ResiduePositionSet.objects.get(pk=selection_id)
            for residue in rset.residue_position.all():
                o.append(residue)
        elif selection_subtype == 'site_residue': # used in site search
            o.append(ResidueGenericNumberEquivalent.objects.get(pk=selection_id))

        else:
            o.append(ProteinSegment.objects.get(pk=selection_id))

    for obj in o:
        # add the selected item to the selection
        selection_object = SelectionItem(selection_subtype, obj)
        selection.add(selection_type, selection_subtype, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()
    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # template to load
    if selection_subtype == 'site_residue':
        template = 'common/selection_lists_sitesearch.html'
        amino_acid_groups = {
            'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
            'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
        context.update(amino_acid_groups)
    else:
        template = 'common/selection_lists.html'

    # amino acid groups
    # print('+++++++++++++++++++++++++')
    # print(context['selection_type'])
    # print(context)
    # for c in context['selection']['targets']:
    #     print(c, c.type, c.item)
    return render(request, template, context)

def RemoveFromSelection(request):
    """Removes one selected item from the session"""
    selection_type = request.GET['selection_type']
    selection_subtype = request.GET['selection_subtype']
    selection_id = request.GET['selection_id']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # remove the selected item to the selection
    selection.remove(selection_type, selection_subtype, selection_id)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # template to load
    if selection_subtype == 'site_residue':
        template = 'common/selection_lists_sitesearch.html'
        amino_acid_groups = {
            'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
            'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
        context.update(amino_acid_groups)
    else:
        template = 'common/selection_lists.html'

    return render(request, template, context)

def ClearSelection(request):
    """Clears all selected items of the selected type from the session"""
    selection_type = request.GET['selection_type']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # remove the selected item to the selection
    selection.clear(selection_type)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict(selection_type))

def SelectRange(request):
    """Adds generic numbers within the given range"""

    selection_type = request.GET['selection_type']
    selection_subtype = request.GET['selection_subtype']
    range_start = request.GET['range_start']
    range_end = request.GET['range_end']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # process selected object
    o = []
    if selection_type == 'segments' and selection_subtype == 'residue':
        residue_nums = ResidueGenericNumberEquivalent.objects.all()
        for resn in residue_nums:
            if range_start < float(resn.label.replace('x','.')) < range_end:
                o.append(resn)

def SelectFullSequence(request):
    """Adds all segments to the selection"""
    selection_type = request.GET['selection_type']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # get all segments
    if "protein_type" in request.GET:

        if request.GET['protein_type'] == 'gprotein':
            segmentlist = definitions.G_PROTEIN_SEGMENTS
            pfam = 'Alpha'
        else:
            segmentlist = definitions.ARRESTIN_SEGMENTS
            pfam = 'Arrestin'

        preserved = Case(*[When(slug=pk, then=pos) for pos, pk in enumerate(segmentlist['Full'])])
        segments = ProteinSegment.objects.filter(slug__in=segmentlist['Full'], partial=False, proteinfamily=pfam).order_by(preserved)

    else:
        segments = ProteinSegment.objects.filter(partial=False, proteinfamily='GPCR')

    for segment in segments:
        selection_object = SelectionItem(segment.category, segment)
        # add the selected item to the selection
        selection.add(selection_type, segment.category, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict(selection_type))

def SetTreeSelection(request):
    """Adds all alignable segments to the selection"""
    option_no = request.GET['option_no']
    option_id = request.GET['option_id']
    # get simple selection from session
    simple_selection = request.session.get('selection', False)
    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)
    selection.tree_settings[int(option_no)]=option_id
    simple_selection = selection.exporter()
    # add simple selection to session
    request.session['selection'] = simple_selection
    return render(request, 'common/tree_options.html', selection.dict('tree_settings'))

def SelectAlignableSegments(request):
    """Adds all alignable segments to the selection"""
    selection_type = request.GET['selection_type']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # get specific segments
    if "protein_type" in request.GET:
        if request.GET['protein_type'] == 'gprotein':
            segmentlist = definitions.G_PROTEIN_SEGMENTS
            pfam = 'Alpha'
        else:
            segmentlist = definitions.ARRESTIN_SEGMENTS
            pfam = 'Arrestin'

        preserved = Case(*[When(slug=pk, then=pos) for pos, pk in enumerate(segmentlist['Structured'])])
        segments = ProteinSegment.objects.filter(slug__in=segmentlist['Structured'], partial=False, proteinfamily=pfam).order_by(preserved)
    else:
        segments = ProteinSegment.objects.filter(partial=False, slug__startswith='TM')

    for segment in segments:
        selection_object = SelectionItem(segment.category, segment)
        # add the selected item to the selection
        selection.add(selection_type, segment.category, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict(selection_type))

def SelectAlignableResidues(request):
    """Adds all alignable residues to the selection"""
    selection_type = request.GET['selection_type']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    if "protein_type" in request.GET:
        if request.GET['protein_type'] == 'gprotein':
            segmentlist = definitions.G_PROTEIN_SEGMENTS
            pfam = 'Gprotein'
        else:
            segmentlist = definitions.ARRESTIN_SEGMENTS
            pfam = 'Arrestin'

        preserved = Case(*[When(slug=pk, then=pos) for pos, pk in enumerate(segmentlist['Structured'])])
        segments = ProteinSegment.objects.filter(slug__in=segmentlist['Structured'], partial=False, proteinfamily=pfam).order_by(preserved)
    else:
        segments = ProteinSegment.objects.filter(proteinfamily='GPCR').order_by('pk')

    numbering_scheme_slug = 'false'

    # find the relevant numbering scheme (based on target selection)

    cgn = False
    if numbering_scheme_slug == 'cgn':
        cgn = True
    elif numbering_scheme_slug == 'false':
        if simple_selection.reference:
            first_item = simple_selection.reference[0]
        else:
            first_item = simple_selection.targets[0]
        if first_item.type == 'family':
            proteins = Protein.objects.filter(family__slug__startswith=first_item.item.slug)
            numbering_scheme = proteins[0].residue_numbering_scheme
        elif first_item.type == 'protein':
            numbering_scheme = first_item.item.residue_numbering_scheme
    else:
        numbering_scheme = ResidueNumberingScheme.objects.get(slug=numbering_scheme_slug)

    for segment in segments:
        if segment.fully_aligned:
            selection_object = SelectionItem(segment.category, segment)
            # add the selected item to the selection
            selection.add(selection_type, segment.category, selection_object)
        else:
            #if not fully aligned

            if ResidueGenericNumberEquivalent.objects.filter(
            default_generic_number__protein_segment=segment,
            scheme=numbering_scheme).exists():
                segment.only_aligned_residues = True
                selection_object = SelectionItem(segment.category, segment, properties={'only_aligned_residues':True})
                selection.add(selection_type, segment.category, selection_object)

    simple_selection = selection.exporter()
    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict('segments'))

def ToggleFamilyTreeNode(request):
    """Opens/closes a node in the family selection tree"""
    action = request.GET['action']
    type_of_selection = request.GET['type_of_selection']

    node_id = request.GET['node_id']
    parent_tree_indent_level = int(request.GET['tree_indent_level'])
    tree_indent_level = []
    for i in range(parent_tree_indent_level+1):
        tree_indent_level.append(0)
    parent_tree_indent_level = tree_indent_level[:]
    del parent_tree_indent_level[-1]

    # session
    simple_selection = request.session.get('selection')
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    ppf = ProteinFamily.objects.get(pk=node_id)
    if action == 'expand':
        pfs = ProteinFamily.objects.filter(parent=node_id)

        # species filter
        species_list = []
        for species in selection.species:
            species_list.append(species.item)

        # annotation filter
        protein_source_list = []
        for protein_source in selection.annotation:
            protein_source_list.append(protein_source.item)

        # preferred g proteins filter
        pref_g_proteins_list = []
        for g_protein in selection.pref_g_proteins:
            pref_g_proteins_list.append(g_protein.item)

        # g proteins filter
        g_proteins_list = []
        for g_protein in selection.g_proteins:
            g_proteins_list.append(g_protein.item)

        if species_list:
            ps = Protein.objects.order_by('id').filter(family=ppf,
                species__in=(species_list),
                source__in=(protein_source_list)).order_by('source_id', 'id')
        else:
            ps = Protein.objects.order_by('id').filter(family=ppf,
                source__in=(protein_source_list)).order_by('source_id', 'id')

        if pref_g_proteins_list:
            proteins = [x.protein_id for x in ProteinGProteinPair.objects.filter(g_protein__in=g_proteins_list, transduction='primary')]
            ps = Protein.objects.order_by('id').filter(pk__in=proteins).filter(pk__in=ps)

        if g_proteins_list:
            proteins = [x.protein_id for x in ProteinGProteinPair.objects.filter(g_protein__in=g_proteins_list)]
            ps = Protein.objects.order_by('id').filter(pk__in=proteins).filter(pk__in=ps)

        # Excluding G protein Alpha subunit protein structure objects, e.g. 3sn6_a
        ps = ps.exclude(accession__isnull=True, family__parent__parent__name='Alpha')

        action = 'collapse'
    else:
        pfs = ps = {}
        action = 'expand'

    return render(request, 'common/selection_tree.html', {
        'action': action,
        'type_of_selection': type_of_selection,
        'ppf': ppf,
        'pfs': pfs,
        'ps': ps,
        'parent_tree_indent_level': parent_tree_indent_level,
        'tree_indent_level': tree_indent_level,
    })

def SelectionAnnotation(request):
    """Updates the selected level of annotation"""
    protein_source = request.GET['protein_source']

    if protein_source == 'All':
        pss = ProteinSource.objects.all()
    else:
        pss = ProteinSource.objects.filter(name=protein_source)

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # reset the annotation selection
    selection.clear('annotation')

    # add the selected items to the selection
    for ps in pss:
        selection_object = SelectionItem('annotation', ps)
        selection.add('annotation', 'annotation', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection
    return render(request, 'common/selection_filters_annotation.html', selection.dict('annotation'))

def SelectionSpeciesPredefined(request):
    """Updates the selected species to predefined sets (Human and all)"""
    species = request.GET['species']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    all_sps = Species.objects.all()
    sps = False
    if species == 'All':
        sps = []
    if species != 'All' and species:
        sps = Species.objects.filter(common_name=species)

    if sps != False:
        # reset the species selection
        selection.clear('species')

        # add the selected items to the selection
        for sp in sps:
            selection_object = SelectionItem('species', sp)
            selection.add('species', 'species', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    context = selection.dict('species')
    context['sps'] = all_sps

    return render(request, 'common/selection_filters_species.html', context)

def SelectionSpeciesToggle(request):
    """Updates the selected species arbitrary selections"""
    species_id = request.GET['species_id']

    all_sps = Species.objects.all()
    sps = Species.objects.filter(pk=species_id)

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # add the selected items to the selection
    for sp in sps:
        exists = selection.remove('species', 'species', species_id)
        if not exists:
            selection_object = SelectionItem('species', sp)
            selection.add('species', 'species', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    context = selection.dict('species')
    context['sps'] = Species.objects.all()

    return render(request, 'common/selection_filters_species_selector.html', context)

def SelectionGproteinPredefined(request):
    """Updates the selected g proteins to predefined sets (Gi/Go and all)"""
    g_protein = request.GET['g_protein']
    preferred = request.GET['preferred']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    all_gprots = ProteinGProtein.objects.all()
    gprots = False
    if g_protein == 'All':
        gprots = []
    if g_protein != 'All' and g_protein:
        gprots = ProteinGProtein.objects.filter(name=g_protein)

    if gprots != False:
        # reset the g proteins selection
        if preferred == 'true':
            selection.clear('pref_g_proteins')
        else:
            selection.clear('g_proteins')

        # add the selected items to the selection
        for gprot in gprots:
            selection_object = SelectionItem('g_protein', gprot)
            if preferred == 'true':
                selection.add('pref_g_proteins', 'g_protein', selection_object)
            else:
                selection.add('g_proteins', 'g_protein', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    if preferred == 'true':
        context = selection.dict('pref_g_proteins')
    else:
        context = selection.dict('g_proteins')
    context['gprots'] = ProteinGProtein.objects.all()

    if preferred == 'true':
        return render(request, 'common/selection_filters_pref_gproteins.html', context)
    else:
        return render(request, 'common/selection_filters_gproteins.html', context)

def SelectionGproteinToggle(request):
    """Updates the selected g proteins arbitrary selections"""
    g_protein_id = request.GET['g_protein_id']
    preferred = request.GET['preferred']

    all_gprots = ProteinGProtein.objects.all()
    gprots = ProteinGProtein.objects.filter(pk=g_protein_id)
    print("'{}'".format(ProteinGProtein.objects.get(pk=g_protein_id).name))

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # add the selected items to the selection
    for gprot in gprots:
        if preferred == 'true':
            exists = selection.remove('pref_g_proteins', 'g_protein', g_protein_id)
        else:
            exists = selection.remove('g_proteins', 'g_protein', g_protein_id)
        if not exists:
            selection_object = SelectionItem('g_protein', gprot)
            if preferred == 'true':
                selection.add('pref_g_proteins', 'g_protein', selection_object)
            else:
                selection.add('g_proteins', 'g_protein', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    if preferred == 'true':
        context = selection.dict('pref_g_proteins')
    else:
        context = selection.dict('g_proteins')

    context['gprots'] = ProteinGProtein.objects.all()

    if preferred == 'true':
        # print(request.session['selection'])
        return render(request, 'common/selection_filters_pref_gproteins_selector.html', context)
    else:
        return render(request, 'common/selection_filters_gproteins_selector.html', context)

def ExpandSegment(request):
    """Expands a segment to show it's generic numbers"""
    segment_id = request.GET['segment_id']
    position_type = request.GET['position_type']
    numbering_scheme_slug = str(request.GET['numbering_scheme'])

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # find the relevant numbering scheme (based on target selection)
    cgn = False
    if numbering_scheme_slug == 'cgn':
        cgn = True
    elif numbering_scheme_slug == 'false':
        if simple_selection.reference:
            first_item = simple_selection.reference[0]
        else:
            first_item = simple_selection.targets[0]
        if first_item.type == 'family':
            proteins = Protein.objects.filter(family__slug__startswith=first_item.item.slug)
            numbering_scheme = proteins[0].residue_numbering_scheme
        elif first_item.type == 'protein':
            numbering_scheme = first_item.item.residue_numbering_scheme
    else:
        numbering_scheme = ResidueNumberingScheme.objects.get(slug=numbering_scheme_slug)

    if cgn ==True:
        # fetch the generic numbers for CGN differently
        context = {}
        context['generic_numbers'] = ResidueGenericNumberEquivalent.objects.filter(
            default_generic_number__protein_segment__id=segment_id,
            scheme__slug='cgn').order_by('label')
        context['position_type'] = position_type
        context['scheme'] = ResidueNumberingScheme.objects.filter(slug='cgn')
        context['schemes'] = ResidueNumberingScheme.objects.filter(slug='cgn')
        context['segment_id'] = segment_id
    else:
        # fetch the generic numbers
        context = {}
        context['generic_numbers'] = ResidueGenericNumberEquivalent.objects.filter(
            default_generic_number__protein_segment__id=segment_id,
            scheme=numbering_scheme).order_by('label')
        context['position_type'] = position_type
        context['scheme'] = numbering_scheme
        context['schemes'] = ResidueNumberingScheme.objects.filter(parent__isnull=False)
        context['segment_id'] = segment_id
        print(context['scheme'], context['schemes'])

    return render(request, 'common/segment_generic_numbers.html', context)

def SelectionSchemesPredefined(request):
    """Updates the selected numbering_schemes to predefined sets (GPCRdb and All)"""
    numbering_schemes = request.GET['numbering_schemes']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    all_gns = ResidueNumberingScheme.objects.exclude(slug=settings.DEFAULT_NUMBERING_SCHEME).exclude(slug='cgn')
    gns = False
    if numbering_schemes == 'All':
        print(len(selection.numbering_schemes), all_gns.count())
        if len(selection.numbering_schemes) == all_gns.count():
            gns = []
        else:
            gns = all_gns

    # reset the species selection
    selection.clear('numbering_schemes')

    # add the selected items to the selection
    for gn in gns:
        selection_object = SelectionItem('numbering_schemes', gn)
        selection.add('numbering_schemes', 'numbering_schemes', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    context = selection.dict('numbering_schemes')
    context['gns'] = all_gns

    return render(request, 'common/selection_filters_numbering_schemes.html', context)

def SelectionSchemesToggle(request):
    """Updates the selected numbering schemes arbitrary selections"""
    numbering_scheme_id = request.GET['numbering_scheme_id']
    gns = ResidueNumberingScheme.objects.filter(pk=numbering_scheme_id).exclude(slug='cgn')

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # add the selected items to the selection
    for gn in gns:
        exists = selection.remove('numbering_schemes', 'numbering_schemes', numbering_scheme_id)
        if not exists:
            selection_object = SelectionItem('numbering_schemes', gn)
            selection.add('numbering_schemes', 'numbering_schemes', selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # add all species objects to context (for comparison to selected species)
    context = selection.dict('numbering_schemes')
    context['gns'] = ResidueNumberingScheme.objects.exclude(slug=settings.DEFAULT_NUMBERING_SCHEME).exclude(slug='cgn')

    return render(request, 'common/selection_filters_numbering_schemes.html', context)

def UpdateSiteResidueFeatures(request):
    """Updates the selected features of a site residue"""
    selection_type = request.GET['selection_type']
    selection_subtype = request.GET['selection_subtype']
    selection_id = request.GET['selection_id']

    o = []
    if selection_type == 'reference' or selection_type == 'targets':
        if selection_subtype == 'protein':
            o.append(Protein.objects.get(pk=selection_id))
        elif selection_subtype == 'protein_set':
            selection_subtype = 'protein'
            pset = ProteinSet.objects.get(pk=selection_id)
            for protein in pset.proteins.all():
                o.append(protein)
        elif selection_subtype == 'family':
            o.append(ProteinFamily.objects.get(pk=selection_id))
        elif selection_subtype == 'set':
            o.append(ProteinSet.objects.get(pk=selection_id))
        elif selection_subtype == 'structure':
            o.append(Protein.objects.get(entry_name=selection_id.lower()))
    elif selection_type == 'segments':
        if selection_subtype == 'residue':
            o.append(ResidueGenericNumberEquivalent.objects.get(pk=selection_id))
        elif selection_subtype == 'residue_with_properties': # used in site search
            o.append(ResidueGenericNumberEquivalent.objects.get(pk=selection_id))
        else:
            o.append(ProteinSegment.objects.get(pk=selection_id))

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    for obj in o:
        # add the selected item to the selection
        selection_object = SelectionItem(selection_subtype, obj)
        selection.add(selection_type, selection_subtype, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict(selection_type))

def SelectResidueFeature(request):
    """Receives a selection request, add a feature selection to an item, and returns the updated selection"""
    selection_type = request.GET['selection_type']
    selection_subtype = request.GET['selection_subtype']
    selection_id = int(request.GET['selection_id'])
    feature = request.GET['feature']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # process selected object
    if selection_type == 'segments' and selection_subtype == 'site_residue':
        for obj in selection.segments:
            if int(obj.item.id) == selection_id:
                obj.properties['feature'] = feature
                obj.properties['amino_acids'] = ','.join(definitions.AMINO_ACID_GROUPS[feature])
                break

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # amino acid groups
    amino_acid_groups = {
        'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
        'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
    context.update(amino_acid_groups)

    # template to load
    template = 'common/selection_lists_sitesearch.html'

    return render(request, template, context)

def AddResidueGroup(request):
    """Receives a selection request, creates a new residue group, and returns the updated selection"""
    selection_type = request.GET['selection_type']

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # add a group

    selection.site_residue_groups.append([])

    # make the new group active
    selection.active_site_residue_group = len(selection.site_residue_groups)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # amino acid groups
    amino_acid_groups = {
        'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
        'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
    context.update(amino_acid_groups)

    # template to load
    template = 'common/selection_lists_sitesearch.html'

    return render(request, template, context)

def SelectResidueGroup(request):
    """Receives a selection request, updates the active residue group, and returns the updated selection"""
    selection_type = request.GET['selection_type']
    group_id = int(request.GET['group_id'])

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # update the selected group
    selection.active_site_residue_group = group_id

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # amino acid groups
    amino_acid_groups = {
        'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
        'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
    context.update(amino_acid_groups)

    # template to load
    template = 'common/selection_lists_sitesearch.html'

    return render(request, template, context)

def RemoveResidueGroup(request):
    """Receives a selection request, removes a residue group, and returns the updated selection"""
    selection_type = request.GET['selection_type']
    group_id = int(request.GET['group_id'])

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # find all positions in the group and delete them
    for position in selection.segments:
        if position.type == 'site_residue':
            if position.properties['site_residue_group'] == group_id:
                selection.remove(selection_type, position.type, position.item.id)
            else:
                if position.properties['site_residue_group'] > group_id:
                    position.properties['site_residue_group'] -= 1

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # amino acid groups
    amino_acid_groups = {
        'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
        'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
    context.update(amino_acid_groups)

    # template to load
    template = 'common/selection_lists_sitesearch.html'

    return render(request, template, context)

def SetGroupMinMatch(request):
    """Receives a selection request, sets a minimum match for a group, and returns the updated selection"""
    selection_type = request.GET['selection_type']
    group_id = int(request.GET['group_id'])
    min_match = int(request.GET['min_match'])

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    # update the group
    selection.site_residue_groups[group_id - 1][0] = min_match

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    # amino acid groups
    amino_acid_groups = {
        'amino_acid_groups': definitions.AMINO_ACID_GROUPS,
        'amino_acid_group_names': definitions.AMINO_ACID_GROUP_NAMES }
    context.update(amino_acid_groups)

    # template to load
    template = 'common/selection_lists_sitesearch.html'

    return render(request, template, context)

def ResiduesDownload(request):

    simple_selection = request.session.get('selection', False)

    outstream = BytesIO()
    wb = xlsxwriter.Workbook(outstream, {'in_memory': True})
    worksheet = wb.add_worksheet()
    row_count = 0

    for position in simple_selection.segments:
        if position.type == 'residue':
            worksheet.write_row(row_count, 0, ['residue', position.item.scheme.slug, position.item.label])
            row_count += 1
        elif position.type == 'helix':
            worksheet.write_row(row_count, 0, ['helix', '', position.item.slug])
            row_count += 1
    wb.close()
    outstream.seek(0)
    response = HttpResponse(outstream.read(), content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    response['Content-Disposition'] = "attachment; filename=segment_selection.xlsx"

    return response

def ResiduesUpload(request):
    """Receives a file containing generic residue positions along with numbering scheme and adds those to the selection."""

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    selection_type = 'segments'
    if request.FILES == {}:
        return render(request, 'common/selection_lists.html', '')

    #Overwriting the existing selection
    selection.clear(selection_type)

    #The excel file
    o = []
    workbook = xlrd.open_workbook(file_contents=request.FILES['xml_file'].read())
    worksheets = workbook.sheet_names()
    for worksheet_name in worksheets:
        worksheet = workbook.sheet_by_name(worksheet_name)
        for row in worksheet.get_rows():
            if len(row) < 2:
                continue
            try:
                if row[0].value == 'residue':
                    position = ResidueGenericNumberEquivalent.objects.get(label=row[2].value, scheme__slug=row[1].value)
                    o.append(position)
                elif row[0].value == 'helix':
                    o.append(ProteinSegment.objects.get(slug=row[2].value))
            except Exception as msg:
                print(msg)
                continue
    for obj in o:
        # add the selected item to the selection
        if obj.__class__.__name__ == 'ResidueGenericNumberEquivalent':
            selection_subtype = 'residue'
        else:
            selection_subtype = 'helix'
        selection_object = SelectionItem(selection_subtype, obj)
        selection.add(selection_type, selection_subtype, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    return render(request, 'common/selection_lists.html', selection.dict(selection_type))

@csrf_exempt
def ReadTargetInput(request):
    """Receives the data from the input form nd adds the listed targets to the selection"""

    # get simple selection from session
    simple_selection = request.session.get('selection', False)

    # create full selection and import simple selection (if it exists)
    selection = Selection()
    if simple_selection:
        selection.importer(simple_selection)

    selection_type = 'targets'
    selection_subtype = 'protein'

    if request.POST == {}:
        return render(request, 'common/selection_lists.html', '')

    o = []
    up_names = request.POST['input-targets'].split('\r')
    for up_name in up_names:
        try:
            o.append(Protein.objects.get(entry_name=up_name.strip().lower()))
        except:
            continue

    for obj in o:
        # add the selected item to the selection
        selection_object = SelectionItem(selection_subtype, obj)
        selection.add(selection_type, selection_subtype, selection_object)

    # export simple selection that can be serialized
    simple_selection = selection.exporter()

    # add simple selection to session
    request.session['selection'] = simple_selection

    # context
    context = selection.dict(selection_type)

    return render(request, 'common/selection_lists.html', context)

@csrf_exempt
def ExportExcelSuggestions(request):
    """Convert json file to excel file"""
    headers = ['reference','review', 'protein', 'mutation_pos', 'generic', 'mutation_from', 'mutation_to',
        'ligand_name', 'ligand_idtype', 'ligand_id', 'ligand_class',
        'exp_type', 'exp_func',  'exp_wt_value',  'exp_wt_unit','exp_mu_effect_sign', 'exp_mu_effect_type', 'exp_mu_effect_value',
        'exp_mu_effect_qual', 'exp_mu_effect_ligand_prop',  'exp_mu_ligand_ref', 'opt_type', 'opt_wt',
        'opt_mu', 'opt_sign', 'opt_percentage', 'opt_qual','opt_agonist', 'added_date'
         ] #'added_by',

    # icl2_end
    # thermo
    # icl2_start
    # nterm
    # cterm
    # icl3_start
    # removals
    # icl3_end

    sheets = ['nterm','icl2_start','icl2_end','icl3_start','icl3_end','cterm','thermo','removals']

    headers = {}
    headers['nterm'] = ['From TM1','hits','Homology levels','Fusions']
    headers['icl2_start'] = ['Start position','hits','Homology levels','PDB codes']
    headers['icl2_end'] = ['End position','hits','Homology levels','PDB codes']
    headers['icl3_start'] = ['Start position','hits','Homology levels','PDB codes']
    headers['icl3_end'] = ['End position','hits','Homology levels','PDB codes']
    headers['cterm'] = ['From TM8','hits','Homology levels']
    headers['thermo'] = ['Generic position','Mutation','hits','methods']
    headers['removals'] = ['segment','mutation','type','subtype']

    data = request.POST['d']
    data = json.loads(data)

    #EXCEL SOLUTION
    output = BytesIO()
    workbook = xlsxwriter.Workbook(output)

    for name in sheets:
        values = data[name]
        if len(values)==0:
            continue
        worksheet = workbook.add_worksheet(name)
        col = 0
        for h in headers[name]:
            worksheet.write(0, col, h)
            col += 1
        row = 1
        for d in values:
            col = 0
            #print(d)
            # for h in headers:
            #     worksheet.write(row, col, d[h])
            #     col += 1
            for c in d:
                #print(c)
                if isinstance(c, list):
                    c = ",".join(c)
                worksheet.write(row, col, c)
                col += 1
            row += 1
    workbook.close()
    output.seek(0)
    xlsx_data = output.read()

    ts = time.time()

    cache.set(ts,xlsx_data,30)
    response = HttpResponse(ts)
    return response

@csrf_exempt
def ExportExcelModifications(request):
    """Convert json file to excel file"""
    headers = ['#','type', 'method', 'range', 'info','insert_location','order','from','to','sequence','fixed','extra']

    #EXCEL SOLUTION
    output = BytesIO()
    workbook = xlsxwriter.Workbook(output)

    if 'd' in request.POST:
        data = request.POST['d']
        data = json.loads(data)

        worksheet = workbook.add_worksheet("modifications")
        row = 1
        index = {}
        col = 0
        for h in headers:
            worksheet.write(0, col, h)
            index[h] = col
            col += 1
        number = 0
        for mod in data:
            worksheet.write(row, 0, str(number))
            number += 1
            for m,v in mod.items():
                if isinstance(v, list) and m=='range' and len(v)>1:
                    #v = ",".join(str(x) for x in v)
                    v = str(v[0])+"-"+str(v[-1]) #first and last
                elif isinstance(v, list):
                    v = ",".join(str(x) for x in v)
                if m in index:
                    worksheet.write(row, index[m], str(v))
                else:
                    print('No column for '+m)
            row += 1
    elif 'm' in request.POST:
        datas = request.POST['m']
        datas = json.loads(datas)
        worksheet = workbook.add_worksheet("modifications")
        row = 0
        for i, data in enumerate(datas):

            worksheet.write(row, 0, "Construct Number #"+str(i+1))
            row += 1
            index = {}
            col = 0
            for h in headers:
                worksheet.write(row, col, h)
                index[h] = col
                col += 1
            number = 0
            row += 1
            for mod in data:
                if len(mod)>0:
                    worksheet.write(row, 0, str(number))
                    number += 1
                    for m,v in mod.items():
                        if isinstance(v, list) and m=='range' and len(v)>1:
                            #v = ",".join(str(x) for x in v)
                            v = str(v[0])+"-"+str(v[-1]) #first and last
                        elif isinstance(v, list):
                            v = ",".join(str(x) for x in v)
                        if m in index:
                            worksheet.write(row, index[m], str(v))
                        else:
                            print('No column for '+m)
                row += 1
            row += 1

    worksheet2 = workbook.add_worksheet("FASTA SEQUENCES")
    # worksheet2.write(0, 0, "sequences")
    row = 0

    sequences = request.POST['s']
    sequences = json.loads(sequences)
    for s in sequences:
        # worksheet2.write(row, 0, "Modifications # used")
        # worksheet2.write(row, 1, ' '.join(s[0]))
        # row += 1
        worksheet2.write(row, 0, ">" + s[1] + "[Modifications:" + ' '.join(s[0]) +"]")
        row += 1
        #worksheet2.write(row, 0, "Sequence")
        worksheet2.write(row, 0, s[2])
        row += 1

    worksheet3 = workbook.add_worksheet("FASTA SEQUENCES BLOCK")
    # worksheet2.write(0, 0, "sequences")
    row = 0

    sequences = request.POST['s']
    sequences = json.loads(sequences)
    for s in sequences:
        # worksheet2.write(row, 0, "Modifications # used")
        # worksheet2.write(row, 1, ' '.join(s[0]))
        # row += 1
        worksheet3.write(row, 0, ">" + s[1] + "[Modifications:" + ' '.join(s[0]) +"]")
        row += 1
        #worksheet2.write(row, 0, "Sequence")
        worksheet3.write(row, 0, s[3])
        row += 1

    workbook.close()
    output.seek(0)
    xlsx_data = output.read()

    ts = time.time()

    cache.set(ts,xlsx_data,30)
    response = HttpResponse(ts)
    return response

def ExportExcelDownload(request, ts, entry_name):
    """Convert json file to excel file"""

    response = HttpResponse(cache.get(ts),content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = 'attachment; filename='+entry_name+'.xlsx' #% 'mutations'

    return response

@csrf_exempt
def ImportExcel(request, **response_kwargs):
    """Recieves excel, outputs json"""
    o = []
    if request.method == 'POST':
        form = FileUploadForm(data=request.POST, files=request.FILES)
        if form.is_valid():
            workbook = xlrd.open_workbook(file_contents=request.FILES['file_source'].read())
            worksheets = workbook.sheet_names()
            for worksheet_name in worksheets:
                worksheet = workbook.sheet_by_name(worksheet_name)
                # Only load modifications
                if worksheet_name!='modifications':
                    continue
                num_rows = worksheet.nrows - 1
                num_cells = worksheet.ncols - 1
                curr_row = 0 #skip first, otherwise -1
                while curr_row < num_rows:
                    curr_row += 1
                    #row = worksheet.row(curr_row)
                    curr_cell = -1
                    temprow = []
                    if worksheet.cell_value(curr_row, 0) == '': #if empty
                        continue
                    while curr_cell < num_cells:
                        curr_cell += 1
                        #cell_type = worksheet.cell_type(curr_row, curr_cell)
                        cell_value = worksheet.cell_value(curr_row, curr_cell)
                        temprow.append(cell_value)
                    o.append(temprow)
            jsondata = json.dumps(o)
            response_kwargs['content_type'] = 'application/json'
            return HttpResponse(jsondata, **response_kwargs)

        else:
            pass
    jsondata = json.dumps(o)
    response_kwargs['content_type'] = 'application/json'
    return HttpResponse(jsondata, **response_kwargs)


It is okay to show that you are not looking for a wife, not yet but you are indeed looking for a girl. I figured I already outsourced my online marketing efforts, so why not my online dating?
After 10, hours invested, and over in-person dates thanks Microsoft ExcelI quietly achieved mastery. You may offend a Russian girl if you seem indifferent. If you are looking for someone who will make your life exciting, but steady and happy, you have chosen the right place.
It comes from the ability to solve problems and the courage to face them. I do not want to sound unfounded but these single ladies are indeed gorgeous. Neznalek online dating often they are described as perfect respectful spouses and reliable moms.
From the time consuming, tedious messages that result in dead-ends, to the intimidating number of thirsty suitors competing for her attention. Which, may or may not go well. The thing is neznalek online dating such an experience often results in feeling desperate and lonely.
Russian girls have extremely good intuition. Just try and you feel that dating is great at any age and in any part of the globe.
Russian traditions develop little Russian girls into caring mothers and wives. Finally, we have to ask for the date at the right time. More dates with attractive women, to be precise. Do not make them feel like they have competitors in single dating.
Just to keep the interaction alive. The truth is that they are indeed tender and attentive. Do not hide if you are not intended to start anything serious. Therefore, be sincere about your plans and intentions.
Show what you want. Online dating service Our dating service features both men and women who make their search internationally and find their prospective long-term partners in different parts of the world.
Here at PDA, everyone is welcome. The next step was to let someone else take over.
Do not manipulate those girls. It sometimes seems they are born to be a family hearth. You must have experienced bad dates more than once. Online dating network allow millions of singles to meet potential partners they otherwise would not have met.
However, you should be careful when playing with them.
Our date coaches will sort you out. D flakes at the slightest misstep. Online dating enables attractive women to be almost impossibly selective, and act like A. These girls often present their emotions to a man, in order to encourage him to act, exaggerating things in the process.
How did this come to be? The latest internet dating technologies make the process easy and safe, protecting your privacy and you can make contact via our dating service webmail until you feel the right moment to get more personal.
From now on you are in good and professional hands. So be a soft pillow for her. We offer great number of opportunities to initiate communication and also receive contacts from our growing international singles database.
Calm her down and support her if she shows her emotions. Take a moment, put distractions to the side, and get to know us. We will do our best to find a perfect match for you and make both you and one of our single Russian girls happy.
Not too quickly as to scare the cat, nor too long that she gets bored, swooped up by a another guy, or a thousand other reasons for a fruitless outcome. What is so special about these beautiful Russian singles? The positive thinking does not mean they ignore problems or hard decisions and live happily.
I do not want to sound sexist but these girls know how to make the place cozy, clean and full of delicious meals. While as men, we have to perform. They mostly do it subconsciously.


Home › Products › Seahorse Safe Fish › Firefish Goby (Nemateleotris magnifica), 2.0" to 2.5"
The Firefish Goby is a white fish with a bright yellow tinted head and an orange/red posterior. They are full of personality as they flit around aquariums, burrowing into the sand and darting into hiding places whenever they feel threatened.
They are an easy-to-care for fish that reside peacefully in reef aquariums. They can be aggressive to others of the same species so it is best not to overcrowd your aquarium. Firefish Goby are popular for their small adult size of up to 3 inches long. It is important to keep your aquarium covered as Gobys can leap out of the tank. They readily eat most appropriately-sized frozen foods including brine or mysis shrimp.
Firefish Goby (Nemateleotris magnifica), 2.0" to 2.5" has been added to your cart!


Sony took dominance in Japan's weekly sales chart last week, thanks in large part to the PlayStation 4 price cut, Konami's Pro Evolution Soccer 2016 and Gust's Yoru no Nai Kuni.
PlayStation Vita's Tokyo Xanadu topped the software chart with 88,879 copies sold, with Nintendo's Pircross 3D 2 debuting in ninth place by shifting 30,468 copies.
As for hardware, the PlayStation 4 saw a significant boost from 4,071 units to 46,177 whereas PlayStation Vita actually saw a decline despite Tokyo Xanadu's performance. Similar declines were seen with the Nintendo 3DS family of systems that drew 24,350 unit sales, while Wii U sold 12,843 units.


text:
Bugatti declassified the final version of La Voiture Noire priced at 11 million euros
Bugatti has unveiled the final version of the unique La Voiture Noire, produced only in a single copy.
The hypercar was first shown in 2019, but it has only been fully prepared for the buyer. The car is estimated at 11 million euros.
For the last two years, Bugatti La Voiture Noire was the most expensive car worldwide, until the appearance a month ago of the Rolls-Royce Boat Tail convertible (this car is estimated at 20 million pounds sterling.
Bugatti La Voiture Noire coupe made its debut in Geneva 2019 to celebrate the Frenchman's 110th anniversary. The car is made on the Chiron model base, but the differences are increased wheelbase, a completely different front end, and stern with six pipes.
Technically the Bugatti La Voiture Noire is equipped with a W16 8.0 liters engine with four turbocharged compressors with 1500 horses and 1600 Nm.
Bugatti news
Bugatti pictures 943

redpajama_set_name: RedPajamaCommonCrawl


THANKS TO LEGAL AID, I kept three young children from being made street homeless.
This entry was posted in Clients with mental health problems, Housing law and tagged cuts to legal aid, Legal aid, save legal aid, save UK justice by thanks2legalaid. Bookmark the permalink.


Where there's a will there's a way, and that's exactly what Lee Cimino found out. The 30-year-old, who is from the UK, is a frequent flyer with Ryanair and has been loyal to the airline since he can remember. Cimino booked his flight to Belfast two days before the airline decided to make changes to their baggage fees, so he wanted to come up with an idea to avoid paying for the carry-on.
Until recently, any passenger flying Ryanair could bring a bag on board free of charge if it didn't exceed a certain size and weight. With the newly updated cabin bag policy, one must now pay between £6 and £8 ($7.88 and $10.51) for each bag depending on the size. That means passengers can only bring one small personal bag on board that fits under the seat in front of you. So, like any other human who wishes to save money, Cimino decided to trick the system and avoid all fees possible. How? By grabbing an oversized old coat and sewing all of his clothes inside. Genius, pure genius!
Cimino captured the whole process in a Facebook video, showing exactly how he managed to pull off his plan. He found a tailor who helped him create pockets using some of his old clothes and sewing them inside the sleeves. I have to admit I am pretty impressed with this whole situation because he actually managed to fit everything inside! The coat included everything from a change of clothes, his shoes, a toothbrush, and toiletries.
Safe to say he looked ridiculous with the coat on due to it being 3 times bigger than it should, but hey, it worked. He kind of reminded me of Joey from Friends when he decides to put on all of Chandler's clothes to get back at him.
But, although he was pretty smart and didn't have to pay for that extra fee, there is a small problem here. He did have to go to the trouble to pay someone to sew everything on the coat. So…you see my point here? It might have been easier to just use a carry-on bag and pay the fee, bud.
But hey, whatever makes you happy, right? Time to go buy a bulky coat!


text:
Home / Spoken Word / Poetry / The Great Poets (Unabridged)
The Great Poets (Unabridged)
Today Byron is regarded as the ultimate romantic- a rebel, a Casanova and a man of intense, brooding passion. He was the most famous literary man of his time, and his poetry, endlessly witty and often insightful, was immensely popular and hugely influential. From the delicate romanticism of She Walks in Beauty to the evocative reflections of So We'll Go No More a Roving, Byron's poems such as Destruction of Sennacherib, a reimagining of the biblical story of Sennacherib, Prometheus, a sardonic poem about the Greek gods, and Darkness, an apocalyptic story of the last man on earth, also included here, reveal Byron to be a poet of great range and variety. "Mad, bad and dangerous to know," Lord Byron was without equal in English literature.
NA0334
NAXOS AUDIO BOOKS
Non-Classical Artist Beale, Simon Russell
The Great Poets 01:15:00
1 She Walks In Beauty 00:01:09 Beale, Simon Russell
2 The Destruction Of Sennacherib 00:01:28 Beale, Simon Russell
3 Darkness 00:04:40 Beale, Simon Russell
4 The Dream 00:11:05 Beale, Simon Russell
5 Solitude 00:01:17 Beale, Simon Russell
6 So We'll Go No More a-Roving 00:00:37 Beale, Simon Russell
7 When We Two Parted 00:01:16 Beale, Simon Russell
8 Written After Swimming From Sestos To Abydos 00:01:07 Beale, Simon Russell
9 Oh! Weep for Those 00:00:56 Beale, Simon Russell
10 To Caroline 00:01:23 Beale, Simon Russell
11 Love's Last Adieu 00:02:53 Beale, Simon Russell
12 On Chillon 00:05:00 Beale, Simon Russell
13 To A Lady 00:02:02 Beale, Simon Russell
14 Stanzas For Music: There's Not A Joy The World Can 00:07:01 Beale, Simon Russell
15 Prometheus 00:05:02 Beale, Simon Russell
16 It Is the Hour 00:07:00 Beale, Simon Russell
17 And Thou Art Dead, As Young and Fair 00:03:03 Beale, Simon Russell
18 To M 00:04:01 Beale, Simon Russell
19 Stanzas To A Lady, On Leaving England 00:02:03 Beale, Simon Russell
20 Lines Inscribed Upon A Cup Formed From A Skull 00:02:01 Beale, Simon Russell
21 Remind Me Not, Remind Me Not 00:01:01 Beale, Simon Russell
22 To Romance 00:02:03 Beale, Simon Russell
23 My Soul is Dark 00:02:00 Beale, Simon Russell
24 Sonnet - to Genevra 00:02:01 Beale, Simon Russell
25 To Time 00:02:02 Beale, Simon Russell
26 Adieu, Adieu! My Native Land 00:02:00 Beale, Simon Russell
27 Farewell To The Muse 00:02:02 Beale, Simon Russell
28 I Saw Thee Weep 00:02:00 Beale, Simon Russell
29 Ode to Napoleon Bonaparte 00:02:08 Beale, Simon Russell
30 Remember Him, Whom Passion's Power 00:02:02 Beale, Simon Russell
31 Churchill's Grave 00:02:02 Beale, Simon Russell
32 And Wilt Thou Weep When I Am Low? 00:02:01 Beale, Simon Russell
If you like The Great Poets (Unabridged), please tell your friends! You can easily share this page directly on Facebook, Twitter and via e-mail below.
The Great Poets: The War Poetry of Wilfred Owen
The Great Poets: John Clare
The Great Poets: John Masefield
The Prelude (Unabridged)
The Kalevala (Unabridged) NA0124 2/1/2013 $66.58 ($73.98)
The Metaphysical Poets NA0089 8/1/2012 $13.48 ($14.98)
This item has been discontinued, and will no longer be available once out of stock.
CLASSIC POEMS FOR BOYS (Unabridged) NA0102 7/1/2012 $13.48 ($14.98)
Metamorphoses (Unabridged) NA0107 7/1/2012 $80.98 ($89.98)
Evgenii Onegin (Unabridged) NA0077 5/1/2012 $26.08 ($28.98)
A Shropshire Lad (Unabridged) NA0047 6/1/2011 $13.48 ($14.98)
Also Ordered
Flowers of Evil (Unabridged)
Buy + $26.08 ($28.98)
The Great Poets: Walt Whitman (Unabridged)
BECKETT, S.: Waiting for Godot (Unabridged)
SEVEN AGES - An Anthology of Poetry with Music


LAS VEGAS, Nevada -- (PRESS RELEASE) -- From Las Vegas to Reno, from Elko to Laughlin and everywhere in between, players in casinos across Nevada can now become instant millionaires, thanks to Aristocrat's new statewide penny progressive, Millioni$er.
Currently, 760 Millioni$er penny games are in play throughout the state and across the U.S., and 385 games in Nevada will all be linked by October to create a statewide progressive jackpot that offers players the chance to win more than $1 million playing a penny slot.
Millioni$er has already created 28 millionaires since 2004, and with the new statewide progressive jackpot, many more players could soon be added to the growing list of Millioni$er millionaires.
"This is an exciting time for all types of players in casinos throughout Nevada! By playing the new Millioni$er progressive product, players now have a chance at becoming a millionaire by playing a penny slot!" said Aristocrat Senior Vice President of Sales Sean Evans.
Millioni$er is a Hyperlink(R) progressive and sports a patented second-screen feature with four different jackpot levels that can be triggered randomly during game play. The four tiered progressives give Millioni$er a higher hit frequency so players win jackpots more often.
Aristocrat launches Millioni$er in Nevada is republished from CasinoVendors.com.


iBurbia Studios is a fantastic venue choice for companies looking for somewhere to brainstorm, meet, have creative sessions and enjoy away-days with a difference. This versatile venue may be small, but it plays host to state of the art technologies, spacious and contemporary meeting rooms and light, airy events spaces.
The Blue Suite is arranged around a central room, with several smaller break out spaces attached. Ideal for sessions that require a lot of individual private spaces, there's also a large social area that offers direct access to all the smaller rooms in the suite – The Indigo & Iris Rooms, and the Cobalt Room. Offering a comfortable flow, a layout that can be configured to suit your needs and an abundance of AV gear in each space, this is a fantastic all-rounder venue for an important away-day.
The Green Suite is also arranged around a central social space, and like the Blue Suite, you can configure a layout for up to 20 people in classroom, cabaret, boardroom, lounge or theatre style. Two small breakout rooms also reside within this suite (including an interactive media room, pictured), and you'll be provided with presentation technologies, flipcharts, stationery and plasma screens with all manner of plug-ins, so presentations are made easy yet still delivered efficiently and professionally.
The Lemon Room is one of these smaller break out rooms, and is specifically designed for more informal, creative meetings. A whiteboard calls this room home – a brilliant tool for on-the-spot brainstorming and much more effective than a screen or keyboard, and in The Lime Room, a small boardroom table and comfortable lounge style chairs offer a welcoming and adaptable space. Again, plasma screens are standard in every room.
iBurbia prides itself on providing an unrivalled standard of AV technology, digital services and IT support in the UK. On-site parking and bespoke catering are yet more appealing features of iBurbia, and Function Fixers can also recommend a huge range of venues for evening receptions, restaurants and bars in the local area for a spot of relaxation after what's certain to be a very productive day!
Call us now for your chance to enjoy this fabulous venue at a snippet of the market price!


text:
Portocala australiană (Capparis mitchellii Lindl.) este o plantă nativă din Australia. Nu este înrudită cu portocala. Numele ei pentru aborigenii din centrul Australiei este "merne atwakeye".

Portocala australiană este un fruct delicios. Aborigenii îl foloseau înaintea europenilor. Este verde când se coace, iar în interior este galben sau portocaliu, cu gust aromat.

Note

Legături externe
ZipcodeZoo.com
Botanica Sistematica

Capparaceae
Fructe
Flora Australiei

redpajama_set_name: RedPajamaWikipedia


text:
Гранха ла Фама има више значења:

 Гранха ла Фама (Делисијас), насеље у савезној држави Чивава у Мексику
 Гранха ла Фама (Кулијакан), насеље у савезној држави Синалоа у Мексику


text:
Q: How do I specify 16 slots in Quake 3 Is there a command that I can run in-game to open up more slots during a networked game of Quake 3 Arena?

A: Add this line to your server.cfg:
seta sv_maxclients 16

From here:

sv_maxclients 16 - maximum number of players on the server.

You can try using rcon to change this while the server is running:
/rcon seta sv_maxclients 16

..but even if that is possible normally, most hosting companies disallow that because you pay by the number of server-slots.

redpajama_set_name: RedPajamaStackExchange


It started back in a coffee shop just around the corner from Georgetown Cupcakes (don't tempt me like that!! Ha!). Chris, Frankie, and I met upstairs to meet and get to know one another. I felt as though I got together with old friends because they were so welcoming and down-to-earth! I fell in love with their love story, their intentions to continue pursuing one another, and the vision of their engagement session and wedding day! I had no idea, though, how much I would continue falling for these two and the bond they share with each other. <3 Undoubtedly, you will see how they were truly designed to be together once you get to know them throughout this blog post!!!
We got together for their engagement portraits last fall at the always-gorgeous Shenandoah Valley! I got to photograph them in their element and had the opportunity to meet their fur babe, Chloe! She had an important role during their wedding day too. So I'm glad she was able to be a special part of their engagement and wedding celebrations. Clearly, she means so much to them!!! 🙂 During our time together, I had the chance to get to know these two even better. Oh my gosh, their sense of humor is undeniable! No wonder they are so liked and loved by many!!! If you want to get to know them better and see for yourself how hilarious these two are, check out their GORGEOUS engagement portraits as well as their love stories from their perspectives HERE!
** Warning … I had WAY too many favorites from this wedding!!! SO many beautiful, unique details that I thought was fun to share with you all!! So grab a cup of coffee and enjoy!!!
WHEW! Let me tell you, the time before the ceremony was a WHIRLWIND of an afternoon. We had a lot to cover in a short amount of time, but we made it work despite the threat of rain!! No rain was going to ruin Chris and Frankie's joyful day. And when I say joyful … You better believe there wasn't one wasted second of having fun! 🙂 It was absolutely JOY-FILLED!!! The vendor team and I knew we were in for a treat last Saturday!!
Also, look a little closer — Frankie made map flowers!!! Seriously, she's amazing!!!!
LOOK at that dress!!!!! After Frankie slipped her dress on, the girls squealed and couldn't help but admire the detailing.
Frankie loved the gold glitter on the bottom of her shoes — I wouldn't doubt if she did that herself because she is classy with her DIY projects!!! And as Chris stated, "she goes big every time!" And yes she does, which is why I love it!!!!
To fit in with their custom illustrated card I shared above, they designed this illustrated postcard to send thank yous! What a cute idea! Even her dress is drawn perfectly!
Again, another FABULOUS Frankie DIY project!!! She painted the world map on their Toms along with the "Est. 2018" on the back of them! Cute, unique and totally fitting for this travel inspired wedding!!
Awe, Chris had a way with his words. <3 Gosh, these two were made for each other!!
Chris said, "This is EXACTLY what I imagined you wearing!" Just what every girl wants to hear. 🙂 🙂 🙂 And, naturally, he wanted to take a walk around to check her out, 360! So cute!!!!
I mean, seriously … Look at that happiness!!!!
THIS. CREW. May I go on? They were down to do anythingggggg, and I LOVED it!
Frankie embroidered their wedding day on Chris' socks! Cute idea! Also, love the pops of color!
LOVE this idea!!!! Frankie made paper airplanes attached to the bouquets with the girls' names written on it. I admired every detail Frankie thought of for her special day — Can I hire her creativity for my future wedding, please? 😉 HAHA!
UH! *Pump* UH! *Pump* UH! "*Pump* I like it like that!" HAHAHA!
I don't typically share the "jumping shot" on my blog — But how could I NOT share this epic photo?! Can I photograph this wedding party every weekend? Haha!
I'm SO glad Chris and Frankie said they would take a risk with the rain and have the ceremony outside!!! The sun came out! <3 PTL!
During the ceremony, instead of the typical mixing sand or unity candle, they had soil from Colorado (where they fell in love) and Charlottesville (where they got married) and sprinkled it on this bonsai tree!
Chloe making had a very responsible role holding on to the rings!!! What a great pup!
As if I didn't adore these two enough, they had to recite Alex and my FAVORITE movie, The Greatest Showman!!! YES!
As you'll see in the love sign detail photo later in this blog post, Chris and Frankie have a mission to have a photograph with every LOVE sign in Virginia! 🙂 There are over 100 statewide, and they have tackled 25! Now it can be 26! 🙂 Frankie made this love sign from scratch … Seriously, Frankie … You're amazing!
Also, if you want to see their proposal video involving one of the Virginia love signs … and involves wearing silver gray wigs (LOL!) … Check it out HERE!!!!! SO worth watching!!! You'll see why I instantly fell in love with these two!
Get ready to be INSPIRED by their travel-themed details!
I love how much they love taking photos!!!!
They had guests sign their names on the love locks and lock it on their gold globe! What a cute display to have in their house!!!
I love seeing how they balanced the maroon, grey, and gold color theme with the details! The maroon immediately brought me back to their engagement session when Frankie wore that incredible maroon colored dress!!!
Each guest was given a cute luggage tag. Totally fitting for their rustic, travel-inspired theme!
Every table had a different city Chris and Frankie visited together. The centerpieces weren't the typical floral display, but rather little knick-knack souvenirs from each city!!
This signature drink board was so "them!" HAHAHA!
I'll admit … That "in" wasn't supposed to be crooked, and the bartenders wanted to fix it but couldn't reach it … BUT, I thought it was actually appropriate for it to be out of place. 😉 HA!
Krysta and I looked at each other and thought, "Can we join?!" Haha! Such a fun group!!!!
Thanks to the vendors who made this day so special!!!
Wedding Planner: Elixir Media Co.


For the serious student of Arabic, eyeVocab is essential. Arabic is notoriously difficult to learn, and eyeVocab drastically increases the speed and quality of students' vocabulary comprehension.
Easily accessible glossary; searchable by English, Arabic, or Arabic root.
What's next? We're currently working on an expanded implementation in Modern Standard Arabic that includes Levantine and Egyptian dialects.


text:
post '/sessions' do   #post /users
  p "="*100
  p "hello from NEW LOGIN post /sessions route"
  p "="*100

  @user = User.find_by_email(params[:email])
  p "@user.password #{@user.password} params[:password] #{params[:password]}"
  if @user && @user.password == params[:password]
      session[:user_id] = @user.id

  # if @user = User.authenticate(params[:email], params[:password])
  #   session[:user_id] = @user.id
    p "="*100
    p "hello from NEW LOGIN post /sessions route USER HAS LOGGED IN"
    p "="*100
    redirect "/users/#{session[:user_id]}"
  else
      p "="*100
      p "hello from NEW LOGIN post /sessions route ERRORS"
      p "="*100
      msg = ["User cannot be authenticated"]
      @errors = msg
      @items = Item.all
      erb :'/items/index'
   end
end
#----------------------------------
# NEW: a user registers
#----------------------------------
post '/users' do #post '/users/new'
  p "="*100
  p "hello from NEW REGISTER post /users route"
  p "="*100
	@user = User.new(params[:user])
	@user.password = params[:password]
	p params
	if @user.save
  p "="*100
  p "hello from @user.save"
  p "="*100
		session[:user_id] = @user.id
    	redirect "/users/#{session[:user_id]}"
  	else
    	@errors = @user.errors.full_messages
    	session[:errors] = @errors
    	erb :'/items/index'
  	end
end
#----------------------------------
# SHOW: display user profile (specific details)
#----------------------------------
get '/users/:id' do
  p "="*100
  p "hello from SHOW get /users/:id route"
  p "="*100
	@user = User.find(params[:id])
  session[:user_id] = @user.id
	erb :'users/show'
end
#----------------------------------
# LOG OUT
#----------------------------------
delete '/sessions/:id' do
  p "="*100
  p "hello from delete /sessions/:id route"
  p "="*100
  session[:user_id] = nil
  redirect '/'
end

redpajama_set_name: RedPajamaGithub


I celebrated the 30th anniversary of my 24th birthday last weekend. Well, I didn't so much celebrate it as acknowledge it, the way inmates at the notorious penal colony in French Guiana might have grimly scratched a mark on the side of a coconut tree to memorialize that yet another year had passed since they arrived at that jolly resort destination.
Some people try to turn the age clock back through liposuction or by having their sagging facial skin stapled to the back of their noggins. Others radically change their diets and begin eating nuts and fiber instead of honey-bunches of bacon. A friend told me that when you get over 50, "you gotta go with the grain." He apparently really went with the grain because he seemed to spend an inordinate amount of time in restrooms. As a smart man familiar with the perils of going with too much grain once said, "It's one thing to be regular, another to be UNSTOPPABLE!"
I try not to get depressed at birthdays. A voice in my head says, "Hey, 54 years old is quite young by biblical standards. Methuselah lived to be 969." Then another voice in my head says, "Yeah, but Methuselah's brother Bernie died at age 49." And the other voice says, "Yeah, but he was run over by an ox cart. That doesn't count." And the other voice says, "OK, but the Aztecs rarely lived more than 45 years." And the other voice says, "That's because they ate too much corn and grain and were too regular."
And the voices continue on like a couple of philosophical cage fighters while I refill my wine glass, hum "Happy birthday to me" and consider the age-old question, Just how painful IS liposuction?
Inevitably my innate optimism wins out, and I realize that even in my old, decrepit state, life is good. Much better than the aforementioned alternative. In fact, there's a lot of good to be said about getting older. You aren't as dumb as you were. You know, for instance, that there's some catch to every product sold via TV informercials. Like, that rotisserie machine looks pretty cool, but you know it's going to be hard to clean and will take up too much counter space. I think that's called wisdom.
The thing about living a long, happy life is not to get carried away. Woody Allen said, "I don't want to achieve immortality through my work. I want to achieve immortality through not dying." That would be a good trick. And God knows Woody looks like he's pulling it off. If his jowls drop any farther, he'll have to tuck them into his socks.
When it comes to a long, happy life, wisdom compels us to focus on the "happy" instead of the "long." As Methuselah reportedly said, "Don't worry. Be happy. And watch for ox carts."


We all know no political leader can lie better than the Zionist prime minister Benjamin Netanyahu. Now two Western leaders, US president Donald Trump and British prime minister Theresa May are sharing the title with Netanyahu. All three are proven to be morally corrupt and fear Muslims and Islam the most.
All three also share fear of the emerging influence of the Islamic Republic of Iran on the international stage.
On Friday, London-based Captain SKA, band, released a song (listen below) mocking Theresa May by calling her Liar, Liar, Liar… again and again, is heading to the top of the charts, day it was released and a week before the election despite receiving no airplay from radio stations because of impartiality guidelines.
Captain SKA has promised to donate all revenue from song download to an anti-austerity activism group and UK Food Banks.
Jake Painter, the man behind the Captain SKA song has claimed that he was told by BBC not to go too hard on the Tories.
The song includes several clips of May's speeches, with the chorus: She is Liar, Liar, oh she's a Liar. You cannot trust her, No, No, No, No. It also shows Theresa May holding hands with Donald Trump and chuckling in the House of Commons (British parliament).
The song citing 3.7 million children living in poverty in United Kingdom, lamblast May for making cuts to host of country's institutions including schools and the National Health Service. However, Tory government has £50 million funds to waste on a new Holocaust Museum in London.
Theresa May has repeatedly said: Without Jews, Britain Wouldn't be Britain (Breibart, December 22, 2016 – Israel National News, April 10, 2017).
The song doesn't explicitly support the so-called 'Hamas-loving' Labour leader Jeremy Corbyn. The video ends with captions saying: 8 June, Tories Out.
According to Jewish media, 77% British Jews are voting for the Tories and only 13% to the Corbyn's Labour.
"It's uncomfortable, at least for this author, the way in which the song's demonization of May echoes a host of criticisms lobbed at Hillary Clinton during her 2016 run for President of the United States. It's all well and good to call politicians out for their flaws," Zax said.


Glendale Youth Rugby - Play Rugby in Denver - Colorado Youth Rugby | Rugby Today. Rugby Tomorrow.
Try League Starts April 23rd!
It's game time, and try time! Sign up today!
Mar 3-Apr 11 2019. Rugby starts here with skills, games and scrimmages. Join us Tuesdays & Thursdays from 4:30-5:45pm at Infinity Park.
Apr 23-Jun 22 2019. Try out your rugby skills by playing with Glendale's Youth Teams in Rugby Colorado's Try League. It's game time, and try time.
July 24-28 2019. Take your rugby to the next level at the strongest girls camp. Train with the best at Infinity Park in Glendale, Colorado.
The programming at Glendale Youth Rugby has been shaped and honed over a decade to prepare children of all ages for success in rugby, and life.
Being part of Glendale Youth Rugby is not a singular event. It does not last a day, a week, or even a season. Instead, the programming was conceived as a pathway that young players follow, from kindergarten through high school. Each step along the way adds an additional layer of skills, experience, and knowledge on which players can rely as they progress along the path.
Throughout this journey, coaches, trained specifically for working with children, model the unique rugby ethos: One that values team success through personal excellence while remaining committed to respecting every person on the pitch—especially those donning the colors of the opposing team. The same values that define the youth program permeate every team that calls Infinity Park home and have helped to create the vibrant culture that has attracted thousands of fans.
Children entering the program begin by learning fundamental skills and work to develop the high-level skills that can take them to the next levels of the sport. Glendale Youth Rugby includes a spring try-league, summer flag league, after-school programs, high school programming for girls, and indoor winter play.
In addition to creating exceptional athletes, Glendale Youth Rugby reinforces the sport's inclusive nature, its ability to encourage fitness through participation, and its character-driven values of self-discipline, teamwork, and challenge. With this foundation for rugby-inspired young people, those values promise to have a lifelong home in Glendale.


This Beautiful sun drenched 1bed Penthouse has 4 different exposures and 2 private terraces.
Experience spacious loft living at The Louver House This Boutique development is positioned to take advantage of all that Williamsburg has to offer! Prominently located at the corner of Wythe and Metropolitan near the waterfront ? just two blocks away from Bedford Avenue and a short walk from the Bedford L train that is just one stop from Manhattan. These true lofts are designed to maximize space while offering a motif of indoor and outdoor living. Each loft has at least 2 outdoor spaces. Offering exceptional layouts to enhance your lifestyle. With its bold architecture Louvers is where the building gets its name, The fa?ade of The Louver Condominium is clad in a series of vertical louvers not only designed for their visual appeal but for their functionality as well. This system, custom designed and energy efficient, allows for incredible light and air while providing shade throughout day yet drama and privacy in evenings. As dramatic and unique as the exterior design, so are the interiors of the 13 boutique residences. The Louver Condominium offers an assortment of exceptional layouts to enhance your lifestyle. Each light-enveloped space offers impressive finishes, quality craftsmanship, expansive walls of windows, individually controlled heating and cooling, washer/dryer hook-ups and hardwood floors throughout. Many offer private outdoor spaces as well. At the center of Williamsburg, The Louver Condominium offers a departure from the ordinary, yet epitomizes the energy of this exciting neighborhood. This Beautiful sun drenched 1bed Penthouse has 4 different exposures and 2 private terraces.