text:
from __future__ import division

__author__ = "Kishori M Konwar"
__copyright__ = "Copyright 2013, MetaPathways"
__credits__ = ["r"]
__version__ = "1.0"
__maintainer__ = "Kishori M Konwar"
__status__ = "Release"

try:
    from os import makedirs, sys, remove, rename
    from sys import path
    import re, traceback
    from optparse import OptionParser, OptionGroup
    from glob import glob
    from libs.python_modules.utils.metapathways_utils  import parse_command_line_parameters, fprintf, printf, eprintf
    from libs.python_modules.utils.metapathways_utils  import strip_taxonomy, ShortenrRNAId, ShortenORFId, ShortenContigId, ContigID
    from libs.python_modules.utils.sysutil import getstatusoutput
    from libs.python_modules.utils.utils  import doesFileExist
    from libs.python_modules.utils.errorcodes import error_message, get_error_list, insert_error
    from libs.python_modules.utils.errorcodes  import *

except:
    print """ Could not load some user defined  module functions"""
    print """ Make sure your typed 'source MetaPathwaysrc'"""
    print """ """
    sys.exit(3)

usage=  sys.argv[0] + """ -d dbname1 -b parsed_blastout_for_database1 -w weight_for_database1 [-d dbname2 -b parsed_blastout_for_database2 -w weight_for_database2 ] [ --rRNA_16S  16SrRNA-stats-table ] [ --tRNA tRNA-stats-table ] [ --compact_output ]"""
parser = None

errrocode=8

def createParser():
     global parser
     epilog = """Based on the parsed homology search results against reference protein databases,
               tRNA scan results and matches against the LSU and SSU rRNA sequence databases
               annotations for individual ORFs are created.
               The functional annotation is done by synthesizing  the annotations from the
               reference databases, after removing redundant texts and also making sure
               the annotations from different reference databases are in agreement with each other.
               The taxonomic annotation is done by applying the LCA (lowest common ancestor rule)
               on the hits from the RefSeq NR protein database."""

     epilog = re.sub(r'\s+',' ', epilog)
     parser = OptionParser(usage = usage, epilog = epilog)

     parser.add_option("-b", "--blastoutput", dest="input_blastout", action='append', default=[],
                       help='blastout files in TSV format [at least 1 REQUIRED]')
     parser.add_option("-a", "--algorithm", dest="algorithm", default="BLAST", help="algorithm BLAST or LAST" )

     parser.add_option("-m", "--contig-map", dest="contig_map_file", default=None, help="contig map file" )

     parser.add_option("-d", "--dbasename", dest="database_name", action='append', default=[],
                       help='the database names [at least 1 REQUIRED]')

     parser.add_option("-D", "--blastdir", dest="blastdir",  default=None,
                       help='the blast dir where all the BLAST outputs are located')

     parser.add_option("-s", "--samplename", dest="sample_name",  default=None,
                       help='the sample name')

     parser.add_option("-w", "--weight_for_database", dest="weight_db", action='append', default=[], type='float',
                       help='the map file for the database  [at least 1 REQUIRED]')

     parser.add_option( "--rRNA_16S", dest="rRNA_16S", action="append", default=[],
                       help='the 16s rRNA stats file [OPTIONAL]')

     parser.add_option( "--tRNA", dest="tRNA", action="append", default=[],
                       help='the tRNA stats file [OPTIONAL]')

     cutoffs_group =  OptionGroup(parser, 'Cuttoff Related Options')

     cutoffs_group.add_option("--min_score", dest="min_score", type='float', default=20,
                       help='the minimum bit score cutoff [default = 20 ] ')

     cutoffs_group.add_option("--max_evalue", dest="max_evalue", type='float', default=1e-6,
                       help='the maximum E-value cutoff [ default = 1e-6 ] ')
     cutoffs_group.add_option("--min_length", dest="min_length", type='float', default=30,
                       help='the minimum length of query cutoff [default = 30 ] ')
     cutoffs_group.add_option("--max_length", dest="max_length", type='float', default=10000,
                       help='the maximum length of query cutoff [default = 10000 ] ')

     cutoffs_group.add_option("--min_identity", dest="min_identity", type='float', default=20,
                       help='the minimum identity of query cutoff [default 30 ] ')
     cutoffs_group.add_option("--max_identity", dest="max_identity", type='float', default=100,
                       help='the maximum identity of query cutoff [default = 100 ] ')

     cutoffs_group.add_option("--limit", dest="limit", type='float', default=5,
                       help='max number of hits per query cutoff [default = 5 ] ')

     cutoffs_group.add_option("--min_bsr", dest="min_bsr", type='float', default=0.00,
                       help='minimum BIT SCORE RATIO [default = 0.00 ] ')
     parser.add_option_group(cutoffs_group)

     output_options_group =  OptionGroup(parser, 'Output Options')
     output_options_group.add_option("--tax", dest="taxonomy", action='store_true', default=False,
                       help='add the taxonomy info [useful for refseq] ')
     parser.add_option_group(output_options_group)

     parser.add_option('-o' , "--output_gff", dest="output_gff",
                      help='the output gff file [REQUIRED]')

     parser.add_option('--output-comparative-annotation', dest="output_comparative_annotation",
                      help='the comparative output table [REQUIRED]')

     parser.add_option( "--compact_output", dest="compact_output", action='store_true', default=False,
                      help='compact output [OPTIONAL]')

     parser.add_option('--input_gff', dest='input_gff',
                metavar='INPUT', help='Unannotated gff file [REQUIRED]')

def check_arguments(opts, args):

    return True

    if len(opts.input_blastout) == 0:
         eprintf("There should be at least one blastoutput file\n")
         return False

    if len(opts.database_name) == 0:
         eprintf("There should be at least one database name\n")
         return False

    if len(opts.weight_db) == 0:
         eprint("There should be at least one weight\n")
         return False

    if len(opts.input_blastout) != len(opts.database_name) or\
         len(opts.input_blastout) !=  len(opts.weight_db) :
         eprint("The num of database names, blastoutputs and database map file should be equal\n")
         return False

    if opts.output_gff == None:
       eprintf("Must specify the output gff file\n")
       return False

    if opts.output_comparative_annotation == None:
       eprintf("Must specify the output tables for comparative annotation\n")
       return False

    if opts.input_gff == None:
       eprintf("Must specify the input gff file\n")
       return False

    return True

def insert_attribute(attributes, attribStr):
     rawfields = re.split('=', attribStr)
     if len(rawfields) == 2:
       if rawfields[0].strip().lower()=='id':
           orfid = ShortenORFId(rawfields[1].strip())
           attributes[rawfields[0].strip().lower()] = orfid
       else:
           attributes[rawfields[0].strip().lower()] = rawfields[1].strip()

def split_attributes(str, attributes):
     rawattributes = re.split(';', str)
     for attribStr in rawattributes:
        insert_attribute(attributes, attribStr)

     return attributes

def insert_orf_into_dict(line, contig_dict, shortenorfid=False):
     rawfields = re.split('\t', line)

     fields = []
     for field in rawfields:
        fields.append(field.strip());

     if( len(fields) != 9):
       return

     attributes = {}

     seqname = fields[0]
     try:
       if shortenorfid:
          seqname = ShortenContigId(fields[0])
       else:
          seqname = fields[0]
     except:
       seqname = fields[0]

     attributes['seqname'] =  seqname   # this is a bit of a  duplication
     attributes['source'] =  fields[1]
     attributes['feature'] =  fields[2]
     attributes['start'] =  int(fields[3])
     attributes['end'] =  int(fields[4])

     try:
        attributes['score'] =  float(fields[5])
     except:
        attributes['score'] =  fields[5]

     attributes['strand'] =  fields[6]
     attributes['frame'] =  fields[7]

     split_attributes(fields[8], attributes)

     if not seqname in contig_dict :
       contig_dict[seqname] = []

     contig_dict[seqname].append(attributes)

class GffFileParser(object):

    def __init__(self, gff_filename, shortenorfid=False):
        self.Size = 10000
        self.i=0
        self.orf_dictionary = {}
        self.gff_beg_pattern = re.compile("^#")
        self.lines= []
        self.size=0
        self.shortenorfid = shortenorfid
        try:
           self.gff_file = open( gff_filename,'r')
        except AttributeError:
           eprintf("Cannot read the map file for database : %s\n", dbname)
           exit_process()

    def __iter__(self):
        return self

    def refillBuffer(self):
       self.orf_dictionary = {}
       i = 0
       while i < self.Size:
          line=self.gff_file.readline()
          if not line:
            break
          if self.gff_beg_pattern.search(line):
            continue
          insert_orf_into_dict(line, self.orf_dictionary, self.shortenorfid)
          #print self.orf_dictionary
          i += 1

       self.orfs = self.orf_dictionary.keys()
       self.size = len(self.orfs)
       self.i = 0

    def next(self):
        if self.i == self.size:
           self.refillBuffer()

        if self.size==0:
           self.gff_file.close()
           raise StopIteration()

        #print self.i
        if self.i < self.size:
           self.i = self.i + 1
           return self.orfs[self.i-1]

def process_gff_file(gff_file_name, orf_dictionary):
     try:
        gfffile = open(gff_file_name, 'r')
     except IOError:
        eprintf("Cannot read file %s!\n", gff_file_name)

     gff_lines = gfffile.readlines()
     gff_beg_pattern = re.compile("^#")
     gfffile.close()

     count = 0
     for line in gff_lines:
        line = line.strip()
        if gff_beg_pattern.search(line):
          continue
        insert_orf_into_dict(line, orf_dictionary)
        count += 1
        #if count %10000 == 0:
        #   print count

def create_dictionary(databasemapfile, annot_map):
       seq_beg_pattern = re.compile(">")

       dbmapfile = open( databasemapfile,'r')
       lines=dbmapfile.readlines()
       dbmapfile.close()
       for line in lines:
          if seq_beg_pattern.search(line):
              words = line.rstrip().split()
              name = words[0].replace('>','',1)

              words.pop(0)
              annotation = ' '.join(words)
              annot_map[name]= annotation

def write_annotation_for_orf(outputgff_file, candidatedbname, dbname_weight, results_dictionary, orf_dictionary, contig, candidate_orf_pos,  orfid, compact_output):
   global errorcode
   try:
      fields = [  'source', 'feature', 'start', 'end', 'score', 'strand', 'frame' ]

      output_line= orf_dictionary[contig][candidate_orf_pos]['seqname']

      #if compact_output:
      #output_line = ShortenContigId(output_line)

      for field in fields:
         output_line += "\t"+ str(orf_dictionary[contig][candidate_orf_pos][field])

      #if compact_output:
      try:
         attributes = "ID="+ShortenORFId(orf_dictionary[contig][candidate_orf_pos]['id'])
         attributes += ";" + "locus_tag="+ShortenORFId(orf_dictionary[contig][candidate_orf_pos]['locus_tag'])
      except:
         attributes = "ID="+orf_dictionary[contig][candidate_orf_pos]['id']
         attributes += ";" + "locus_tag="+orf_dictionary[contig][candidate_orf_pos]['locus_tag']

      attributes += ";" + "contig_length="+orf_dictionary[contig][candidate_orf_pos]['contig_length']
      attributes += ";" + "orf_length="+orf_dictionary[contig][candidate_orf_pos]['orf_length']
      attributes += ";" + "partial="+orf_dictionary[contig][candidate_orf_pos]['partial']
      attributes += ";" + "sourcedb="+candidatedbname

      if candidatedbname in results_dictionary:
         attributes += ";" + "annotvalue="+str(results_dictionary[candidatedbname][orfid]['value'])
         attributes += ";" + "ec="+str(results_dictionary[candidatedbname][orfid]['ec'])
         attributes += ";" + "product="+results_dictionary[candidatedbname][orfid]['product']
      else:
         attributes += ";" + "annotvalue="+str('0')
         attributes += ";" + "ec="+str('')
         attributes += ";" + "product="+'hypothetical protein'

      output_line += '\t' + attributes

      if candidatedbname in results_dictionary:
         fprintf(outputgff_file, "%s\n", output_line);
   except:
      eprintf("ERROR : Failure to annotate in contig %s\n", contig)
      #print orf_dictionary[contig]
      print traceback.print_exc(10)
      insert_error(errorcode)
      exit_process()

def  write_16S_tRNA_gene_info(rRNA_dictionary, outputgff_file, tag):
      fields = [  'source', 'feature', 'start', 'end', 'score', 'strand', 'frame' ]
      for rRNA in rRNA_dictionary:
          output_line= rRNA_dictionary[rRNA]['id']
          for field in fields:
             output_line += "\t"+ str(rRNA_dictionary[rRNA][field])

          attributes = "ID="+ShortenORFId(rRNA_dictionary[rRNA]['seqname']) + tag
          attributes += ";" + "locus_tag="+ShortenORFId(rRNA_dictionary[rRNA]['seqname']) + tag
          attributes += ";" + "orf_length=" + str(rRNA_dictionary[rRNA]['orf_length'])
          attributes += ";" + "contig_length=" + str(rRNA_dictionary[rRNA]['contig_length'])
          attributes += ";" + "ec="
          attributes += ";" + "product="+rRNA_dictionary[rRNA]['product']
          output_line += '\t' + attributes
          fprintf(outputgff_file, "%s\n", output_line);

def process_rRNA_16S_stats(rRNA_16S_file, rRNA_16S_dictionary, shortenorfid=False):
     counter_rRNA={}
     if not doesFileExist(rRNA_16S_file):
         return
     try:
        taxonomy_file = open(rRNA_16S_file, 'r')
     except IOError:
        eprintf("Cannot read file %s!\n", rRNA_16S_file)
        exit_process()

     tax_lines = taxonomy_file.readlines()
     similarity_pattern = re.compile("similarity")
     evalue_pattern = re.compile("evalue")
     bitscore_pattern = re.compile("bitscore")
     taxonomy_pattern = re.compile("taxonomy")
     headerScanned = False
     for line in tax_lines:
         if headerScanned == False:
            if similarity_pattern.search(line) and evalue_pattern.search(line) and bitscore_pattern.search(line) and  taxonomy_pattern.search(line):
                headerScanned = True
            continue
         fields = [ x.strip() for x in line.split('\t') ]
         if len(fields) >=6:

           if shortenorfid:
              name = get_sequence_number(fields[0])
           else:
              name = fields[0]

           if not name in counter_rRNA:
              counter_rRNA[name] =0

           _name = name + "_" + str(counter_rRNA[name])
           counter_rRNA[name] = counter_rRNA[name]  + 1

           if fields[1]!='-':
              rRNA_16S_dictionary[_name] =  [ fields[1], fields[2], fields[5] ]
           else:
              if len(fields) >=12:
                 if fields[7]!='-':
                     rRNA_16S_dictionary[_name] =  [ fields[7], fields[8], fields[11] ]

     taxonomy_file.close()

def get_sequence_number(line):
      seqnamePATT = re.compile(r'[\S]+_(\d+)$')
      result = seqnamePATT.search(line.strip())
      if result:
         return result.group(1)
      return  line

def process_tRNA_stats(tRNA_stats_file, tRNA_dictionary, shortenorfid=False):
     counter_tRNA={}
     try:
        tRNA_file = open(tRNA_stats_file, 'r')
     except IOError:
        eprintf("Cannot read file %s!\n", tRNA_stats_file)
        exit_process()
     tRNA_lines = tRNA_file.readlines()

     sequence_name_pattern = re.compile("sequence name", re.I)
     number_pattern = re.compile("number", re.I)

     headerScanned = False
     for line in tRNA_lines:
         if number_pattern.search(line):
            continue
         if headerScanned == False:
            if sequence_name_pattern.search(line):
                headerScanned = True
            continue
         fields = [ x.strip() for x in line.split('\t') ]
         if len(fields) >=6:

              if shortenorfid:
                 name = get_sequence_number(fields[0])
              else:
                 name = fields[0]
              if not name in counter_tRNA:
                 counter_tRNA[name] =0

              _name = name + "_" + str(counter_tRNA[name])
              counter_tRNA[name] = counter_tRNA[name] +1

              tRNA_dictionary[_name] =  [ fields[3], fields[4], fields[5], fields[1] ]

# this adds the features and attributes to  be added to the gff file format for the tRNA genes
def add_tRNA_genes(tRNA_dictionary, tRNA_gff_dictionary, contig_lengths) :

     for tRNA in tRNA_dictionary:
        try:
           orf_length = abs(int( tRNA_dictionary[tRNA][1] )-int( tRNA_dictionary[tRNA][0] )) + 1
        except:
           orf_length = 0

        if tRNA in  contig_lengths:
           contig_length = contig_lengths[tRNA]
        else:
           contig_length = 0

        dict = { 'id':ContigID(tRNA), 'seqname': tRNA, 'start':str(tRNA_dictionary[tRNA][0]), 'end':str(tRNA_dictionary[tRNA][1]),\
                 'strand':tRNA_dictionary[tRNA][2], 'score':" ", 'orf_length':str(orf_length),\
                 'contig_length':str(contig_length),\
                 'feature':'tRNA', 'source':'tranScan-1.4', 'frame':0, 'product':'tRNA-' + tRNA_dictionary[tRNA][3], 'ec':'' }
        tRNA_gff_dictionary[tRNA] = dict.copy()

# this adds the features and attributes to  be added to the gff file format for the 16S rRNA genes
def add_16S_genes(rRNA_16S_dictionary, rRNA_dictionary, contig_lengths) :

    for rRNA in rRNA_16S_dictionary:
        #print rRNA
        try:
           orf_length = abs(int( tRNA_dictionary[rRNA][1] )-int( tRNA_dictionary[rRNA][0] )) + 1
        except:
           orf_length = 0

        if rRNA in  contig_lengths:
           contig_length = contig_lengths[rRNA]
        else:
           contig_length = 0

        dict = {
                 'id':ContigID(rRNA), 'seqname': rRNA, 'start':str(rRNA_16S_dictionary[rRNA][0]), 'end':str(rRNA_16S_dictionary[rRNA][1]),\
                 'strand':'+', 'score':str(rRNA_16S_dictionary[rRNA][2]),  'orf_length':str(orf_length), 'contig_length':str(contig_length),\
                 'feature':'rRNA', 'source':'BLAST Search', 'frame':0, 'product':'16S rRNA', 'ec':''
               }
        rRNA_dictionary[rRNA] = dict.copy()

def create_annotation(dbname_weight, results_dictionary, input_gff,  rRNA_16S_stats_files, tRNA_stats_files,  output_gff, output_comparative_annotation, contig_lengths, compact_output = False):
    orf_dictionary={}
#    process_gff_file(input_gff, orf_dictionary)
    gffreader = GffFileParser(input_gff)

    output_gff_tmp = output_gff + ".tmp"
    outputgff_file = open( output_gff_tmp, 'w')

    output_comp_annot_file1 = open( output_comparative_annotation + '.1.txt', 'w')
    output_comp_annot_file2 = open( output_comparative_annotation + '.2.txt', 'w')

    output_comp_annot_file1_Str = 'orf_id\tref dbname\tEC\tproduct\tvalue'
    fprintf(output_comp_annot_file1,'%s\n', output_comp_annot_file1_Str)

    output_comp_annot_file2_Str = 'orf_id'
    dbnames = dbname_weight.keys()
    for dbname in dbnames:
         weight = dbname_weight[dbname]
         output_comp_annot_file2_Str += '\t{0}(EC) \t{0}(product)\t{0}(value)'.format(dbname)
    fprintf(output_comp_annot_file2,'%s\n', output_comp_annot_file2_Str)

#    gffreader = GffReader(input_gff)
   # for dbname in dbnames:
   #   print dbname, len(results_dictionary[dbname].keys())
   #   print results_dictionary[dbname].keys()
    values= {}
    i = 0
    for contig in  gffreader:
       count = 0
       for orf in  gffreader.orf_dictionary[contig]:
         for dbname in dbnames:
           values[dbname] =0.0001

         success =False
         output_comp_annot_file1_Str = ''
         output_comp_annot_file2_Str = ''
         for dbname in dbnames:
            weight = dbname_weight[dbname]
            orf_id = orf['id']

            if orf_id in results_dictionary[dbname]:

                if values[dbname] < results_dictionary[dbname][orf_id]['value']:
                    values[dbname] = results_dictionary[dbname][orf_id]['value']
    #                print value, dbname
                    candidatedbname=dbname
                    success =True
                    candidate_orf_pos = count

                    if output_comp_annot_file1_Str:
                        output_comp_annot_file1_Str += '{0}\t{1}\t{2}\t{3}\t{4}\n'.format('', dbname,\
                               results_dictionary[dbname][orf['id']]['ec'],\
                               results_dictionary[dbname][orf['id']]['product'],\
                               str(results_dictionary[dbname][orf['id']]['value']*float(weight)))
                    else:
                        output_comp_annot_file1_Str += '{0}\t{1}\t{2}\t{3}\t{4}\n'.format(orf_id, dbname,\
                               results_dictionary[dbname][orf['id']]['ec'],\
                               results_dictionary[dbname][orf['id']]['product'],\
                               str(results_dictionary[dbname][orf['id']]['value']*float(weight)))

                    if output_comp_annot_file2_Str:
                        output_comp_annot_file2_Str += '\t{0}\t{1}\t{2}'.format(\
                               results_dictionary[dbname][orf['id']]['ec'],\
                               results_dictionary[dbname][orf['id']]['product'],\
                               str(results_dictionary[dbname][orf['id']]['value']*float(weight)))
                    else:
                        output_comp_annot_file2_Str += '{0}\t{1}\t{2}\t{3}'.format(orf_id,
                               results_dictionary[dbname][orf['id']]['ec'],\
                               results_dictionary[dbname][orf['id']]['product'],\
                               str(results_dictionary[dbname][orf['id']]['value']*float(weight)))

            else:
                if not output_comp_annot_file1_Str:
                   output_comp_annot_file1_Str += '{0}\t{1}\t{2}\t{3}\t{4}\n'.format(orf_id, '','','','')

                if output_comp_annot_file2_Str:
                   output_comp_annot_file2_Str += '\t{0}\t{1}\t{2}'.format('', '','')
                else:
                   output_comp_annot_file2_Str += '{0}\t{1}\t{2}\t{3}'.format(orf_id, '','','','')

         # end of for all dbname

         if success:  # there was a database hit
            fprintf(output_comp_annot_file1,'%s\n', output_comp_annot_file1_Str)
            fprintf(output_comp_annot_file2,'%s\n', output_comp_annot_file2_Str)
            write_annotation_for_orf(outputgff_file, candidatedbname, dbname_weight, results_dictionary, gffreader.orf_dictionary, contig, candidate_orf_pos,  orf_id, compact_output=compact_output)
         else:   # if it was not  a hit then it is a hypothetical protein
            #print gffreader.orf_dictionary
            write_annotation_for_orf(outputgff_file, 'None', '0', results_dictionary, gffreader.orf_dictionary, contig, count, orf_id, compact_output = compact_output)

         count +=1  #move to the next orf

       #del orf_dictionary[contig]
    output_comp_annot_file1.close()
    output_comp_annot_file2.close()

    # now deal with the rRNA sequences  if there is rRNA stats file
    if len(rRNA_16S_stats_files) > 0 and contig_lengths :
       rRNA_16S_dictionary={}
       for rRNA_16S_stats_file in rRNA_16S_stats_files:
          process_rRNA_16S_stats(rRNA_16S_stats_file, rRNA_16S_dictionary)

       rRNA_dictionary = {}
       add_16S_genes(rRNA_16S_dictionary, rRNA_dictionary, contig_lengths)
       write_16S_tRNA_gene_info(rRNA_dictionary, outputgff_file, '_rRNA')

    # now deal with the tRNA sequences  if there is tRNA stats file
    if len(tRNA_stats_files) > 0 and contig_lengths:
       tRNA_dictionary={}
       for tRNA_stats_file in tRNA_stats_files:
          process_tRNA_stats(tRNA_stats_file, tRNA_dictionary)

       tRNA_gff_dictionary = {}
       add_tRNA_genes(tRNA_dictionary, tRNA_gff_dictionary, contig_lengths)
       write_16S_tRNA_gene_info(tRNA_gff_dictionary, outputgff_file, '_tRNA')
       #print tRNA_dictionary

    outputgff_file.close()
    rename(output_gff_tmp, output_gff)

def process_product(product, database, similarity_threshold=0.9):
    """Returns the best set of products from the list of (*database*,
    *product*) tuples *products*.

    Each product in the set is first trimmed down, removing database-specific
    information.

    The set is then determined by first sorting the products by length
    (ascending), and then, for each product, sequentially applying the longest
    common substring algorithm to determine the similarity between the product
    and already determined products. If this similarity is greater than the
    specified *similarity_threshold*, the longer of the two products is chosen
    to be a determined product.
    """

    processed_product = ''

    # COG
    if database == 'cog':
        results = re.search(r'Function: (.+?) #', product)
        if results:
           processed_product=results.group(1)

    # KEGG: split and process

    elif database == 'kegg':
        kegg_products = re.split(r'\s*;\s+', product)
        for kegg_product in kegg_products:
            # Toss out organism:ID pairs, gene names, and KO IDs
            kegg_product = re.sub(r'^lcl[|]', '', kegg_product)
            kegg_product = re.sub(r'[a-z]{3}:\S+', '', kegg_product)
            kegg_product = kegg_product.strip()
            kegg_product = re.sub(r'(, \b[a-z]{3}[A-Z]?\b)+', '', kegg_product)
            kegg_product = re.sub(r'^\b[a-z]{3}[A-Z]?\b', '', kegg_product)
            # get KO number
            kegg_product = re.sub(r'\bK\d{5}\b', '', kegg_product)

            # Also toss out anything between square brackets
            kegg_product = re.sub(r'\[.*\]', '', kegg_product)

            if kegg_product.strip():
                processed_product=kegg_product.strip()

    # RefSeq: split and process
    elif database == 'refseq':
        for subproduct in product.split('; '):
            subproduct = re.sub(r'\[.+?\]', '', subproduct)
            subproduct = re.sub(r'[a-z]{2,}\|(.+?)\|\S*', '', subproduct)
            subproduct = re.sub(r'\[', '', subproduct)
            if subproduct.strip():
                processed_product=subproduct.strip()

    # MetaCyc: split and process

    elif database == 'metacyc':
        # Pull out first name after the accession code:
        product_name = product.split('#')[0].strip()
        product_name = re.sub(r'^[^ ]* ', '', product_name)
        product_name = re.sub(r' OS=.*', '', product_name)

        if product_name:
            processed_product=product_name

    # Seed: split and process

    elif database == 'seed':
        for subproduct in product.split('; '):
            #subproduct = re.sub(r'[a-z]{2,}\|(.+?)\|\S*', '', subproduct)
            subproduct = re.sub(r'\[.+?\]', '', subproduct)
            subproduct = re.sub(r'\(.+?\)', '', subproduct)
            if subproduct.strip():
                processed_product=subproduct.strip()

    elif database == 'cazy':
        for subproduct in product.split('; '):
            #subproduct = re.sub(r'[a-z]{2,}\|(.+?)\|\S*', '', subproduct)
            subproduct = re.sub(r'\[.+?\]', '', subproduct)
            subproduct = re.sub(r'\(.+?\)', '', subproduct)
            if subproduct.strip():
                processed_product=subproduct.strip()

    # MetaCyc: split and process
    # Generic
    else:
        processed_product=strip_taxonomy(product)
        processed_product = re.sub(r'\[.*\]', '', processed_product)

    words = [x.strip() for x in processed_product.split() ]
    filtered_words =[]
    underscore_pattern = re.compile("_")
    arrow_pattern = re.compile(">")
    for word in words:
       if not  underscore_pattern.search(word) and not arrow_pattern.search(word):
           filtered_words.append(word)

    #processed_product = ' '.join(filtered_words)
    # Chop out hypotheticals
    processed_product = remove_repeats(filtered_words)
    processed_product = re.sub(';','',processed_product)

    # can actually be a proper annotation
    # processed_product = re.sub(r'hypothetical protein','', processed_product)

    return processed_product

def remove_repeats(filtered_words):
    word_dict = {}
    newlist = []
    for word in filtered_words:
       if not word in word_dict:
          if not word in ['', 'is', 'have', 'has', 'will', 'can', 'should',  'in', 'at', 'upon', 'the', 'a', 'an', 'on', 'for', 'of', 'by', 'with' ,'and',  '>' ]:
            if not word=='#':   # for metacyc this is important
                word_dict[word]=1

            newlist.append(word)
    return ' '.join(newlist)

class BlastOutputTsvParser(object):
    def __init__(self, dbname,  blastoutput, shortenorfid=False):
        self.dbname = dbname
        self.blastoutput = blastoutput
        self.i=1
        self.data = {}
        self.fieldmap={}
        self.shortenorfid=shortenorfid
        self.seq_beg_pattern = re.compile("#")

        try:
           self.blastoutputfile = open( blastoutput,'r')
           self.lines=self.blastoutputfile.readlines()
           self.blastoutputfile.close()
           self.size = len(self.lines)
           if not self.seq_beg_pattern.search(self.lines[0]) :
              exit_process("First line must have field header names and begin with \"#\"")
           header = self.lines[0].replace('#','',1)
           fields = [ x.strip()  for x in header.rstrip().split('\t')]
           k = 0
           for x in fields:
             self.fieldmap[x] = k
             k+=1
           eprintf("Processing database : %s\n", dbname)

        except AttributeError:
           eprintf("Cannot read the map file for database :%s\n", dbname)
           exit_process()

    def __iter__(self):
        return self
    count = 0
    def next(self):
        if self.i < self.size:

           try:
              fields = [ x.strip()  for x in self.lines[self.i].split('\t')]
              #print self.fieldmap['ec'], fields, self.i,  self.blastoutput
              if self.shortenorfid:
                 self.data['query'] = ShortenORFId(fields[self.fieldmap['query']])
              else:
                 self.data['query'] = fields[self.fieldmap['query']]

              self.data['q_length'] = int(fields[self.fieldmap['q_length']])
              self.data['bitscore'] = float(fields[self.fieldmap['bitscore']])
              self.data['bsr'] = float(fields[self.fieldmap['bsr']])
              self.data['expect'] = float(fields[self.fieldmap['expect']])
              self.data['identity'] = float(fields[self.fieldmap['identity']])
              self.data['ec'] = fields[self.fieldmap['ec']]
              self.data['product'] = re.sub(r'=',' ',fields[self.fieldmap['product']])

              self.i = self.i + 1
              return self.data
           except:
              print self.lines[self.i]
              print traceback.print_exc(10)
              sys.exit(0)
              return None
        else:
           raise StopIteration()

def isWithinCutoffs(data, cutoffs):
    if data['q_length'] < cutoffs.min_length:
       return False

    if data['bitscore'] < cutoffs.min_score:
       return False

    if data['expect'] > cutoffs.max_evalue:
       return False

    if data['identity'] < cutoffs.min_identity:
       return False

    if data['bsr'] < cutoffs.min_bsr:
       return False

    return True

def word_information(string_of_words):
    words = [ x.strip() for x in string_of_words.split() ]

    information = 0
    wordlist = {}
    underscore_pattern = re.compile("_")
    for word in words:
       if not word in ['', 'is', 'have', 'has', 'will', 'can', 'should',  'in', 'at', 'upon', 'the', 'a', 'an', 'on', 'for', 'of', 'by', 'with' ,'and',  '>', 'predicted', 'protein', 'conserved' ]:
          if not underscore_pattern.search(word):
             wordlist[word]=1

    #print string_of_words
    #print wordlist
    #print len(wordlist)
    return len(wordlist)

def compute_annotation_value(data):
    score = 0;
    if len(data['ec'] ) > 0:
       score += 10

    if not re.search(r'hypothetical protein', data['product']):
       score += word_information(data['product'])

    return score

# compute the refscores
def process_parsed_blastoutput(dbname, weight,  blastoutput, cutoffs, annotation_results):
    blastparser =  BlastOutputTsvParser(dbname, blastoutput, shortenorfid=False)

    fields = ['q_length', 'bitscore', 'bsr', 'expect', 'aln_length', 'identity', 'ec' ]
    if cutoffs.taxonomy:
       fields.append('taxonomy')
    fields.append('product')

    annotation = {}
    for data in blastparser:
        #if count%10000==0:

        if isWithinCutoffs(data, cutoffs) :

           #print data['query'] + '\t' + str(data['q_length']) +'\t' + str(data['bitscore']) +'\t' + str(data['expect']) +'\t' + str(data['identity']) + '\t' + str(data['bsr']) + '\t' + data['ec'] + '\t' + data['product']
#           if data['query'] =='NapDC_illum_asm_188606_0':

    #       print dbname
           annotation['bsr'] = data['bsr']
           annotation['ec'] = data['ec']
           annotation['product'] = strip_taxonomy(process_product(data['product'], dbname) )
           annotation['value'] = compute_annotation_value(annotation)*weight
         #  print annotation

           if not data['query'] in annotation_results:
               annotation_results[data['query']] = {'value':0}

           if annotation_results[data['query']]['value'] <= annotation['value'] :
                annotation_results[data['query']] = annotation.copy()

#    add_refscore_to_file(blastoutput,refscore_file, allNames)
    count =  len(annotation_results.keys())
    return count

def read_contig_lengths(contig_map_file, contig_lengths):
     try:
        mapfile = open(contig_map_file, 'r')
     except IOError:
        print "Cannot read file " + contig_map_file + " !"
        insert_error(errorcode)
        return

     mapfile_lines = mapfile.readlines()
     mapfile.close()

     for line in mapfile_lines:
        line = line.strip()
        fields = [ x.strip() for x in line.split('\t') ]
        if len(fields) != 3:
            contig_lengths = {}
            return
        contig_lengths[fields[0] ] = int(fields[2])

def getBlastFileNames(opts) :

    database_names = []
    parsed_blastouts = []
    weight_dbs = []

    dbnamePATT = re.compile(r'' + opts.blastdir + '*' + opts.sample_name + '*[.](.*)[.]' + opts.algorithm.upper() + 'out.parsed.txt')

    blastOutNames = glob(opts.blastdir + '*' + opts.algorithm.upper() + 'out.parsed.txt')
    for blastoutname in blastOutNames :
        result = dbnamePATT.search(blastoutname)
        if result:
            dbname = result.group(1)
            database_names.append(dbname)
            parsed_blastouts.append(blastoutname)

            if re.search(r'metacyc', blastoutname, re.I):
               weight_dbs.append(2)
            else:
               weight_dbs.append(1)

    return database_names, parsed_blastouts, weight_dbs

# the main function
def main(argv, errorlogger =None, runstatslogger = None):
    global parser
    (opts, args) = parser.parse_args(argv)

    if not check_arguments(opts, args):
       print usage
       sys.exit(0)

    results_dictionary={}
    dbname_weight={}

    contig_lengths = {}
    read_contig_lengths(opts.contig_map_file, contig_lengths)

    if opts.blastdir !=None and opts.sample_name != None:
        try:
           database_names, input_blastouts, weight_dbs = getBlastFileNames(opts)
        except:
           print traceback.print_exc(10)
           insert_error(errorcode)
           pass
    else:
        database_names = opts.database_name
        input_blastouts = opts.input_blastout
        weight_dbs = opts.weight_db

    priority = 6000
    count_annotations = {}

    print ''
    for dbname, blastoutput, weight in zip(database_names, input_blastouts, weight_dbs):
        results_dictionary[dbname]={}
        dbname_weight[dbname] = weight
        count = process_parsed_blastoutput(dbname, weight, blastoutput, opts, results_dictionary[dbname])
        if runstatslogger!=None:
           runstatslogger.write("%s\tProtein Annotations from %s\t%s\n" %( str(priority), dbname, str(count)))
        count_annotations
        priority += 1

    for dbname in results_dictionary:
      print dbname, len(results_dictionary[dbname].keys())
      for seqname in results_dictionary[dbname]:
         count_annotations[seqname] = True
    count = len(count_annotations)
    if runstatslogger!=None:
       runstatslogger.write("%s\tTotal Protein Annotations\t%s\n" %( str(priority),  str(count)))

    #create the annotations from he results
    create_annotation(dbname_weight, results_dictionary, opts.input_gff, opts.rRNA_16S, opts.tRNA, opts.output_gff, opts.output_comparative_annotation, contig_lengths, compact_output = opts.compact_output)

def MetaPathways_annotate_fast(argv, errorlogger = None, runstatslogger = None):
    createParser()
    errorlogger.write("#STEP\tANNOTATE_ORFS\n")
    try:
       main(argv, errorlogger = errorlogger, runstatslogger = runstatslogger)
    except:
       insert_error(errorcode)
       return (0,'')

    return (0,'')

# the main function of metapaths
if __name__ == "__main__":
    createParser()
    main(sys.argv[1:])


John Nava, Teresa of Avila, 2004, Woven Tapestry, 93.5" x 39"
Beginning on February 27th the Shatto Chapel of the First Congregational Church of Los Angeles will be displaying the works of 69 artists in a themed exhibition titled Art & Spirit.
Lynn Aldrich, Rose Ghost, 2015, Tulle, 72"x72"
"I'm so pleased to open the doors of First Church as wide as we can as we invite everyone in the city of Los Angeles to explore that fascinating intersection where Art meets the Spirit." says First Church's Senior Minister, Dr. R. Scott Colglazier, who, along with Joan Agajanian Quinn, first conceived the idea of Art & Spirit as a theme for the show. "Not only are we creating this opportunity for the public, but our connection with Art Division has allowed us to tap some of our city's new artists to respond to this theme in their own unique way."
While the theme of the show focuses on the idea of "spirit," many of the works are not overtly religious in nature. The collection of paintings, sculptures, and tapestries will include images by Rembrandt and Albrecht Dürer, along with contemporary works by Sam Francis, Ed Ruscha, Laura Lasworth, and Corita Kent, among others.
Rembrandt Van Rijn, Good Samaritan, 1633, Etching and engraving, 22" x 15.5"
A portion of the show will focus on art created by students from Art Division--a school that offers a professional training program for underserved young adults--who were asked to create works as a reaction to the theme. "The students had many reactions," explains Art Division's Executive Director, Dan McCleary, "confusion, excitement, resistance, bewilderment. They were given enormous freedom to respond as they saw fit - and the work they produced is as varied and imaginative as they are."
Robert Ortiz, Walt Disney Concert Hall Chair #4, 2015, Acrylic on Panel, 36" x 36"
Joan Agajanian Quinn, the longest sitting member appointed to the California Arts Council, is co-curating the exhibit. "The theme Art & Spirit is something that isn't the norm for a show title," she explains. "Gallerists and curators don't think it's politically correct to bring religion into the art world per se, butI have always felt that art is an experience, either good or bad. It can move a person in a way that nothing else can. Maybe it's the spirit within the piece, maybe it's the spirit within the viewer; but no matter what, there is a transforming moment."


WestBond Enterprises Corporation (the "Company") is pleased to announce that it has renewed its agreement (the "Agreement") with 547853 B.C. Ltd. operating as Quinton Investment Services Corp. ("Quinton") of Kamloops, British Columbia for investor relations services. The new term of the Agreement is from September 1, 2002 to August 31, 2004, but may be cancelled by either party on one month's notice. Quinton will receive a bonus of $15,000 plus $2,500 per month, which will be paid out of cash flow. The Agreement is subject to the approval of the TSX Venture Exchange.
Doren Quinton is the principal of Quinton and has provided investor relations services for other listed companies. Quinton and Doren Quinton, collectively, currently own 62,000 common shares of the Company. The Company's objective is to increase awareness in the investment community.
The Company also announces that under it's stock option plan, it has granted incentive stock options to directors and employees of the Company, to purchase up to a total aggregate of 430,000 Common shares in the capital stock of the Company at a price of $0.12 per share. The options are exercisable for a period of five years ending on December 12, 2007.


The Royal Carved Couch we offer are widely used in hotels, lounges, lobby areas of houses and resorts. These wooden carved sofa sets are appreciated for heir elegant designs and traditional appeal. Made of quality wood, these Royal Carved Couches are long lasting with a brilliant finish. Placing these Royal Carved Couch would surely enhance dull and mundane interiors.
We are offering high quality wooden furniture for enhancing the beauty of interiors.
We are offering wide range of wooden teapoys at the market leading prices.


The plate heat exchanger frame and plate are removable. It's easy to disassemble, plate can be cleaned at any time, but all welded plates are welded together can not disassemble. The customer can use the CIP method to clean it.
Plate heat exchanger is a high efficiency heat exchanger, which is made up of a series of metal sheets with certain corrugated shape. A thin rectangular channel is formed between various plates, and heat is exchanged through the plates. It's an ideal equipment for liquid-liquid and liquid-vapor heat exchange, has the characteristics of high heat transfer efficiency, low heat loss, compact and lightweight structure, small floor area, wide application and long service life. Under the same pressure loss, the heat transfer coefficient is 3-5 times higher than that of tubular heat exchanger, occupying one third of the area of tubular heat exchanger, and the heat recovery rate can be as high as 90%.
A all welded heat exchanger is a new generation product which integrates the advantages of a detachable plate heat exchanger and shell-and-tube heat exchanger. Its introduction makes up for the application gap of the removable plate heat exchanger. At the same time, its high temperature, high pressure, and strong corrosion resistance ensure the replacement of most working conditions of the traditional shell and tube heat exchangers.
The fully welded heat exchanger has a corrugated plate structure similar to the plate heat exchanger. At the same time, it adopts more advanced Full-welding process seals, no gasket design, and the selection of various metal and alloy materials to ensure that MAX fully-welded heat exchanger is suitable for almost all heat transfer process occasions with temperature ranging from 5 to 500 oc and working pressure ranging from vacuum to 60bar. Its compact structure design, efficient heat transfer performance and convenient and flexible use determine that it has inherent superiority to completely replace the traditional shell and tube heat exchangers.


How do we stay small and sell big? It's simple: years of experience. At Smith's Cycle Center, our mission is to offer you the latest in parts and products at the best prices, and with unparalleled service. Our workers understand to sell and work on the new products, you must know the old products and where Honda came from. We pledge to use our best efforts to make your experience both beneficial and enjoyable. Once you give us a try, we're sure you'll be back for more!
After selling Cushman motorcycles for many years, founder of Smith's Cycle Center Sam Smith made an important decision to begin selling Honda motorcycles. A huge risk then has been worth it, in 2015 Smith's Cycle will be celebrating 50 years with Honda Motor Company. The 1963 Cushman pictured above was restored to remember the Smith's father and remember where the business began.


Gungahlin records a mild, dry July 2009.
Weather conditions across Gungahlin during July were both milder and drier than normal.
Nights were cool to cold, with an average minimum of 2.3°C; significantly warmer than the average of 0.8°C recorded last July, and well above Gungahlin's longer term July average of 1.1°C. The warmest night for the month occurred on July 12, when the temperature was a mild 7.4°C, while on July 18, it dropped to a frosty -2.5°C.
Days were generally cool and cloudy, with an average maximum of 10.9°C; up slightly on the average of 10.4°C recorded last July. The highest temperature for the month was a warm 15.7°C, recorded on July 22, while on July 14, cloudy skies and gusty NW winds combined to keep Gungahlin's maximum temperature to just 7.3°C.
Gungahlin recorded 13 frosts and 4 fogs during July, compared to the 22 frosts and 3 fogs in July 2008.
Winds at the Weather Centre averaged at 4.8 km/h during July, with the strongest gust for the month 51.5 km/h from the NW, recorded on July 2.
Despite the promising forecast of above average winter rain this year, Gungahlin recorded just 23.6mm in July, over 16 days. This was well below the 43.7mm that fell last July, and down on Gungahlin's longer term July average of 39mm. Falls in other parts of Canberra were also below normal, with Canberra AP recording 29.8mm for the month and Tuggeranong 33.4mm. Gungahlin's total rainfall so far in 2009 now stands at 193.0mm, well down on the 232.6mm that fell over the same period last year.
Gungahlin's August outlook: The milder winter weather looks set to continue in August, with temperatures on the whole a little warmer than normal, especially at night. Overall, daytime temperatures should average at around 14°C, and nights at 3°C. This compares to Gungahlin's longer term August average of 1°C to 13°C. Despite both June and July recording below average rainfall, conditions look favourable for a relatively wet August, with decent falls likely towards the middle of the month. With this in mind, Gungahlin is set to receive around 60mm of rain for the month, up on the longer term average of 55.7mm.


text:
Forgotten Fable
About Forgotten Fable
Forgotten Fable provides a unique experience collaborating their diverse styles of metal and theatrics. The atmosphere is energetic and heavy with a sense of duality within the music. What one person hears might vary from what his/her friend perceives from that very same song. And that's the way Forgotten Fable likes it.
"People hear music, and they adapt it to themselves and to their experiences in life," said lead singer Andrew Taylor. "It's a more positive influence on music and lyrics and just life."
While they take risks with their on-stage antics, Forgotten Fable takes their music very sincerely. Not only are they interested in reaching their fans with their sounds, but also they want to reach out and assist their fans in dealing with life's situations through music.
Their roots are in heavy music, and that's exactly what you will get if you go to one of their shows. So be prepared to be rocked and entertained all night. Like the music or not, you will not leave disappointed. It's the little things they do on stage that set this band apart from all others.
Follow Forgotten Fable on
www.forgottenfable....

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: ArcGIS ArcGISDynamicMapServiceLayer, setExtent I have a layer made with ArcGISDynamicMapServiceLayer like this:
return esriLoader.loadModules([
  'esri/layers/ArcGISDynamicMapServiceLayer',
  'esri/layers/ImageParameters',
  'esri/InfoTemplate'
]).then(([ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate]) => {

  const infoTemplate = new InfoTemplate();
  infoTemplate.setContent(this.handleContentChange);
  infoTemplate.setTitle(this.props.intl.formatMessage({ id: 'layers.popup.title' }));
  const imageParams = new ImageParameters();
  imageParams.layerIds = [layerCode];
  imageParams.layerOption = ImageParameters.LAYER_OPTION_SHOW;
  imageParams.transparent = true;

  const layer = new ArcGISDynamicMapServiceLayer(layerUrl, {
    id: layerId,
    opacity: 0.5,
    imageParameters: imageParams,
    infoTemplates: { [layerCode]: { infoTemplate: infoTemplate } }
  });

  esriMap.addLayer(layer)

I want to set the extent of the layer that I'm rendering to fit what it's rendered. The problem that I see is the featureExtent and initialExtent comes from the service, and it's the same for each service. But some layers are in different parts of the map, some are big, some are very small, so I need a way to zoom to what it's showed in the map. How can I set the extent on those service to fit it?
For example, with: esriMap.setExtent(layer.initialExtent, true) doesn't work, because in the services

I have this extents:

A: Since ArcGIS Server 10.4, the query operation on a layer supports the returnExtentOnly parameter. You could use this to together with where=1=1 to get the extent of the layer, and then zoom to that extent.
The documentation for the Query object in JavaScript (v3, v4) doesn't explicitly mention this option, so you'll have to add it to the QueryTask's URL manually.

redpajama_set_name: RedPajamaStackExchange


Development Magazine: "Bulfinch Crossing The Next Phase of Urban Revitalization in Boston"
Architect's Newspaper: "A five-acre redevelopment of Boston's Bulfinch Triangle will replace a much-maligned concrete garage"
Curbed: "Bulfinch Crossing construction officially starts"
In addition to providing complex urban design for the 4.2-million-square-foot Bulfinch Crossing Redevelopment, CBT is designing a 486-unit residential tower as the first phase of development. Located at the point of the Bulfinch Triangle, the new tower will offer unparalleled views to the Charles River, Boston Harbor, and downtown Boston. The elegant and unique "pin-striped" design of the glass tower will offer a beautiful new feature to Boston's ever-changing skyline.


The Whippet tanks of the 3rd Battalion Tank Corps move up first time into action near Maillet Mailly on this day.
Somme: German 3rd Marines and 54th Reserve Divisions enter Albert. British Whippet light tanks first time in action: 12 rout 2 German battalions, helping ANZAC troops to plug Hebuterne-Collincamps gap in Third Army front after 22-mile retreat in 5 days. Germans capture Roye from the French.
Mesopotamia – Battle of Khan Baghdadi (until March 27): Brooking's c.11,000 men, 48 guns, 16 planes, 13 armoured cars and 300 Ford vans storm 2 Turk trench lines and cut Aleppo road trapping 5,254 PoWs (including Nazim Bey, commander 50th Division), 12 guns and 47 MGs for 159 casualties.
St George's Channel: Royal Navy PC-51 depth charges and sinks U-61, sinker of 36 ships (90,770t) since 1916.
Western Front: British Third Army uses 27 of its 34 Royal Flying Corps squadrons or over 250 aircraft for close support, total 29t (c.1437) bombs and 228,000 rounds by formations of up to 60 aircraft. RFC lose 50 planes (Germans claim 12 for loss of 5) for 10 German claimed. Both sides night bomb. RFC drop record of 1,326 bombs.
Britain: Churchill cables all factories for increased output and Easter holidays' deferment (over 1,500 firms do); assures War Cabinet 2,000 guns ready for BEF by April 6. Light, Heating and Power Order, no lighting in public places after 10.30pm.


About 500 people are killed in hippopotamus attacks each year. On Saturday, Kristen Yaldor was almost one of them.
The 37-year-old American woman was on a river safari tour with her husband, Ryan, when she was suddenly attacked by a hippo that was said to be protecting her calf.
The couple was on a guided canoe safari on Zimbabwe's Zambezi River. Led by tour operator Wild Horizons, the safari group had three guests and two guides. While canoeing down the river, one of the guides spotted the hippo on the river's right bank. He reportedly instructed the group to paddle to the left side of the river to avoid the hippo, an animal known for its aggression, especially during calving season.
As the Yaldors paddled to the other side, a hippo appeared under their canoe and flipped it over, Wild Horizons told ABC News. The hippo pulled Kristen Yaldor beneath the water as she was trying to swim to the riverbank. Meanwhile, Ryan Yaldor, who was thrown from the canoe toward the riverbank, swam to the shore in less than 30 seconds. He turned around and called for his wife, and she emerged from the water — with her leg inside the hippo's mouth.
Kristen Yaldor punched the hippo in the face several times, and it finally released her. She was able to swim to the shore, where her husband helped her out of the water and the head guide reportedly administered first aid. She was airlifted to a clinic in Zimbabwe about 45 minutes later.
From the clinic, she was transferred to a hospital in Johannesburg, an ordeal that took 14 hours after the initial attack. The pressure of the hippo's clenched teeth caused a ragged fracture in Kristen Yaldor's right femur. She has already received two surgeries to repair the broken bone and remove dead tissue, and she might possibly need further operations.
The attack happened on Kristen Yaldor's 37th birthday. The couple told ABC that they were never warned it was calving season for hippos, which might make them more aggressive.
Wild Horizons, which has operated tours in the Victoria Falls region of Zimbabwe for nearly 30 years, told ABC it has strict safety protocols, including a pre-safari safety briefing and instructions on how to properly paddle and steer the canoe. Backup vehicles also follow the canoes down the river, the tour company said, and guides are provided cell phones and handheld radios for emergencies.
The Yaldors say the guides couldn't reach anyone for help on the radios, and their cell phones did not work from the location on the river bank, causing a delay in medical assistance.
TPG reached out to Wild Horizons for more information but did not receive a response by time of publication.


Imagine your deer fence as a series of picture frames, each frame defined by its two side posts. The products listed here secure the fence by attaching the fencing to the frame. At the top, for all those fences that need it, goes top support tie wire or monofilament line with terminators and tensioners, as well as circular (hog ring) staples for attaching this top support line to the fencing. Then at the side come U-nails or zip-lock ties for attaching the fencing to trees, wood posts, or metal posts. At the bottom come ground stakes for securing a bottom fold of the fencing material to the ground. And in the center go temporary warning flags to ensure the deer get the picture, seen the fence, and don't charge it.
All metal hexagrid fences need these, as do all poly fences where falling tree limbs could strike the fence or where the length of the fence exceeds 500 feet. Get our 13.5-gauge pvc-coated steel tie wire for fences that are short or curving, monofilament line for long fences that run straight. Use the 8-gauge monofilament line for metal hexagrid fences and the 12-gauge monofilament line for poly fences.


Huntsville Heating and Cooling Service | Southern Heating & Cooling Inc.
When is the last time you had your home's furnace and air conditioner checked? If you can't recall the last time you set up an appointment with an HVAC professional to perform routine maintenance, you are not alone—but you may be leaving yourself open to a sudden, unexpected problem with your furnace or air conditioner.
Though not usually given much thought by homeowners, your heating and cooling system is a critical component in the overall comfort of your home. Spending one day in a house without cool air during the summer, or heat during the winter, will tell you all you need to know about just how critical it is to maintain a livable temperature in the home. Here at Southern Heating & Cooling Inc. in Huntsville, all of our team members are here to make sure that should the need for emergency service arise, we can resolve the situation as soon as possible.
In our many years of experience here in Huntsville, we've seen it all, from heating units that haven't been inspected in years to AC units that suddenly stop working in the heat of summer. Luckily, our exposure to this wide variety of unique situations and problems has given us the expertise needed to solve nearly any problem, no matter the scope. Should you ever need emergency service on your furnace or AC unit, just call us at 256-574-1300 to arrange an appointment with one of our excellent technicians. We'll help ensure your home is back to a livable temperature as soon as possible.
Of course, this doesn't mean you should put off regular maintenance, either. By taking the time to schedule an annual appointment to service your home's heating and cooling units, you're also taking an important step towards extending the lifespan of the system and shrinking the chances of running into serious problems at a later date. And, if you have an old unit that you think should be replaced, we have the knowhow and extensive product catalog to match you with the right product.
Here at Southern Heating & Cooling Inc., we have products that cover nearly every need and budget. Whether you're looking for an air conditioning unit with allergen filtration, an energy-efficient furnace, or a no-frills unit, we have it all. What's more, our entire suite of products is ENERGY STAR certified, meaning you'll stretch your dollars farther on your energy bill. What could be better than a modern, reliable furnace or air conditioner?
Whether you're in need of emergency service on your HVAC system, want to schedule annual maintenance, or are looking to replace a part of your home's heating and air conditioning system, you can trust that our team here at Southern Heating & Cooling Inc. can help answer your questions. If anything we've described here fits your needs, give us a call at 256-574-1300 so we can get the conversation started.


Check out @triggermanagement DJs & MCs This Week's schedule 17 – 18 April 2019 at ..
This entry was posted on Wednesday, April 17th, 2019 at 12:20 PM	and is filed under Events, News and Updates. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.


The 2004 harvest followed an extraordinary viticultural year: October and November 2003 were very wet followed by an extremely dry start to 2004. Just 147mm of rain, half the ten-year average, fell in Pinhão from January to the end of April. August then saw the highest rainfall for many years, accompanied by relatively low temperatures. As a result ripening slowed dramatically. September started with unsettled weather that could have caused considerable damage to the grapes. Harvesting began 10 days later than usual. There then followed 25 days of sunshine with temperatures around 30ºC every day. No rain fell during the harvest. On the 9th and 10th of October the weather finally broke, but by then most of the grapes were all safely in the wineries.
Quinta dos Malvedos is situated on the north bank of the Douro River, a short distance from the mouth of the river Tua, between Pinhão and the Valeira dam. Located in the Upper Douro region, the vineyards at Quinta dos Malvedos are mostly south facing ensuring prolonged solar exposure and excellent ripening of the grapes despite localised microclimates created by the natural undulations of the valley. Height above sea level in the Quinta varies from 130m to 350m, with a 15-year annual average rainfall of 606mm. The vineyard produces rich and complex full-bodied wines with floral characteristics of eucalyptus and mint, and soft violet overtones when young. Malvedos Vintage Ports are bottled and aged in Graham's cellars in Vila Nova de Gaia and not released until ready to enjoy, around ten years after harvest.


(as it is in the 303 response)?
good practice (see [CHIPS], 7.2).
That comma should be a semicolon (or a sentence break).
or a RDF document describing Alice.
the objects of both of those statements about Bob's likes.
object and the resource that represents it.
Was that meant to say "the resource that describes it"?
suggestion you may want to copy for your implementations.
.asp out of your URIs, you may want to change technologies later.
The comma should be elided.
Is that last statement correct?  There is no ".php" suffix anywhere.
or quote the two phrases italicized in the original.
The "understanding" should be "understand."
* Section 8 says "detailled."
* Section 1 says "frontpage."  Shouldn't that be "front page"?
those references say simply "home page"?
Next message: Ivan Herman: "Re: Cool URIs for the Semantic Web comments: some errors"
Next in thread: Ivan Herman: "Re: Cool URIs for the Semantic Web comments: some errors"
Reply: Ivan Herman: "Re: Cool URIs for the Semantic Web comments: some errors"


text:
When will they move in? – ESPN Crikey
The owner of a wooden house that was vandalised in South Australia will have to relocate to a new home.
In a Facebook post, the owner of the wooden house, David Daley, said the vandalised wooden structure had been removed from his property.
"I was at work and noticed the graffiti on the exterior of the house on Tuesday evening," Mr Daley said.
"The property owner, Mark Gorman, and I were at work when we noticed the damage."
It was clearly visible that someone had been taking a look inside and had done some damage to the wooden structure.
"We have since removed the graffiti and are working to get it repaired."
Mr Daley is due to take the structure out of his house, which is owned by his sister, on Wednesday morning.
The owner, Mr Gorman has previously described the incident as an "epidemic" and has promised to clean up the graffiti.
Topics:social-media,law-crime-and-justice,community-and.disputes,parliament,state-parliament
wooden house rv
When is the next season of The Walking Dead going to premiere?
A look at the quails wood bug from the backyard
Wooden house number one is the most beautiful in the world


A TV saved my marriage.
I kid, I kid, but there is teeny bit of truth here. Who knew a TV (not a TV show, or a TV doctor) but an honest to goodness, physical, electronic device could have been such a pain point in my marriage? But more on that later.
Like most red-blooded Americans, I love a good "before and after" story, be it hair color, weight loss or room transformation. Hours of labor and planning and design summed up in a simple side-by-side image of what something WAS and what it now IS.
Loving a good refresh means that I'm always in flux. I see the potential to change and "improve" everywhere, at times, to my detriment. For instance, I live in a beautiful home, that was remodeled, only two years ago. What am I doing while on bedrest? Thinking of all of the ways I can change it. The guest bedroom was turned into an office, then turned back into a guest bedroom, then a nursery. The office was turned into a guest room, office, nursery (for a brief spell), guest bedroom and back to another nursery. Everything has changed, but nothing has changed. Except for my sanity, and that of my husbands.
With my need to change, I've been (rightfully) banished from making changes to my home (FOR NOW!) and charged with finding projects that don't affect my family's living space, which is why I leaped at the chance to refresh a rustic boathouse space with Emily Henderson (yes, that Emily Henderson!) and Samsung.
Talk about a dream project. Nestled in upstate New York, this boathouse was on a secluded lake with incredible views. We had 72 hours to transform the space from "rustic" to "chic." We were both up for the challenge. This is not a reveal story (at least not yet) but I will give you a sneak peek at the before space and the design concepts that we put together.
Back to saving my marriage. With my house in constant flux, there needed to be a compromise in either aesthetic or execution. Joe has lived and stayed the course with me through all of these room transformations, and I wanted to do something just for him (and maybe a little bit for me as well). All Joe has ever wanted in this house, is a TV above the fireplace. A simple request, but one that was the biggest challenge for me personally.
I'm no Luddite, and I love watching TV, but I honestly never think about a TV as a focal point of a room; it's just something that I never subscribed to or incorporated into my aesthetic. I knew this project involved a TV that would change the way I thought about how the electronic device related to decor, but I had serious, serious doubts. Believe it or not, my thoughts changed after the boathouse project with Emily and Samsung.
During the boathouse refresh, Samsung challenged us to incorporate their new TV, The Frame, into the space. As I mentioned, I was skeptical, but after seeing and experiencing The Frame firsthand, I've converted. Not only does The Frame look like art, with the ability to collage or matte your own images or feature pre-loaded photos and art to display, it sits COMPLETELY flush against the wall (like a picture frame). You can purchase different colors of Customized Frames to suit your decor, change the warmth and brightness of the artwork to fit the lighting in your space automatically with a built-in sensor, AND it comes with a handy, slim, easy to hid box for all those annoying gadgets that usually sit out on your TV console.
After the boathouse project, I had one last room refresh planned (aside from the current nursery project!) for the living room. Joe met the news with cautious optimism, especially when I reassured him that I was planning on including a TV above the fireplace. After the transformation was complete, he had tears in his eyes. Ok, no tears, but he was incredibly happy. And so was I. My house didn't resemble a sports bar (my irrational fear of the outcome if I did place a TV over a fireplace) and I finally had a place to display some of my favorite pictures.
The big reveal of my project with Emily is coming to you in just a couple weeks. I can't wait to share how our two aesthetics came together to transform a truly beautiful space. Stay tuned for more!
Sounds like an awesome TV, haha! Marriage saver for sure.
I hope the canoes are still under cover somewhere! Ours is in the living room and it helps hold books, keep from decaying and make life adventureful all at once.
What a beautiful space and a fun project! I definitely want that TV!
Cool TV indeed. I love this interior, everything fits so well together.


Bitlocker To Go - a new feature of Windows 7 - is a full-disk encryption protection technology for removable storage devices, such as USB drive, flash drive.
Basically, BitLocker To Go allows to encrypt a USB drive and restrict access with a password. When you connect the encrypted USB drive to a Windows 7 computer, you will be prompted for the password. After successfully entering the password to unlock it, you can read and write to the drive as usual.
During the encryption process, Windows 7 installs a special reader on the USB drive. When you connect the encrypted USB drive to a computer running Windows Vista, Bitlocker To Go takes control, prompts for the password, and then basically makes the USB drive a read-only device.
Is there Bitlocker To Go for Mac to open/access Bitlocker encrypted drive on macOS or Mac OS X?
Please download Mac Bitlocker To Go: M3 Bitlocker Loader for Mac to open, access, unlock, mount, read, write Bitlocker encrypted drive on Mac computer and it works well on Mac Mini, Mac Pro, MacBook, MacBook Pro, MacBook Air, iMac with macOS 10.14 Mojave, High Sierra 10.13, 10.12 Sierra and Mac OS X 10.11/10.10/10.9/10.8/10.7 Operating Systems.
Step 3: Insert a Bitlocker encrypted drive into the Mac computer.
Step 4: Open Applications folder, find M3 Bitlocker Loader for Mac and then launch it.
Step 5: Select Bitlocker encrypted drive and then click "Open" icon to continue.
Step 6: Enter the password (or recovery key) and click "Unlock" to open/acess Bitlocker encrypted drive.
Step 7: After unlocking Bitlocker encrypted drive, the Bitlocker encrypted drive will be mounted as a regular drive, we can operate it same as Mac computer native drive, such as read, write, delete, view, delete, etc.
Step 8: After reading/writing Bitlocker encrypted USB drive, please click Lock and then click Eject in M3 Bitlocker Loader to safely eject Bitlocker encrypted drive from Mac computer. Please don't directly unplug Bitlocker encrypted drive in case of data loss, it is very important.
M3 Bitlocker Loader for Linux is a command line tool to open/access Bitlocker encrypted drive and encrypt drive with Bitlocker in Linux/Ubuntu.


The Core Configuration Manager (CCM) provides an intuitive software utility for HelixNet on any browser-enabled platform. CCM facilitates a quick and simple means of configuring any devices in a Link-Group, including role-based configuration endpoints, account management (Agent-IC, SIP and IVC-32-HX cards), save and restore, and live monitoring of all system components.
Although there are subtle differences, the CCM for HelixNet, LQ Series and FreeSpeak II systems have a common design and workflow to allow system administrators to quickly navigate from one product line to another without the need for training of different configuration tools. The pages logically group similar components and/or behaviors to maximize workflow efficiency.


text:
HomeAmericasIndo AmericaCongressional Bill Takes Aim at China's Occupation of Tibet
Congressional Bill Takes Aim at China's Occupation of Tibet
WASHINGTON, DC(ANI) – A bill introduced in Congress by Jim McGovern, (D-MA), and Michael McCaul (R-TX) on July 13 is taking aim at China's decades-long illegal occupation of Tibet by fully recognizing Tibet's unresolved status and faulting China for violating the Tibetan people's right to self-determination.
The 'Promoting a Resolution to the Tibet-China Conflict Act' faults China for failing to meet expectations of participating in dialogue with the Dalai Lama or his representatives and recognizing that Tibetans have a right to self-determination–and that China's policies preclude them from exercising that right.
Under China's brutal occupation, Tibet is now the least-free country on earth alongside South Sudan and Syria–according to the latest rankings from the watchdog group Freedom House–and the Chinese government has refused to negotiate with Tibetan leaders since 2010.
"Congress has had a long and abiding interest in a peaceful resolution to the conflict between Tibet and China. The United States government has consistently called on Chinese officials to return to dialogue, without preconditions. But that hasn't worked. The Chinese continue to turn their backs on the Dalai Lama. Our bipartisan legislation seeks to strengthen US policy by grounding it in international law and countering Chinese disinformation, with the aim of getting the two sides to negotiate a durable solution," the bill reads.
In recent years, the US has also passed several pieces of legislation on Tibet as it continues to support the nation against Chinese atrocities.
During the 2020 presidential campaign, then-candidate Joe Biden promised to "work with our allies in pressing Beijing to return to direct dialogue with the representatives of the Tibetan people to achieve meaningful autonomy, respect for human rights, and the preservation of Tibet's environment as well as its unique cultural, linguistic and religious traditions."
Biden has already delivered on one of his campaign promises by appointing a new Special Coordinator for Tibetan Issues. In December 2021, Uzra Zeya, the Under Secretary of State for Civilian Security, Democracy and Human Rights, took on the Special Coordinator role.
Unstoppable: 'Pathaan ...
3 Savani Brothers Charged Of M...


Its old of course and kid used. I've had it stored since we moved and when I tried to power it on for use in my shop, the computer seems to boot but the monitor although seems to get power has no display. It's a touch screen, who knows.. I'm not going to try. It has the stylus still I have the HP remote with it. Includes the power cord. I'm not including a keyboard or mouse. I'm selling or trading as is, parts if you want to call it that. I'm looking for a working laptop, a car double din dvd, amps or subs for even trades.


Want to be notified of new releases in huashengdun/webssh?
A simple web application to be used as an ssh client to connect to your ssh servers. It is written in Python, base on tornado, paramiko and xterm.js.
SSH password authentication supported, including empty password.
SSH public-key authentication supported, including DSA RSA ECDSA Ed25519 keys.
Auto detect the ssh server's default encoding.
Modern browsers including Chrome, Firefox, Safari, Edge, Opera supported.
Input your data, submit the form.
For whatever deployment choice you choose, don't forget to enable SSL.
By default plain http requests from a public network will be either redirected or blocked and being redirected takes precedence over being blocked.
Try to use reject policy as the missing host key policy along with your verified known_hosts, this will prevent man-in-the-middle attacks. The idea is that it checks the system host keys file("~/.ssh/known_hosts") and the application host keys file("./known_hosts") in order, if the ssh server's hostname is not found or the key is not matched, the connection will be aborted.


text:
Blue Jays return home to tame the Tigers
By Keegan Matheson
Aug 25, 2015; Arlington, TX, USA; Toronto Blue Jays starting pitcher Mark Buehrle (56) throws during the first inning against the Texas Rangers at Globe Life Park in Arlington. Mandatory Credit: Kevin Jairaj-USA TODAY Sports
Game 3: Sunday, August 30th – 1:07 ET
Mark Buehrle (13-6, 3.60) vs. Alfredo Simon (11-8, 4.89)
The Sunday finale sees the grizzled lefty Mark Buehrle on the hill, and much like Dickey, he's looking to turn it around after some shaky pitching of late. Over Buehrle's last two starts, he's pitched 10.0 innings while allowing nine earned runs on 14 hits. Every ball that could fall against the Texas Rangers did fall, but Buehrle insisted that he was making the pitches he wants. I'll trust the man and expect a bounce-back outing this time around.
Simon's season has been all over the place as he's allowed four or more earned runs in eight of his last 10 starts. His past two starts, however, paint quite the scattered picture. Simon allowed eight earned runs over 4.1 innings against the Angels last time out, but twirled a one-hit complete game shutout over the Los Angeles Angels the start before. Control has been a major issue for Simon, so a patient approach should serve the Blue Jays well.
Next: Could John Gibbons steal the AL Manager of the Year?


Six to Start's latest app is another pedometer for people who need more motivation to get off the couch. Similar to the team's previous game, Zombies, Run!, The Walk is an immersive experience that pits players in the midst of a suspenseful storyline - but rather than tap and swipe at the screen to make progress, you must get on your feet and move. It hopes to change your next walk around town into an adventure you will never forget.
The game begins with a bomb exploding in Inverness station and you being handed a package that could save the world. What follows is a story containing over 800 minutes of audio spread across 51 episodes and hundreds of miles. The Walk will have you travel the length of the UK before it's over, evading the police and secret agents. Depending on where in the world you live, that might sound like a far less escapist experience than fleeing from zombies, but hey, some of us are just plain tired of the undead.
If you loved Zombies, Run! and want a more updated experience and new environment, The Walk may just be worth a look. It's available below for $3.99, a 20% discount to celebrate its launch. So what are you waiting for? Get moving!
Tags:adventure pedometer Six to Start story The Walk zombies run!


Less than a week after a new generation of Windows Phones reached retailers' shelves, Microsoft is making the nightly news as the company whose servers crashed and irretrievably lost all of T-Mobile Sidekick customers' address and calendar data. The popular Sidekick cell phones were wiped out if customers turned them off or tried to reboot during a week or longer service outage that started on Oct. 2nd.
The timing couldn't have been worse. The Windows Phone launch on Oct. 6th marked the debut of Windows Mobile 6.5, which includes Windows Marketplace for Mobile, home to about 250 applications. Ironically, Windows Mobile 6.5 users have the option of using the free My Phone service for backing up contacts, messages, videos and other data on a pass protected Web site "in the event of a lost phone."
Microsoft agreed to acquire Danger Inc., the software-as-a-service company that developed the Sidekick apps in February 2008. Unlike Apple's iPhone which frequently syncs with the user's local desktop through iTunes, giving the user the opportunity to store information locally, the SideKick services and My Phone are hosted on remote data servers.
Regarding those of you who have lost personal content, T-Mobile and Microsoft/Danger continue to do all we can to recover and return any lost information. Recent efforts indicate the prospects of recovering some lost content may now be possible."
Microsoft can only hope that this pr disaster is somehow remedied and fast. Next month, the company is commercializing its cloud computing Windows Azure Platform, a platform as a service, which only runs in the company's own data centers. Despite 99.95 percent service level agreements, outages happen, services go down, but a remote threat of losing corporate data is a bet most companies won't make, even with local backups.


In another sign of Beijing's increasing squeeze on Hongkongers' civil liberties, Hong Kong lawmakers are now debating a bill that would punish people who diss the Chinese national anthem — with jail terms of up to three years.
The legislation, aimed at curbing public displays of anti-Chinese sentiment in the semi-autonomous city-state, has renewed concerns about shrinking freedom of expression in Hong Kong. In recent years, Beijing has been crimping civil liberties in the former British colony of 7.4 million people, which is governed under a "one country, two systems" policy that grants Hongkongers greater civil liberties — including the right to freedom of expression — than on the Mainland.
The move follows outrage on the Mainland at reports of Hong Kong soccer fans booing the Chinese anthem as it played at matches in recent years, as a form of protest at Beijing's increasing encroachment on Hong Kong.
China's national legislature passed a law on the Mainland banning disrespect for the anthem in 2017, and added it to an annex of Hong Kong's de facto constitution, obliging the city-state's government, the Legislative Council, to introduce equivalent legislation.
He called on the government to withdraw the bill and launch a public consultation.
The bill was also met with signs of opposition within the legislature, with some lawmakers holding placards reading: "Against anthem law. Safeguard freedom of speech." Nevertheless, the bill is expected to pass by July, as the opposition lacks the seats to block the legislation.
Beijing's clampdown on the so-called special administrative region in recent years have included expelling democratically-elected lawmakers from the Legislative Council, refusing others to stand for election, and heavy-handed prosecutions of pro-democracy activists. Concerns have also grown over increasing self-censorship by the media in the city-state to respect the invisible red lines drawn by Beijing.


This year commemorates the sixty-fifth year since the official admission of women to Georgia Tech. To mark this occasion, GT WAN is seeking to raise at least $65 from 65 alumni with all donations going towards our undergraduate scholarship which supports women pursuing degrees at Tech. Please consider making a tax-deductible donation and help us spread the word by sharing with other alum and friends of Georgia Tech via email and/or social media.


Grief is a natural, universal reaction to the loss of someone you care about, yet what you experience as grief is itself highly personal and unique to you. It can involve many different distressing experiences, including a roller coaster of emotions, a lack of concentration, difficulty focusing and remembering, physical sensations such as a tightness in the throat, fatigue, and an overarching sense of loneliness. And no wonder, for you have not just lost your loved one, but also all the different roles that they played in your life: mentor, confidant, parent, etc.
It is for this reason and more that receiving support is so important in coping with grief. Research tells us that when we feel supported it facilitates healing in the grief process. This is why here at Beth Donovan Hospice, we aim to provide several different ways that you can receive support, which are detailed below. Which service you access depends on your level of need and comfort, and so feel free to look at each resource in turn in the box to the right, to see what is available.
To access these services, or if you are not sure what resource is right for you, call 613-258-9611 ext. 6 to speak with our grief and bereavement counsellor.
For other grief and bereavement resources, please refer to the Champlain Healthline.


The road from the airport is lined with irrigation canals in which children play and find respite from the malevolent heat. Hotels line the main street of Siem Reap, the nearest city to the ruins of Angkor and Bayon. Billboards provide warnings of the consequences for those seeking out child prostitution. Walking around Siem Reap, you observer almost every social stratum with little to no boundaries in between to denote wealth, from the most extreme poverty. Some neighborhoods house little communities of expatriates seeking refuge from the inequities of the first world, and transplanting those same inequities into the third where they can occupy a higher position in the food chain.
The children of South East Asia smile on a grand scale, but unlike in some other neighboring countries the joyous smile on the Cambodian adults seemed more like a mask. They still were able to smile, but the mouth is less supple and the eyes have grown dull and hard, from years of poverty, torment, and exploitation. We were solicited with services and trinkets everywhere we went, the only defense against it is to temporarily turn your self into some sort of blind monster, especially when you see the need in the peoples eyes. To think that a few hundred years before these peoples ancestors new the prosperity of a thriving civilization was very sobering.
We only spent one day viewing the nearby temples, all of which were magnificent monuments to the human will and to human ignorance. The Khmer empire, once the largest in South East Asia, ruled over parts of modern-day Laos, Thailand, and Vietnam. Under the reign of Suryavarman II, Angkor Wat was built in a period of thirty-seven years. Then under the rule of Jayavarman VII: Bayon, Ta Prohm, Banteay Kdei and Neak Pean, as well as the reservoir of Srah Srang, were built. The complete history of the region is beyond the scope of this article, but the downfall of this great empire can serve as a lesson to our current generation. In addition to military conflicts and failures, political unrest, and internal upheavals, one of the primary causes of the nations dissemination came from an ecological and infrastructural collapse. The extensive system of canals the Khmer people had developed for travel, trade, and irrigation became overburdened by an ever-growing population. In addition more trees had to be cleared to farm rice for the growing population, which led to extensive run-off draining into the canal system and further damaging their infrastructure. Sound familiar.


Pubs and Clubs welcomes Zaba Gaming Lounge, in Surfers Paradise for all your Club and entertainment needs, enquire online today.
Za'Ba Gaming Lounge is a meeting place for all occasions. Quench your thirst with a selection of 10 icy cold beers on tap, or ask any of the friendly staff to mix you a cocktail to remember! Catch the latest sport or special event on the big screen TV or simply unwind and relax. For those of you who fancy a flutter, try your luck on one of 35 gaming machines. Located on lobby level, open daily from 10am till late.


Mharo Singaar — रा जस् था न मे ं हे इस गा ने की धू म इसको सु नकर आपका दि ल भी ते ज धड़ क. Provided to YouTube by Sa Re Ga Ma Aho Karbhari Asha Bhosle Aandhala Marto Dola Saregama India Limited. Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd- -.
Aho namdeva mala ek chanas hava song download. Tags: Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd Song download Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd Full mp3 song download, Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd Mp3 Song download Aaho Namdeva Mala Ek Chanas Hawa. Aaho Karbhari mp3 song belongs new Marathi songs Aaho Karbhari by Asha Bhosle Aaho Karbhari available To free download on DjBaap. Marathi Film Industry Elder brother known as Dada Kondke is among the name who have introduced the the genre of comedy to Marathi cinema and Indian cinema.
This movie Mala Ek Chanas Hava is dedicated to Late Dada Kondke. Does he succeed in fulfilling his dream?
Airtel Champions League T20 A R Rahman Ola Ola Piano Notes Free download Airtel Champions League T20 A R Rahman Ola Ola Piano Notes mp3 for free. This comedy has been directed by Bal Mohite who has written the film` s screenplay as well.
` ` Mala Ek Chanas Hava` ` is dedicated to Late Dada Kondke. The film talks about a young talented man who wishes to make it big into films someday. Dada Kondke Film Hits songs Aaho Karbhari released on 31 Dec, 1973.
The Biggest indian movie songs, Film songs, movie songs, Best Collection of Indian songs, hindi songs, old hindi songs, bollywood songs, indian music, mp3 songs, 1990 to hindi songs download free indian song.
Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd- -. Search File : Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd-.
Dj Praniket Obd- Remix Song ee Download Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd. mp3 [ Download File] File Info Size of file: 11.
( Anand Shinde) Dj Praniket Obd Full mp3 song download, Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde) Dj Praniket Obd Mp3 Song download, Aaho Namdeva Mala Ek Chanas Hawa ( Anand Shinde).


text:
Fort Collins History: How Busy Lemay's Name is Actually a Mistake
Dave Jensen Published: December 8, 2022
It runs north and south throughout most of Fort Collins. Millions drive on it every year, seeing some of the great neighborhoods of The Choice City, along the way. What's the deal with Lemay's name?
If you're looking for an efficient way to get from one side of town to the other in Fort Collins, you can't go too wrong with Lemay. Sure, there's that dog-leg at Horsetooth, but overall Lemay is great. After all of these years, when it applies to Fort Collins history, Lemay's name isn't exactly straight.
Poudre-Valley-Hospital
Poudre Valley Hospital is just one business/facility that you'll find along Lemay, not far from Elizabeth. Hundreds of thousands of people have been in PVH over the years; If the hospital made a mistake on your bill, you'd be pretty upset. This name-thing with Lemay hasn't caused any such uproar.
Collindale
Facebook/Collindale Golf Course
Your drive along Lemay includes Collindale Golf Course. Of course, there's netting so that you don't get hit by errant balls, but it's still pretty. The course opened in 1971; it would be interesting to get an estimate on how may golf balls have been hit at Collindale versus how many cars have driven by the course, since then.
RELATED: THE BEST STEAK IN COLORADO IS IN FORT COLLINS
Drake and Lemay is an intersection that holds many memories for long-time residents of Fort Collins, with Woodword [Governor[ being there, Scotch Pines Shopping Center (with Toddy's back in the day) the church, and Williams Lake all being there.
WHAT'S WRONG WITH LEMAY'S NAME?
According to the City of Fort Collins, the street/avenue was named due to the efforts of Bob Everitt and Bill Tiley, who had helped to shape the city as we know it. The City Manager at the time, was renaming what was known as "Hospital Road," and wanted their names to be a part of it.
The two men, decided that a combination of Bob's father's name, "Les," and Bill's mother's name, "Mae," would be the way to go.
WHAT WAS LEMAY SUPPOSED TO BE?
They named it, 'LeMae."
According to the City of Fort Collins, an error was made when entering that, and it became what we know today: "Lemay.'
So, the next time you travel down Lemay with a passenger, you can let them know it's named not after one person, but two: Bob's dad, and Bill's mom. LeMae.
25 Life Hacks Fort Collins Residents Need to Try Right Now
Living in Fort Collins is great, but it could be even better. Read on to see 25 life hacks every Fort Collins resident needs to try, according to Reddit.
25 Reasons Why Residents Love Living in Fort Collins
It never hurts to appreciate the little things, so we're looking at why we're grateful for the Choice City. Read on to see 25 reasons why residents love living in Fort Collins.
7 Things To Appreciate About Fort Collins After Going To Denver
Northern Colorado isn't perfect, no place is perfect but we have it pretty good here and after spending a lot of time down in Denver over the past several weeks, here are a few things that I appreciate that much more about living here in NoCo.
Source: Fort Collins History: How Busy Lemay's Name is Actually a Mistake
Filed Under: Fort Collins
Categories: Articles, NoCo Life, NoCo News
Watch: Fort Collins Gets a Cool Mention in the 2007 'Reno 911!' Movie
Northern Colorado Snow Closures, Delays and Alerts
Cheers: That Cheap 'Chuck' Wine is Coming to Trader Joe's in Fort Collins
Is Northern Colorado's Krispy Kreme Doughnuts Finally Happening This Year? Yes
A New Tacos & Tequila Joint Has Opened in Fort Collins and Looks Terrific
Santa Left, But There's Still Lots of Free Ice Skating Left in Old Town Square
Should You Move to Fort Collins? Here's What Residents Have to Say


text:
Scott Andrew Mink (October 13, 1963 – July 20, 2004) was executed by the State of Ohio. A drug addict and alcoholic, he had been sentenced to die on June 29, 2001, for beating his 79-year-old father and 72-year-old mother to death with a hammer.

Mink had previously served six months in jail for theft.

The crimes occurred on September 19, 2000, when Mink, angry with his parents because they hid his car keys to prevent him from leaving the house to buy drugs and alcohol, attacked William and Sheila Mink while they slept in their rural Montgomery County home.

Enraged at being thwarted in his quest to get high, Mink beat his sleeping parents with a claw hammer until the head broke. He then battered them with cutting boards until those shattered. Finally, he repeatedly stabbed his parents with kitchen knives and strangled his mother with an electrical cord. Mink then stole his parents' credit cards and sold their belongings to purchase crack cocaine. He later confessed the brutal slayings to police.

He pleaded guilty before a panel of three judges and asked for a death sentence, which the judges handed down. Under Ohio law, all death sentences are automatically reviewed by an appellate court regardless of the inmate's desire to appeal. After his conviction was upheld by the Ohio Supreme Court on direct appeal in April 2004, Mink dropped his efforts to fight his sentence.

Mink spent 1,118 days (i.e., 3 years and 23 days) on death row before being executed by lethal injection – the second-shortest time, aside from Rocky Barton, since Ohio began executing criminals in 1999.

See also
 Capital punishment in Ohio
 Capital punishment in the United States
 List of people executed in Ohio
 List of people executed in the United States in 2004

General references
 Clark Prosecutor
 2005 Capital Crimes Report, Ohio Attorney General's Office  (PDF)

References

External links
 The High Price of Crack from The Malefactor's Register

1963 births
2004 deaths
21st-century executions by Ohio
21st-century executions of American people
American people executed for murder
Executed people from Ohio
Parricides
People executed by Ohio by lethal injection
People convicted of murder by Ohio
People from Dayton, Ohio

redpajama_set_name: RedPajamaWikipedia


pawan singh songs, IS FREE DOWNLOAD AFFAH NEW SITES. IT IS PROVIDE THE LATEST SONGS AUDIO AND VIDEO SONGS. »» Details for pawan singh songs, IS FREE DOWNLOAD AFFAH NEW SITES. IT IS PROVIDE THE LATEST SONGS AUDIO AND VIDEO SONGS.
If you are a new business so you want to be heard or buy your important message across, then an effective manuscript or article will surely do the trick. Where as royalty free music is undoubtedly a handy and inexpensive selection for those invoved with search of bulk music for restaurants, its not all royalty free music is produced equal. »» Details for When Is It Time to Upgrade From a Student Violin to a Fine Violin?


This recipe sounds yummmm. It comes from Sally's Baking Addiction.
(4) Wholesome and healthy. Well, compared to skillet brownies at least.
(5) Sweet and salty! Sweet and salty!
These were inspired by a carton of Trader Joes sea salt & turbinado sugar chocolate almonds that Marie brought with her when she visited. Aka the snack I COULD NOT STOP EATING. Have you ever tried them before? If so, you know the struggle.
Turns out, making them at home is cheaper. Don't know if that is a wonderful or terrible (dangerous) thing. Oh, and homemade always tastes better than store-bought. Case in point.
The number one ingredient is, duh, almonds. Since there are so little ingredients in this snack, make sure you're using high quality. The almonds? Diamond of California. No ifs, ands, or buts. Fresh, unsalted, nutrient-dense whole almonds. Doesn't get much healthier than that! And now, the chocolate.
Whoaaa. That sounded really awkward. You know what I mean.
A helpful tool = this 3-piece dipping tool set. These inexpensive tools will be your lifesaver when you begin making Sally's Candy Addiction recipes next month! I use the 3-pronged tool for these to help lift the almonds out of the chocolate pool and shake off as much excess chocolate as I can. It helped me separate the almonds so I wasn't left with chocolate almond clusters– rather, individual chocolate almonds.
The finishing touch is a sprinkle of sea salt and turbinado sugar (I use Sugar In The Raw). Any coarse sugar works! I loooooove the added crunch the sugar gives and the flavor balance of the sea salt. The nuts are wonderful simply coated in chocolate, but the light sprinkle of sugar & salt turns them up about 10 notches.
Only 4 simple, convenient ingredients transformed into something extraordinary. And within minutes too! Plus, they're a good source of protein, energy, and let's not forget all that glorious sweet and salty crunch. Mmm. Seriously, make these today.