text:
package RUM::Property;

use strict;
use warnings;

use Data::Dumper;

use RUM::Usage;
use RUM::UsageErrors;
use Carp;
use RUM::Pipeline;

sub handle {
    my ($conf, $opt, $val) = @_;
    $opt =~ s/-/_/g;
    $conf->set($opt, $val);
}

sub new {
    my ($class, %params) = @_;

    my $self = {};
    $self->{opt}       = delete $params{opt}     or croak "Need opt";
    $self->{desc}      = delete $params{desc};
    $self->{filter}    = delete $params{filter}  || sub { shift };
    $self->{handler}   = delete $params{handler} || \&handle;
    $self->{checker}   = delete $params{check}   || sub { return };
    $self->{default}   = delete $params{default};
    $self->{transient} = delete $params{transient};
    $self->{group}     = delete $params{group};

    if (my @extra = keys %params) {
        croak "Extra keys to RUM::Config->new: @extra";
    }

    $self->{name} = $self->{opt};
    $self->{name} =~ s/[=!|].*//;
    $self->{name} =~ s/-/_/g;

    return bless $self, $class;
}

sub opt { shift->{opt} }
sub handler { shift->{handler} }
sub name { shift->{name} }
sub desc { shift->{desc} }
sub filter { shift->{filter} }
sub checker { shift->{checker} }
sub default { shift->{default} }
sub transient { shift->{transient} }

package RUM::Config;

use strict;
use warnings;

use POSIX qw(ceil);
use Carp;
use FindBin qw($Bin);
use File::Spec;
use File::Path qw(mkpath);
use Data::Dumper;
use Scalar::Util qw(blessed);
use Cwd qw(realpath);

use Getopt::Long;
use RUM::Logging;
use RUM::ConfigFile;
use RUM::Pipeline;

our $AUTOLOAD;
our $log = RUM::Logging->get_logger;
FindBin->again;

our $FILENAME = "rum_job_config";

my $DEFAULT = RUM::Config->new;

our %DEFAULTS = (

    # These properties are actually set by the user

    alt_quant_model       => undef,
    alt_quant             => undef,

    count_mismatches      => undef,

    # These are derived from the user-provided properties, and saved
    # to the rum_job_config file

    ram_ok                => undef,
    input_needs_splitting => undef,
    input_is_preformatted => undef,
    paired_end            => undef,

);

sub is_top_level {
    my ($self) = @_;
    return  ! ($self->parent || $self->child);
}

sub should_preprocess {
    my $self = shift;
    return $self->preprocess || (!$self->chunk &&
                                 !$self->process &&
                                 !$self->postprocess);
}

sub should_process {
    my $self = shift;
    return $self->process || $self->chunk || (!$self->preprocess &&
                                              !$self->postprocess);
}

sub should_postprocess {
    my $self = shift;
    return $self->postprocess || (!$self->chunk &&
                                  !$self->preprocess &&
                                  !$self->process);
}

my %PROPERTIES;

sub _add_prop {
    my (%params) = @_;
    my $prop = RUM::Property->new(%params);
    $PROPERTIES{$prop->name} = $prop;
}

sub make_absolute {
    return File::Spec->rel2abs(shift);
}

sub reads {
    my ($self) = @_;
    return grep { $_ } ($self->forward_reads,
                        $self->reverse_reads);
}

sub pod_for_prop {
    my ($self, $name) = @_;
    my $prop = $PROPERTIES{$name};

    my ($forms, $arg) = split /=/, $prop->{opt};

    my @forms = split /\|/, $forms;

    my @specs;

    my $desc = $prop->{desc} || '';

    for my $form (@forms) {

        my $spec = sprintf('B<%s%s>',
                           (length($form) == 1 ? '-' : '--'),
                           $form);
        push @specs, $spec;
    }

    my $specs = join ', ', @specs;
    if ($arg) {
        $specs .= ' I<' . $prop->name . '>';
    }

    my $item = "=item $specs\n\n$desc\n\n";

    if (defined($prop->default)) {
        $item .= 'Default: ' . $prop->default . "\n\n";
    }

    return $item;
}

_add_prop(
    opt => 'version',
    desc => 'Version of RUM that was used to generate the config file',
);

_add_prop(
    opt => 'paired-end',
);

_add_prop(
    opt => 'step=s',
    transient => 1
);

_add_prop(
    opt => 'from-step=s',
    transient => 1,
    desc => 'Just run the job from the specified step. The step number can be found next to the step in the output of C<rum_runner status>.'
);

_add_prop(
    opt => 'forward-reads=s',
    filter => \&make_absolute,
    desc => 'Forward reads',
    check => sub {
        my $conf = shift;
        if (!defined($conf->forward_reads)) {
            return ('Please provide one or two read files');
        }
        if (defined($conf->forward_reads) &&
            ! -r $conf->forward_reads) {
            return ('Can\'t read from forward reads file ' .
                    $conf->forward_reads . ": $!");
        }
        else {
            return;
        }

    }
);

_add_prop(
    opt => 'reverse-reads=s',
    filter => \&make_absolute,
    desc => 'Reverse reads',
    check => sub {
        my $conf = shift;
        return if ! defined($conf->reverse_reads);

        if ($conf->reverse_reads eq $conf->forward_reads) {
            return ('You specified the same file for the forward '.
                    'and reverse reads.');
        }
        elsif (! -r $conf->reverse_reads) {
            return ('Can\'t read from reverse reads file ' .
                    $conf->reverse_reads . ": $!");
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt => 'limit-nu-cutoff=s',
);

_add_prop(
    opt  => 'quiet|q',
    desc => 'Less output than normal',
    transient => 1
);

_add_prop(
    opt  => 'help|h',
    desc => 'Get help',
    transient => 1,
);

_add_prop(
    opt  => 'verbose|v',
    desc => 'More output than normal',
    transient => 1,
);

_add_prop(
    opt  => 'child',
    desc => 'Indicates that this is a child process',
    transient => 1,
);

_add_prop(
    opt  => 'parent',
    desc => 'Indicates that this is a parent process',
    transient => 1,
);

_add_prop(
    opt  => 'lock=s',
    desc => ('Path to the lock file, if this process is '.
             'to inherit the lock from the parent process'),
    filter => \&make_absolute,
    transient => 1,
);

_add_prop(
    opt  => 'preprocess',
    desc => 'Just run the preprocessing phase',
    transient => 1,
);

_add_prop(
    opt  => 'process',
    desc => 'Just run the processing phase',
    transient => 1,
);

_add_prop(
    opt  => 'postprocess',
    desc => 'Just run the postprocessing phase',
    transient => 1,
);

_add_prop(
    opt  => 'chunk=i',
    desc => 'Just run the processing phase of the specified chunk.',
    transient => 1,
);

_add_prop(
    opt  => 'no-clean',
    desc => 'Don\'t remove intermediate files. Useful when debugging.',
    transient => 1,
);

_add_prop(
    opt  => 'output-dir|o=s',
    desc => 'Output directory for the job.',
    filter => \&make_absolute,
    check => sub {
        my $conf = shift;
        if (!$conf->output_dir) {
            return ('Please specify an output directory with -o or --output');
        }
    }
);

_add_prop(
    opt  => 'index-dir|i=s',
    desc => 'The path to the directory that contains the RUM index for the organism you want to align against.  Please use I<rum_indexes> to install indexes.',

    filter => \&make_absolute,
    check => sub {
        my $conf = shift;
        if (!$conf->index_dir) {
            return ('Please specify an index directory with -i or --index-dir');
        }
        elsif (!RUM::Index->load($conf->index_dir)) {
            return ($conf->index_dir . " does not seem to be a RUM index directory");
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt  => 'name=s',
    desc => 'A string to identify this run. Use only alphanumeric, underscores, and dashes.  No whitespace or other characters.  Must be less than 250 characters.',
    filter => sub  {
        local $_ = shift;

        my $name_o = $_;
        s/\s+/_/g;
        s/^[^a-zA-Z0-9_.-]//;
        s/[^a-zA-Z0-9_.-]$//g;
        s/[^a-zA-Z0-9_.-]/_/g;

        return $_;
    },

    check => sub {
        my $conf = shift;

        if (! $conf->name ) {
            return ('Please specify a job name with --name');
        }
        elsif (length $conf->name > 250) {
            return ('The name must be less than 250 characters');
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt  => 'chunks=s',
    desc => 'Number of pieces to break the job into.  Use 1 chunk unless you are on a cluster, or have multiple cores with lots of RAM.  Have at least one processing core per chunk.  A genome like human will also need about 5 to 6 Gb of RAM per chunk.  Even with a small genome, if you have tens of millions of reads, you will still need a few Gb of RAM to get through the post-processing.',
    check => sub {
        my $conf = shift;
        if ($conf->chunks) {
            return;
        }
        else {
            return ('Please specify the number of chunks to use with --chunks');
        }
    },
);

_add_prop(
    opt  => 'qsub',
    desc => 'Alias for \'--platform SGE --platform-flags "-pe make 2"\'.',
    handler => sub {
        my $self = shift;
        $self->set('platform', 'SGE');
      },
);

_add_prop(
    opt  => 'platform=s',
    desc => 'The platform to use. Either \'Local\' for running a job locally, or \'SGE\' for Sun Grid Engine.',
    default => 'Local'
);

_add_prop(
    opt => 'platform-flags=s',
    desc => 'Additional flags to give to the job submission program. Use in conjunction with the --platform option. If you are running on Sun Grid Engine and you do not specify --platform-flags, this will default to "-V -pe 2 -l mem_free=RAM,h_vmem=RAM", where RAM is calculated based on the genome size (usually 6 GB for a mammalian genome). If you specify --platform-flags, you may want to specify all of those flags. You can always see what flags are given to qsub by looking at the main rum.log file.',
);

_add_prop(
    opt  => 'alt-genes=s',
    filter => \&make_absolute,
    desc => 'File with gene models to use for calling junctions novel. If not specified will use the gene models file specified in the config file.',
    check => sub {
        my $c = shift;
        if ($c->alt_genes && ! -r $c->alt_genes) {
            return ("Can't read from alt gene file ".$c->alt_genes.": $!");
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt  => 'alt-quants=s',
    filter => \&make_absolute,
    desc => 'Use this file to quantify features in addition to the gene models file specified in the config file.  Both are reported to separate files.',
    check => sub {
        my $c = shift;
        if ($c->alt_quants && ! -r $c->alt_quants) {
            return ("Can't read from alt quant file ".$c->alt_quants.": $!");
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt  => 'blat-only',
    desc => 'Don\'t run bowtie, only blat and the parts of the pipeline that deal with blat results.',
);

_add_prop(
    opt  => 'dna',
    desc => 'Run in dna mode, meaning don\'t map across splice junctions.'
);

_add_prop(
    opt  => 'genome-only',
    desc => 'Do RNA mapping, but without using a transcript database.  Note: there will be no feature quantifications in this mode, because those are based on the transcript database.',
);

_add_prop(
    opt  => 'junctions',
    desc => 'Use this I<if> using the -dna flag and you still want junction calls. If this is set you should have the gene models file specified in the RUM config file (if you have one).  Without the -dna flag junctions generated by default so you don\'t need to set this.'

);

_add_prop(
    opt => 'no-bowtie-nu-limit',
    desc => 'Let bowtie produce an unlimited number of non-unique mappings for each read. This can result in extremely large intermediate files.'
);

_add_prop(
    opt => 'bowtie-nu-limit=s',
    default => 100,
    desc => 'The maximum number of non-unique mappings to let bowtie produce for each read.'
);

_add_prop(
    opt => 'count-mismatches',
    desc => 'Report in the last column the number of mismatches, ignoring insertions.',
);

_add_prop(
    opt => 'input-is-preformatted',
);

_add_prop(
    opt => 'input-needs-splitting',
);

_add_prop(
    opt => 'nu-limit=s',
    desc => 'Limits the number of ambiguous mappers in the final output by removing all reads that map to n locations or more.',

    check => sub {
        my $conf = shift;

        if (!defined($conf->nu_limit)) {
            return;
        }

        elsif ($conf->nu_limit =~ /^\d+$/ &&
               $conf->nu_limit > 0) {
            return;
        }
        else {
            return ("--nu-limit must be an integer greater than zero");
        }
    }
);

_add_prop(
    opt => 'max-insertions=s',
    desc => 'Allow at most n insertions in one read. Setting greater than 1 is only allowed for single end reads.  Don\'t raise it unless you know what you are doing, because it can greatly increase the false alignments.',
    default => 1,
    check => sub {
        my $conf = shift;
        if ($conf->forward_reads &&
            $conf->reverse_reads &&
            $conf->max_insertions > 1) {
            return ('For paired-end data, you can\'t set ' .
                    '--max-insertions > 1');
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt => 'min-identity=s',
    desc => 'TODO: Describe me',
);

_add_prop(
    opt => 'min-length=s',
    desc => 'Don\'t report alignments less than this long.  The default = 50 if the readlength >= 80, else = 35 if readlength >= 45 else = 0.8 * readlength.  Don\'t set this too low you will start to pick up a lot of garbage.',
    check => sub {
        my ($conf) = @_;
        my $x = $conf->min_length;

        if ((!defined $x) ||
            $x =~ /^\d+$/ && $x >= 10) {
            return;
        }
        else {
            return ('--min-length must be an integer greater than 9');
        }
    }
);

_add_prop(
    opt => 'preserve-names',
    desc => 'Keep the original read names in the SAM output file.  Note: this doesn\'t work when there are variable length reads.',

    check => sub {
        my $c = shift;
        if ($c->preserve_names && $c->variable_length_reads) {
            return ('Cannot use both --preserve-names and ' .
                    '--variable-read-lengths at the same time. Sorry, we ' .
                    'will fix this eventually.');
        }
    }
);

_add_prop(
    opt => 'quals-file|qual-file=s',
    desc => 'Specify a qualities file separately from a reads file.',
    check => sub {
        my $c = shift;
        if (defined($c->quals_file) &&
            $c->quals_file =~ /\//) {
            return ("do not specify -quals file with a full path, ".
                    "put it in the '". $c->output_dir. "' directory.");
        }
        else {
            return;
        }
    }
);

_add_prop(
    opt => 'quantify',
    desc => 'Use this I<if> using the -dna flag and you still want quantified features.  If this is set you *must* have the gene models file specified in the RUM config file.  Without the -dna flag quantified features are generated by default so you don\'t need to set this.'

);

_add_prop(
    opt => 'ram=s',
    desc => 'On some systems RUM might not be able to determine the amount of RAM you have.  In that case, with this option you can specify the number of Gb of ram you want to dedicate to each chunk.  This is rarely necessary and never necessary if you have at least 6 Gb per chunk.',

);

_add_prop(
    opt => 'ram-ok'
);

_add_prop(
    opt => 'read-length=s',
    desc => 'Specify the length of the reads. By default I will determine it from the input.',
);

_add_prop(
    opt => 'strand-specific',
    desc => 'If the data are strand specific, then you can use this option to generate strand specific coverage plots and quantified values.',
);

_add_prop(
    opt => 'variable-length-reads',
    desc => 'Set this if your reads are not all of the same length.'
);

_add_prop(
    opt => "blat-min-identity|minIdentity=s",
    group => 'blat',
    desc => 'Run blat with the specified value for -minIdentity',
    default => 93,
    check => sub {
        my ($conf) = @_;
        my $x = $conf->blat_min_identity;
        if ((!defined $x) ||
            $x =~ /^\d+$/ && $x <= 100) {
            return;
        }
        else {
            return ('--blat-min-identity or --minIdentity must be an integer ' .
                    'between 0 and 100');
        }
    }
);

_add_prop(
    opt => "blat-tile-size|tileSize=s",
    group => 'blat',
    desc => 'Run blat with the specified value for -tileSize',
    default => 12
);

_add_prop(
    opt => "blat-step-size|stepSize=s",
    group => 'blat',
    desc => 'Run blat with the specified value for -stepSize',
    default => 6
);

_add_prop(
    opt => "blat-rep-match|repMatch=s",
    group => 'blat',
    desc => 'Run blat with the specified value for -repMatch',
    default => 256
);

_add_prop(
    opt => "blat-max-intron|maxIntron=s",
    group => 'blat',
    desc => 'Run blat with the specified value for -maxIntron',
    default => 500000
);

sub is_specified {
    my ($self, $name) = @_;
    return defined $self->{$name};
}

sub parse_command_line {

    my ($self, %params) = @_;

    my $options    = delete $params{options};
    my $positional = delete $params{positional} || [];
    my $nocheck    = delete $params{nocheck};

    my %getopt;

    for my $name (@{ $options }, 'help') {
        my $prop = $PROPERTIES{$name} or croak "No property called '$name'";
        $getopt{$prop->opt} = sub {
            my ($name, $val) = @_;
            $val = $prop->filter->($val);
            $prop->handler->($self, $name, $val);
        };
    }

    my @errors;

    my $old_warn = $SIG{__WARN__};

    $SIG{__WARN__} = sub {
        push @errors, $_[0];
    };

    my $status = GetOptions(%getopt);

    $SIG{__WARN__} = $old_warn;

  POSITIONAL: for my $name (@{ $positional }) {
        my $prop = $PROPERTIES{$name} or croak "No property called '$name'";
        last POSITIONAL if ! @ARGV;
        $prop->handler->($self, $prop->name, shift(@ARGV));
    }

    if ($params{load_default}) {
        if ($self->output_dir) {
            if ( $self->is_new ) {
                die "There does not seem to be a RUM job in " . $self->output_dir . "\n";
            }
            $self->load_default;
        }
        else {
            die RUM::UsageErrors->new(
                errors => ['Please specify an output directory with --output or -o']);
        }
    }

    if (! $nocheck ) {

        for my $name (@{ $options },
                      @{ $positional }) {
            my $prop = $PROPERTIES{$name} or croak "No property called '$name'";
            my @these_errors = $prop->checker->($self);
            push @errors, grep { $_ } @these_errors;
        }

        if (@ARGV) {
            push @errors, "There were extra command-line arguments: @ARGV";
        }

        if (@errors || !$status) {
            die RUM::UsageErrors->new(errors => \@errors)
        }
    }

    if ($self->reverse_reads) {
        $self->set('paired_end', 1);
    }

    return $self;
}

sub new {

    my ($class, %params) = @_;

    my $is_default = delete $params{default};

    my $self = {};

    if ($is_default) {
        for my $prop (values %PROPERTIES) {
            if (defined (my $v = $prop->default)) {
                $self->{$prop->name} = $v;
            }
        }
    }
    else {
        $self->{_default} = $class->new(default => 1);
    }

    return bless $self, $class;
}

sub script {
    return File::Spec->catfile("$Bin/../bin", $_[1]);
}

sub postproc_dir {
    my ($self, $file) = @_;
    return File::Spec->catfile($self->output_dir, "postproc");
}

sub chunk_dir {
    my ($self) = @_;
    return File::Spec->catfile($self->output_dir, "chunks");
}

sub temp_dir {
    my ($self) = @_;
    return File::Spec->catfile($self->output_dir, "tmp");
}

sub in_output_dir {
    my ($self, $file) = @_;
    my $dir = $self->output_dir;
    return $dir ? File::Spec->catfile($dir, $file) : $file;
}

sub in_chunk_dir {
    my ($self, $name) = @_;
    my $path = File::Spec->catfile($self->output_dir, "chunks", $name);
}

sub in_postproc_dir {
    my ($self, $file) = @_;
    my $dir = $self->postproc_dir;
    mkpath $dir;
    return File::Spec->catfile($dir, $file);
}

sub chunk_file {
    my ($self, $name, $chunk) = @_;
    $chunk or return undef;
    return $self->in_chunk_dir("$name.$chunk");
}

sub opt {
    my ($self, $opt, $arg) = @_;
    return defined($arg) ? ($opt, $arg) : "";
}

sub read_length_opt         { $_[0]->opt("--read-length", $_[0]->read_length) }
sub min_overlap_opt         { $_[0]->opt("--min-overlap", $_[0]->min_length) }
sub max_insertions_opt      { $_[0]->opt("--max-insertions", $_[0]->max_insertions) }
sub match_length_cutoff_opt { $_[0]->opt("--match-length-cutoff", $_[0]->min_length) }
sub limit_nu_cutoff_opt     { $_[0]->opt("--cutoff",        $_[0]->nu_limit) }
sub faok_opt                { $_[0]->faok             ? "--faok" : ":" }
sub count_mismatches_opt    { $_[0]->count_mismatches ? "--count-mismatches" : "" }
sub paired_end_opt          { $_[0]->paired_end       ? "--paired" : "--single" }
sub dna_opt                 { $_[0]->dna              ? "--dna" : "" }
sub name_mapping_opt   { "" }
sub ram_opt {
    return $_[0]->ram ? ("--ram", $_[0]->ram || $_[0]->min_ram_gb) : ();
}
sub blat_opts {
    my ($self) = @_;
    my %opts = (
        minIdentity => $self->blat_min_identity,
        tileSize    => $self->blat_tile_size,
        stepSize    => $self->blat_step_size,
        repMatch    => $self->blat_rep_match,
        maxIntron   => $self->blat_max_intron);

    return map("-$_=$opts{$_}", sort keys %opts);
}

sub is_property {
    my $name = shift;
    exists $PROPERTIES{$name};
}

my %paths = (
    forward_reads => 1,
    reverse_reads => 1,

);

sub set {
    my ($self, %params) = @_;
    croak "Can't call set on $self" unless ref $self;
    for my $k (keys %params) {
        croak "No such property $k" unless is_property($k);
        $self->{$k} = $params{$k};
    }

    return $self;
}

sub save {
    my ($self) = @_;

    $self->set('version', $RUM::Pipeline::VERSION);

    my @specified = grep { $_ ne 'output_dir' && $self->is_specified($_) } $self->property_names;

    my %copy;

    for my $k (keys %{ $self }) {
        if (!$PROPERTIES{$k} ||
            !$PROPERTIES{$k}->transient) {
            $copy{$k} = $self->{$k};
        }
    }

    if (@specified) {
        my $filename = $self->in_output_dir($FILENAME);
        open my $fh, ">", $filename or croak "$filename: $!";
        print $fh Dumper(bless \%copy, __PACKAGE__);
        return 1;
    }
    return 0;
}

sub destroy {
    my ($self) = @_;
    my $filename = $self->in_output_dir($FILENAME);
    unlink $filename;
}

sub is_new {
    my ($self) = @_;

    my $new_filename = $self->in_output_dir($FILENAME);
    my $old_filename = $self->in_output_dir(".rum/job_settings");

    return ! ((-e $new_filename) ||
              (-e $old_filename));
}

sub load_default {
    my ($self) = @_;

    my $filename = $self->in_output_dir($FILENAME);

    if (! -f $filename) {
        warn "It looks like this job was run before with an older version of RUM (2.0.2_06 or earlier), because the job configuration is stored in $filename. I will try to use this older configuration.";

        $filename = $self->in_output_dir(".rum/job_settings");
    }

    $self->{_default} = do $filename;

    my $class = blessed($self);

    ref($self->{_default}) =~ /$class/ or croak "$filename did not return a $class";
    my $output_dir = realpath($self->output_dir);
    my $loaded_dir_orig = $self->{_default}->output_dir;
    my $loaded_dir = realpath($loaded_dir_orig);
    if (!$loaded_dir) {
        croak("I loaded a config file from '$output_dir', and it " .
              "had its output directory set to '$loaded_dir_orig', which does ".
              "not exist. Have you moved the RUM job directory? If so, you ".
              "can manually edit $filename and change the output_dir setting ".
              "to the new output directory");
    }
    if ($loaded_dir eq $output_dir) {
        delete $self->{output_dir};
    }
    else {
        croak("I loaded a config file from ".$output_dir.", and it " .
              "had its output directory set to ".$loaded_dir.". It " .
              "should be the same as the directory I loaded it from. This means " .
              "the config file is corrupt. You should probably start the job again " .
              "from scratch.");
    }

    if (!$self->version) {
        die("You seem to be trying to rerun a job that was set up with an " .
            "older version of RUM (v2.0.2_02 or earlier), which is ".
            "incompatible with the current version ($RUM::Pipeline::VERSION). ".
            "You will need to rerun the job from the beginning using the " .
            "current version of RUM.\n");
    }

    return $self;
}

sub get {
    my ($self, $name) = @_;

    ref($self) or croak "Can't call get on $self";
    is_property($name) or croak "No such property $name";

    if (defined $self->{$name}) {
        return $self->{$name};
    }
    elsif ($self->{_default}) {
        return $self->{_default}->get($name);
    }
    else {
        return;
        #croak "Property $name was not set. Config is " . Dumper($self);
    }
}

sub properties {
    sort keys %DEFAULTS;
}

sub settings_filename {
    my ($self) = @_;
    return ($self->in_output_dir($FILENAME));
}

sub lock_file {
    my ($self) = @_;
    $self->in_output_dir("rum_lock");
}

sub min_ram_gb {
    my ($self) = @_;
    my $index = RUM::Index->load($self->index_dir);
    my $genome_size = $index->genome_size;
    defined($genome_size) or croak "Can't get min ram without genome size";
    my $gsz = $genome_size / 1000000000;
    my $min_ram = ceil($gsz * 1.67)+1;
    return $min_ram;
}

sub should_quantify {
    my ($self) = @_;
    return !($self->dna || $self->genome_only) || $self->quantify;
}

sub should_do_junctions {
    my ($self) = @_;
    return !$self->dna || $self->genome_only || $self->junctions;
}

sub u_footprint { shift->in_postproc_dir("u_footprint.txt") }
sub nu_footprint { shift->in_postproc_dir("nu_footprint.txt") }
sub mapping_stats_final {
    $_[0]->in_output_dir("mapping_stats.txt");
}
sub sam_header {
    my ($self, $chunk) = @_;
    $self->chunk_file("sam_header", $chunk) or $self->in_postproc_dir("sam_header");
}

sub quant {
    my ($self, %opts) = @_;

    my $chunk = $opts{chunk};
    my $strand = $opts{strand};
    my $sense  = $opts{sense};
    if ($strand && $sense) {
        my $name = "quant.$strand$sense";
        return $chunk ? $self->chunk_file($name, $chunk) : $self->in_output_dir($name);
    }

    if ($chunk) {
        return $self->chunk_file("quant", $chunk);
    }
    return $self->in_output_dir("feature_quantifications_" . $self->name);
}

sub alt_quant {
    my ($self, %opts) = @_;
    my $chunk  = $opts{chunk};
    my $strand = $opts{strand} || "";
    my $sense  = $opts{sense}  || "";
    my $name = $self->name;

    if ($chunk) {
        my @parts = ("quant", "$strand$sense", "altquant");
        my $filename = join ".", grep { $_ } @parts;
        return $self->chunk_file($filename, $chunk);
    }
    elsif ($strand && $sense) {
        return $self->in_output_dir("feature_quantifications.altquant.$strand$sense");
    }
    else {
        return $self->in_output_dir("feature_quantifications_$name.altquant");
    }
}
sub novel_inferred_internal_exons_quantifications {
    my ($self) = @_;
    return $self->in_output_dir("novel_inferred_internal_exons_quantifications_"
                                    .$self->name);
}

sub preprocessed_reads {
    return shift->in_output_dir("reads.fa");
}

sub AUTOLOAD {
    confess "Undefined method $AUTOLOAD called on @_" unless ref $_[0];
    my ($self) = @_;

    my @parts = split /::/, $AUTOLOAD;
    my $name = $parts[-1];

    return if $name eq "DESTROY";

    return $self->get($name);
}

sub property_names {
    return keys %PROPERTIES;
}

sub property {
    my ($class, $name) = @_;
    return $PROPERTIES{$name};
}

sub step_props {
    return qw(preprocess process postprocess chunk parent child);
}

sub common_props {
    return qw(quiet verbose help);
}

sub job_setting_props {
    return qw(index_dir name qsub
              platform alt_genes alt_quants blat_only dna
              genome_only junctions bowtie_nu_limit
              no_bowtie_nu_limit nu_limit max_insertions
              min_identity min_length preserve_names quals_file
              quantify ram read_length strand_specific
              variable_length_reads blat_min_identity
              blat_tile_size blat_step_size blat_max_intron
              blat_rep_match count_mismatches no_clean
              platform_flags);
}

sub changed_settings {
    my ($self) = @_;
    my @props = $self->job_setting_props;
    my @changed = grep { $self->is_specified($_) } @props;
    return @changed;
}

1;

__END__

=head1 NAME

RUM::Config - Configuration for a RUM job

=head1 CONSTRUCTOR

=over 4

=item new(%options)

Create a new RUM::Config with the given options. %options can contain
mappings from the keys in %DEFAULTS to the values to use for those
keys.

=back

=head1 CLASS METHODS

=over 4

=item script($name)

Return the path to the rum script of the given name.

=back

=head1 OBJECT METHODS

=head2 Directories

These methods return the paths to some directories I need:

=over 4

=item postproc_dir

=item chunk_dir

=item temp_dir

=back

=head2 File paths

These methods return paths to files relative to some of my directories.

=over 4

=item in_output_dir($file)

Return a path to a file with the given name, relative to our output directory.

=item in_chunk_dir($name)

Return a path to a file with the given name, relative to our chunk
directory.

=item in_postproc_dir($file)

Return a path to a file with the given name, relative to our postproc directory.

=item chunk_file

Return a path to a file in our chunk directory, based on the given
filename, with the given chunk as the suffix.

=item opt($opt, $arg)

Return a list of the option and its argument if argument is defined,
otherwise an empty string.

=back

=head2 Getting option lists for scripts

The following methods can be used to get options to pass into sub
programs, based on the configuration:

=over 4

=item read_length_opt

=item min_overlap_opt

=item max_insertions_opt

=item match_length_cutoff_opt

=item limit_nu_cutoff_opt

=item bowtie_cutoff_opt

=item faok_opt

=item count_mismatches_opt

=item paired_end_opt

=item dna_opt

=item blat_opts

=item name_mapping_opt

=item ram_opt

=back

=head2 Serializing the configuration

=over 4

=item $config->settings_filename

Return the name of the file I should be saved to.

=item $config->save

Save the configuration to a file ($output_dir/rum_job_config)

=item RUM::Config->load($dir, $force)

Load a saved RUM::Config file.

=item $config->destroy

Delete the config file.

=back

=head2 Other

=over 4

=item is_property($name)

Return true if the given name is a property that can be configured.

=item set($key, $value)

Set the value of $key to $value.

=item get($name)

Return the value of the property with the given name.

=item properties

Return a list of the names of my properties.

=item lock_file

Return the path to the lock file that should prevent other instances
of the pipeline from running in the same output directory.

=item min_ram_gb

Return the minimum amount of ram that is needed, based on the genome size.

=back

=head2 Derived Values

These values are derived based on properties provided by the user or
the defaults:

=over 4

=item should_quantify

Return true if the pipeline should do quantifications, based on the
values of the I<dna>, I<genome_only>, and I<quantify> properties.

=item should_do_junctions

Return true if the pipeline should do junctions, based on the values
of the I<dna>, I<genome_only>, and I<junctions> properties.

=back

=head2 Output Files

These functions all return the paths to output files.

=over 4

=item u_footprint

=item nu_footprint

=item mapping_stats_final

=item sam_header

=item sam_header($chunk)

=item quant(%options)

=item alt_quant(%options)

Return the filename for a quant file or an alt quant file, optionally
given a chunk, strand, and sense. The following are valid keys for
options:

=over 4

=item chunk

=item strand

=item sense

=back

=item novel_inferred_internal_exons_quantifications

Return the name of the novel inferred internal exons quants file.

=item preprocessed_reads

Return the path to preprocessed reads file (reads.fa in the output
directory).

=item should_preprocess

=item should_process

=item should_postprocess

These methods return true if the corresponding phase of the pipeline
should be run, according to the options the user provided for this
invocation of rum_runner.

=item step_props

Returns the list of property names that all have to do with specifying
a step or phase of the pipeline to run.

=item reads

Return the list of read files that were supplied.

=item property_names

Return the list of names of all the valid properties.

=item property

Return the RUM::Property with the given name.

=item pod_for_prop($property_name)

Returns the POD for the property with the given name.

=item make_absolute($path)

Returns an absolute filename for the given path.

=item parse_command_line

Populate this config object with settings parsed fromt he
command-line, and optionally loaded from a saved config file.

=over 4

=item options

Names of RUM::Config properties that should be parsed from the command line.

=item positional

Names of RUM::Config properties, which should be picked in order from
the remaining command-line options.

=item load_default

If true, load my defaults from the config file saved in the output
directory specified on the command line.

=back

=item job_setting_props

Return the list of property names that all represent job settings that
should be set during initialization.

=item is_top_level

Return true if this is a "top-level" RUM proces, and not one that was
kicked off by another RUM process.

=item changed_settings

Return a list of names of properties that were changed from the
defaults in this configuration.

=item is_new

Return true if this is a new job, that is, if there is not already a
job configuraiton saved in the output directory.

=item is_specified($prop_name)

Return true if the user specified the given property on the
command-line.

=item common_props

Return a list of property names that should be accepted by every
action.

=back

redpajama_set_name: RedPajamaGithub


Imagine how interesting you could make a camping trip if you could make an espresso for your friends. That's just the kind of guy Eugene Cleland is – he was the one who brought along his espresso machine to camp. For Eugene making coffee is an art, from the choosing of the roast, to the making of the shot, the careful steaming of the milk, and finally, the art he creates with the foam. It is common for friends and family to gather at his home for a great coffee – many have told him he should open his own coffee shop. After much dreaming and consideration, that's exactly what he did.
Eugene and his wife, Betty Jean, began the journey to entrepreneurship in 2016 when they enrolled for the Community Futures Self Employment program. During that training, they had time to learn about business ownership, tackle the challenges in understanding business, develop their ideas, and create a viable business plan which would allow them to turn their passion into reality.
A year or so later, they are the proud owners of Medicine Hat's newest coffeehouse, Café Verve. For first-time business owners entering an already competitive industry, they are doing great things.
They have already mastered one thing: get people into your space. That's of paramount importance especially when you consider the two biggest players in the coffee and snack shop industry hold 83.9% of market share1 and they just happened to open a coffee shop during deep economic hardship in our region.
Not only is Eugene a skilled practitioner at creating that perfect cup of coffee, he is also a talented musician who spent 18 years with a local folk group called "Poet Lark". After a bit of a break, the group is going to perform live, at his very own business. The group is already rehearsing for their first performance which will surely generate a huge buzz in their community of music followers.
Betty Jean is a talented photographer. Even from a young age she was fascinated with photos. She owned her first professional camera at 20, studied photography at the Medicine Hat College and invested considerable time pursuing her passion in creating artistic portraits. When you walk into Café Verve, it's the first thing you notice: beautiful design, open space and a combination of art and design that will take your breath away. Eugene and Betty Jean have carefully planned their space for live music and to support local artists on their gallery style walls. There is usually live music every Friday night. Local art continually changes and adorns their walls. Café Verve has already hosted many musicians and artists' since they opened their doors May 5, 2017. They employ 4 full-time staff and 6 part-time staff.
1. Listen and heed to the advice of other business owners. Listen to the things they have learned.
2. Continue learning about business and remember when making decisions to ask yourself "Does this fit with your vision".
This story was written by Elizabeth Blair. Elizabeth is the regional innovation network (RIN) coordinator at Community Futures Entre-Corp and works to oversee activities with APEX. APEX is a Regional Innovation Network that supports the growth of innovative and technologically-oriented businesses in Southeast Alberta.
APEX is a collaborative initiative between three core service providers: Community Futures Entre-Corp Business Development, Medicine Hat College; and Alberta Innovates. APEX strives to support local entrepreneurs and small to medium-sized enterprises to develop and adopt new technologies, commercialize innovative new products, improve productivity, and get connected to Alberta's Innovation System.
1 Alvarez, Andrew. "Coffee & Snack Shops in Canada." IBISWorld. February 2017.


text:
An intercollegiate community of foreign policy writers, in collaboration with students worldwide.
Tyler Bowen
Chris Newton
U.S. Policy
Posted on April 9, 2015 October 4, 2015
The Dark Side of the Israeli Elections
"Strong against Hamas" – Slogan from Likud party campaign poster
Benjamin Netanyahu and the Likud Party's victory in the Israeli elections on March 17 portend a death blow for the hopes of a two-state solution in the near future. Netanyahu's successful usage of anti-Arab prejudice and aggressive nationalist rhetoric to galvanize voters showed the worst side of Israeli society. That this strategy was victorious should sound alarm bells in the ears of those who champion Israeli democracy and a two-state solution. While Likud's victory may represent a short-term threat to peace, the way in which Likud won this election highlights an endemic, long-term threat in the form of racism and exclusionary nationalism in Israeli society.
Netanyahu's eleventh-hour appeal to his right-wing supporters exposed how distant the prospect of peace is between Israelis and Palestinians. On March 16, Netanyahu, otherwise known as Bibi, declared that he would never sponsor the creation of a Palestinian state while he is Prime Minister. Turning his back on previous promises to work towards a two-state solution, Netanyahu said that "anyone who moves to establish a Palestinian state and evacuate territory gives territory away to radical Islamist attacks against Israel." This statement is unfortunately not a shock to those who have monitored Netanyahu's political career. On first becoming Prime Minister in 1996, Netanyahu went to Ariel, an Israeli settlement in the West Bank, and declared "we will be here permanently forever."
"While Likud's victory may represent a short-term threat to peace, the way in which Likud won this election highlights an endemic, long-term threat in the form of racism and exclusionary nationalism in Israeli society."
Even though Netanyahu stated in a March 19 interview that he does, in fact, support a two-state solution, his actions past and present show that he supports the creation of a Palestinian rump entity under the control of Israel rather than a viable Palestinian state. In July of 2014, he said in a press conference that he could never brook the existence of a fully sovereign Palestinian state because Israel could not afford to lose control over territory in the Jordan River Valley. Netanyahu emphatically stated this position again on March 16, winning the favor of many Israelis.
Netanyahu managed to gain still more support through an ugly appeal to xenophobia and tribalism. On the morning of the election, Netanyahu posted a video on Facebook warning Israelis that "Arab voters are coming in droves to the ballot boxes," and that they faced the specter of a left-wing government which would partition Jerusalem and retreat behind the 1967 borders. Netanyahu's advertisements during the last the week of the campaign stressed that he was the only obstacle standing between Israel and a hostile international community, both on its borders and in the West. Netanyahu even provocatively invoked the phrase "Tzav 8," a military order used to call up reserve troops during national emergencies, no small call-to-arms in a state with compulsory military service.
While it is right to criticize Netanyahu for employing such scare tactics to win an election, it is more important to recognize that he was responding to the attitudes of the Israeli electorate. Two weeks before comments shifted sharply to the right, polling data indicated that Israeli voters who tended to support Netanyahu liked him for his ability to withstand pressure from the international community and to do what is in the best interest of Israel. Perhaps more tellingly, citizens in the West Bank settlements generally dislike Netanyahu for being too far on the left. Yet many of the votes which Netanyahu gained in this election through his last-minute stumping came from ultra-conservative voters who normally vote for the far-right Jewish Home Party. Given the attitudes of such right-wing voters in Israel, it is not surprising that Netanyahu spouted xenophobic nationalism in an attempt to gain more votes.
"Given the attitudes of such right-wing voters in Israel, it is not surprising that Netanyahu spouted xenophobic nationalism in an attempt to gain more votes."
In addition, for all of the rhetoric Israelis voice about treating Arab citizens with respect, they remain comfortable with the Arab population only so long as it does not wield any political clout. About 20% of the Israeli population is Arab-Israeli, and the number of Palestinians in Israel, the Occupied Territories, and neighboring refugee camps is about 6.8 million, outnumbering the Jewish-Israeli population of 6.2 million. Despite their large proportion of the Israeli population, Palestinians own only 3% of the land in Israel. About half of Arab-Israeli families live below the poverty line, compared to only 15% of Jewish-Israeli families. There are also over 20 laws that discriminate against Arab-Israelis, and the Or Commission, a 2003 government inquiry, says that "the government of the Arab sector has been primarily neglectful and discriminatory." While Israel claims that its Arab citizens are equal, they are clearly second-class citizens.
Netanyahu did not singlehandedly cause Israeli citizens to fear Arab voters, a viable Palestinian state, or a more cooperative Israeli head-of-state. He merely recognized existing fears within Israeli society, ratcheted them up, and played upon them to his advantage. This should be the main cause for disquiet regarding the prospects of a two-state solution. Despite moments like the signing of the Oslo Accords and the Camp David Accords that gave the international community hope that peace could be found in the Holy Land, the 2015 elections reveal to us just how far away peace truly is.
While the blame does not lie solely on the Israelis for the lack of a peace deal, as Hamas' actions have done just as much, if not more, to incite conflict, Israeli nationalism presents a serious impediment. Likud's victory and the success of other right-wing parties indicate a society that is gripped by fear and racism. Until this can be overcome, the integrity of Israeli democracy and the survival of a two-state solution are at stake.
Tyler Bowen is studying Political Science and English in the College of Arts and Letters at the University of Notre Dame. He is a Staff Writer for The Diplomacist.
Image Attribution: "Strong against the Hamas" by Hadar Naim, licensed under CC BY-NC-SA 2.0
View all posts by Tyler Bowen
Categories Middle East, Politics & SocietyTags Benjamin Netanyahu, Israel, Israeli Elections, Middle East, Palestine, Politics & Society, Tyler Bowen
Previous Previous post: Written Out of History: Macedonia's Nationalist Rhetoric and the Oppression of Ethnic Albanians
Next Next post: America's Myopic Middle Eastern Security Policy
Re-evaluating the Al-Shabaab Strategy: Does President Trump have a Point?
The Philippines' Strongman Syndrome
View diplomacist's profile on Facebook
View diplomacist's profile on Twitter

redpajama_set_name: RedPajamaCommonCrawl


text:
Humankind hit consoles with 6 new Latin American cultures
Sega and Amplitude announced they are adding six new cultures from Latin America to Humankind in the form of the game's second DLC for the PC version. And come November, the civ-building game will debut on the Xbox and PlayStation game consoles.
The companies made the announcement at the Summer Game Fest today. The PC game will have its Cultures of Latin America DLC pack. It will include six new cultures including Caralans, Nazca, Taíno, Inca, Argentinians, and Cubans.
Acclaimed narrative adventure Road 96 is getting musical…
The DLC will also have six new Wonders: Pyramid of the Sun – Teotihuacan, Maracana Stadium, Salar de Uyuni, Salto Angel, Lençóis Maranhenses, and the Atacama Desert. And it will feature nine independent peoples and 15 narrative events. The main game will have a major Bolivar patch update.
The console version is now available to pre-order for Xbox Game Pass, Xbox Series X/S, Xbox One, PlayStation 4, and PlayStation 5. Aspyr Media is doing the console ports.
"As big fans of Humankind, we're ecstatic to partner with Sega and Amplitude to bring this amazing game to new audiences," said Michael Blair, senior director of business development at Aspyr, in a statement. "With our history in this space, we know that we'll be able to deliver a deep strategy experience that really shines on consoles."
americanConsolescultureshumankindLatin
Fall Guys free-to-play available on Xbox and Switch Consoles
LEGO Brawls released on 2nd September for PC & consoles
GameStop is Restocking PS5 Consoles Tomorrow
Microsoft has discontinued all Xbox One consoles


String Pendant Light Interior | Dreamingincraft.com flos string light pendant. string pendant lighting. string light round pendant.
String Pendant Light Attractive George Home Cream Shade Garden For 2. String Pendant Light Contemporary Stunning DIY Home Decor Pinterest In 3. String Pendant Light New Lamp ScanDesigns Quality Home Furniture For 4. String Pendant Light Popular Ball Lights Parliament Interiors Throughout 5. String Pendant Light Contemporary L2 1661 VandM Hemp Round Lights 6102 ITALUX 6104 With Regard To 6. String Pendant Light Contemporary Perry Braided By Iniko Zanui With 7. String Pendant Light Incredible Amazon Com 20 By Nuevo HGML283 Home Kitchen With Regard To 8. String Pendant Light Brilliant Lamp With Regard To 9. String Pendant Light Amazing Lamp Inside 10. String Pendant Light Contemporary Ball Lights Parliament Interiors In 11. String Pendant Light Popular How To Make Your Own Lamp Apartment Therapy Intended For 12. String Pendant Light New Metro Modern Lucite Lamp Within 13. String Pendant Light Awesome Woven Lamp Hemp Diy Com For 14. String Pendant Light Elegant Glass Globe Pendants Desert Domicile Intended For 15. String Pendant Light Contemporary Cooper Small White Chic Chandeliers For 16. String Pendant Light Attractive Multi Color Fashion Modern Manual Knitted Hemp Intended For 17. String Pendant Light Popular Lamp Love Door Sixteen With 18. String Pendant Light Amazing Random Chandelier Within 19.


text:
Q: Python Dictionary Spell Checker, 'TypeError: write() takes no keyword arguments' I'm using a python dictionary to compare Shakespeares full works and a 10,000 word dictionary, the code should output all words which weren't found in the 10,000 word dictionary to a separate file called 'SpellChecker.txt'. I believe everything in this code is running correctly. I am only coming across one error to do with saving the data to the output file and can't seem to fix it. Any help is appreciated.
Error:
Traceback (most recent call last):
  File "/Users/JakeFrench/Desktop/HashTable.py", line 29, in <module>
    f1.write(word+'\n', encoding= 'utf-8')

    TypeError: write() takes no keyword arguments
import re
import time
start_time = time.time()

f1=open ('SpellChecker.txt', 'w+')

Dictionary = {}
Document = []
with open ('10kWords.txt', encoding= 'utf-8') as f:
        for word in f:
            Dictionary[word.rstrip()] = 1

with open ('ShakespeareFullWorks.txt', encoding= 'utf-8') as f:
    content = f.read().split(" ")
    content = [item.lower() for item in content]
    content = ' '.join(content)
    content = re.findall("\w+", content)
    for line in content:
        Document.append(line)

for line in content:
    for word in line.split():
        if word.lower() not in Dictionary:
            f1.write(word+'\n', encoding= 'utf-8')

f1.close()

print ("--- %s seconds ---" % (time.time() - start_time))

A: Just remove the encoding attribute from the write method and insert it in the open function as follows:
f1=open ('SpellChecker.txt', 'w+', encoding='utf-8')
  ...
f1.write(word+'\n')

redpajama_set_name: RedPajamaStackExchange


Money doesn't grow in trees but who said you can't put your jewellery up in a tree? Win this gorgeous jewellery holder, it has lots of space for all your beautiful jewellery. And it's not just a beautiful talking point on your dressing table - it also prevents chains and necklaces from tangling up.
Pictures don't do justice to this pretty tree-shaped jewellery holder with beautiful birds and lots of branches where you can hang your bracelets and necklaces, and the leaves have holes where you can handily store your earrings.
Messy boxes or drawers will be a thing of the past, the jewellery tree will keep all your ornaments safe in one place and it looks fantastic too. There's even a basket for rings so that it can really hold all your jewellery. Please note that the jewellery in the picture is not included in the prize.
Enter our free competition and you could win this Jewellery Bird Tree totally for free. Also remember to share this competition with your friends using Facebook, Twitter and Google+ because you get 10 points when they join Winneroo. Good luck guys!


BACKGROUND: New oral anticoagulants (NOACs), including direct thrombin inhibitors (DTIs) and factor Xa (FXa) inhibitors, are emerging alternatives for prophylaxis and treatment of atrial fibrillation (AF) and venous thromboembolism (VTE). PURPOSE: To compare the benefits and harms of NOACs versus warfarin for AF and VTE. DATA SOURCES: MEDLINE, EMBASE, and the Cochrane Database of Systematic Reviews from January 2001 through July 2012; U.S. Food and Drug Administration (FDA) database for adverse event reports. STUDY SELECTION: English-language, randomized, controlled trials (RCTs) comparing NOACs with warfarin for management of AF or VTE and observational studies and FDA reports on adverse effects. DATA EXTRACTION: Two independent reviewers abstracted data and rated study quality and strength of evidence. DATA SYNTHESIS: Six good-quality RCTs compared NOACs (2 DTI studies, 4 FXa inhibitor studies) with warfarin. In AF, NOACs decreased all-cause mortality (risk ratio [RR], 0.88 [95% CI, 0.82 to 0.96]); in VTE, NOACs did not differ for mortality or VTE outcomes. Across indications, adverse effects of NOACs compared with warfarin were fatal bleeding (RR, 0.60 [CI, 0.46 to 0.77]), major bleeding (RR, 0.80 [CI, 0.63 to 1.01]), gastrointestinal bleeding (RR, 1.30 [CI, 0.97 to 1.73]), and discontinuation due to adverse events (RR, 1.23 [CI, 1.05 to 1.44]). Subgroup analyses suggest a higher risk for myocardial infarction with DTIs than with FXa inhibitors. Bleeding risk for NOACs may be increased in persons older than 75 years or those receiving warfarin who have good control. LIMITATION: There were no head-to-head comparisons of NOACs and limited data on harms. CONCLUSION: New oral anticoagulants are a viable option for patients receiving long-term anticoagulation. Treatment benefits compared with warfarin are small and vary depending on the control achieved by warfarin treatment. PRIMARY FUNDING SOURCE: Department of Veterans Affairs.


If you prepare a scuba diving mask correctly, it helps to eliminate fogging problems permanently. 1 very inexpensive way to prevent fogging is to take one-two drops of infant shampoo and smear it around the lens of your mask. A time-worn custom to stop fogging is to simply spit in your mask and rub it over the surface area of the mask's lens, but this has recently arrive into disfavor. Masks that have been spit in have a tendency to develop some extremely nasty black mildew with time.
Once you've rented your vehicle from Vehicle Rental Israel, you ought to definitely enjoy every thing this 1 of a kind seaside vacation resort has to offer. Eilat is a outstanding and tranquil location exactly where the sunlight shines virtually all year spherical and it is much from the hustle and bustle of the middle of the nation.
You'll also have to take a appear at drinking water resistance when it arrives to males's watches. Once more, this depends on the wearer's requirements. If they love scuba-diving, you don't need drinking water resistant, but water evidence. There's a big different in between the two, as diving watches can be submerged below drinking water with no harm, but drinking water resistant indicates it can only consider some dampness prior to getting ruined. Make certain you know exactly degree of resistance required before purchasing.
Ios is widely known for the vibrant nightlife and parties. Resorts right here begin at a extremely reduced cost of $13.fifty a night! That's fairly much a good quantity for vacation rentals. At sunset, you will discover numerous people from all over the globe stuffed in the discos and partying. Greek, Italian, Thai, Cuisines are not at all an problem here. But, make certain you check the cafe prices prior to consuming there!
Alas something great from the Harry Potter franchise. We were worried that the Goblet of Fire would be the best in the film series. But "Harry Potter and the Deathly Hallows: Component I" has surpassed our worry and sent a outstanding movie. This movie can be termed as the very best movie in the Harry Potter franchise with the Goblet of Hearth not being much powering.
The location is ideal since it is near to almost all of the action locations accessible in the nation. scuba dive st lucia adventures wouldn't be much of a issue because the Fantastic Blue Gap and the Belize Barrier Reef are only a few minutes away!
Harkness Memorial State Park in Waterford is established amongst the summer mansion of the Harkness family members. The mansion by itself is magnificence at its finest. The grounds feature magnificent gardens and are perfect for image taking. Excursions of the mansion are available at a charge. There are more than 230 acres for picnicking or recreation. The seaside offers a picturesque view of Long Island Audio. There is no swimming, but plenty of fishing and shaded picnicking locations for awesome family members events.
For all those of you who adore to discover and study the maritime ecosystem, Panama is nothing but a paradise. Visit this place and make your vacation the memory of a life time.


After a long wait OMA's one of the most important project is coming to its end – 16th century Fondaco dei Tedeschi transformed into a modern department store and public area.
OMA (The Office for Metropolitan Architecture) was founded in 1975 by Dutch and Greek architects, Rem Koolhaas and Elia Zenghelis. The company has a leading position in the international architecture arena and its projects are located in various parts of the world. It should be noted that OMA has worked on the buildings of historical meaning in the past (Fondazione Prada in Milan, the Garage Center for Contemporary Art in Moscow and so on), therefore company was ready for the obstacles working on Fondaco dei Tedeschi as on a historical monument entailed.
Fondaco dei Tedeschi was built in 1228 and is located on Grand Canal, near the Rialto Bridge. The building changed its function many times over the years; it was a trading center for German merchants in the beginning, later a customs house under Napoleon, and in the twentieth century, a post office under Mussolini. Over time Fondaco dei Tedeschi underwent numerous radical structural changes; in 1505-1508 building was reconstructed due to the fire.
The building has a square shape and is 9000 square meters in size. Architecture is typical to Italian Renaissance style, has three levels which faces large central courtyard; in the courtyard there's a medieval well. At the lower floor, five large rounded arcades enclose a portico (this place was used to store goods unloaded from the Grand Canal). The second floor has a long row of double and single mullioned windows which, at the upper floors, are paired by smaller quadrangular windows. The top of the façade has merlons.
Fondaco dei Tedeschi has received the status of cultural monument in 1987, which automatically banned any changes in building's structure. Despite these restrictions, after talking with government, OMA managed and developed a work plan acceptable to everyone.
The project entails finite number of interventions and vertical distribution devices, among other little details, central pavilion above courtyard was renovated with steel and glass floor, creating space for hosting events. Escalators were installed with wood-paneled sides and bright red steps, additional entrances to the building were created from Campo San Bartolomeo and the Rialto and, of course, wooden terrace on the rooftop, which offers a perfect view over the city. Architects don't touch rooms' layout and try to maintain building's historical face. Glimpses of terracotta-colored partitions with geometric cutouts can be spied behind the internal colonnades. Other interior spaces are clad with golden metal and mirrors. Furthermore, some aspects of the original building have been restored. For example, the walls of the gallerias once again host frescoes that reappear in contemporary form.
Benetton family in 2009 commissioned OMA to transform Fondaco dei Tedeschi into a trade and entertainment center. Company introduced building's design to public in 2009 and began negotiating with country officials to begin the renovations, which was granted in 2013. As said before, in 2016 reconstructions have been finished and Hong-Kong based firm DFS is now working to prepare it for rental.
OMA's aim is that above mentioned building isn't a source of nostalgia in viewers, to demystify its image. It can be said that this reconstruction is building's first step into a modern history.


Concrete work going on. Entry partially finished. Walkway along side Religious Center to new parish office finished. Ceiling tiles installed throughout building. Finish touches of painting going on. State of the art fire control panel installed, tested and working. Panel has direct contact to Cobb County Fire Control Center.


There's a brand new hotel in the 1000 Islands, upstate New York's most lauded destination, and it is turning heads as the first major new full-service hotel to be built in the region in three decades.
Perched on the St. Lawrence River, 1000 Islands Harbor Hotel is a sweet spot for travelers, appealing to diverse interests with a wealth of on- and off-property experiences. Whether guests are after outdoor adventure, a family getaway or a bit of exploring, the AAA Four Diamond hotel has rolled out a slew of packages that speak to every traveler, and they're ripe for discovery.
• For wine enthusiasts, the 1000 Islands region is home to the Seaway Wine Trail, winding through 78 miles of the scenic byways with award-winning wineries and vineyards. Starting May 22, aficionados who book the Wine Tasting package will receive overnight accommodations, three tastings including two wineries and one distillery, a visit to Clayton's renowned River Rat Cheese and breakfast for two. Rates start at $199.
• For explorers, Captain Jeff Garnsey will take guests on a three-hour cruise of the 1000 Islands via the St. Lawrence River, complemented by a local wine and cheese pairing. Accommodating up to six people, the cruise is fully customizable and can also include a tour of the stunning Boldt Castle, a bird's eye view of Millionaires Row, or a trip down the famous Bootleggers tour dating back to the 1920's. Based on overnight accommodations for two, rates start at $299. Each additional person is $50. Available May-November, 2015.
• For wellness buffs, 1000 Islands Harbor Hotel partners with two local spas, bringing guests the ultimate in relaxation during their stay. Guests who book The In-House Spa package, available beginning May 22 with rates starting at $309, will receive overnight accommodations for two, a welcome amenity of sparkling water and strawberries, an in-room massage by Creative Edge Salon and breakfast at Seaway Grille. An Off-Site Spa package (rates start at $289) for those looking for the full spa experience is also available in collaboration with River Day Spa and Salon.
• For lovebirds, 1000 Islands Harbor Hotel's Romantic Getaway includes deluxe overnight accommodations, rose petal turndown, a bottle of Champagne, a half dozen chocolate covered strawberries and breakfast for two at the Seaway Grille. Rates start at $219. A Bed & Breakfast package is also available with rates starting at just $129.
Located just south of the Canadian border in the spectacular countryside of the 1000 Islands region, the quaint village of Clayton is considered one of America's best small towns. Ideal for a long weekend getaway from major cities throughout the Northeast (New York City is a six-hour drive), the region is dotted with award-winning wineries along the 1000 Islands Seaway Wine Trail and more than 20 golf courses. There are trails for three-season hiking and cross-country skiing and snowmobiling in winter. Visitors will find a wealth of historic and cultural attractions, including the Clayton Opera House, the 1000 Islands Arts Center dedicated to hand-weaving and other heritage arts, the Antique Boat Museum, and the Boldt and Singer Castles – two Gilded Age mansions on private islands. The St. Lawrence River draws outdoor enthusiasts with the promise of world-class fishing, kayaking and rafting, while customizable river cruises offer sightseeing adventures past dozens of islands, lighthouses, mansions, and more.
1000 Islands Harbor Hotel offers 105 deluxe guest rooms and suites, sophisticated dining, and state-of-the-art function space on the St. Lawrence riverfront in the heart of New York's spectacular 1000 Islands region. The hotel opened in July 2014 as the third of Buffalo-based Hart Hotels' Harbor Hotels brand, which also includes the Four Diamond-rated Portland Harbor Hotel in Portland, Maine, and Watkins Glen Harbor Hotel in Watkins Glen, New York. The 1000 Islands Harbor Hotel is located at 200 Riverside Drive, Clayton, NY 13624. Call 315-686-1100.


text:
Cheryl Francis Taylor (born March 1964) is the Controller of CBBC in Salford.

Early life
She was brought up in Liverpool in a family of Quakers. She went to the independent boarding school The Mount School, York, where she became Head Girl. York was known for its Quaker heritage, which largely centred around the famous chocolate factories. She studied Drama at the University of Bristol.

Career

Hat Trick Productions
She was Head of Comedy at Hat Trick Productions. With Carmel Morgan, she co-created Drop Dead Gorgeous for BBC Three.

CBBC
On 29 June 2012 it was announced that she would be the next Controller of CBBC. She began in September 2012. On 21 December 2012, children's teatime programming on BBC One finished.

Personal life
She lives near Hebden Bridge in West Yorkshire.

See also
 Kay Benbow, Controller of CBeebies

References

External links

 Prolific North
 BBC biography

1964 births
Alumni of the University of Bristol
BBC executives
British Quakers
Broadcast mass media people from Liverpool
People educated at The Mount School, York
People from Hebden Bridge
Living people

redpajama_set_name: RedPajamaWikipedia


Our customers are our primary focus. Master's Appliance & Refrigeration, LLC has been providing Pasco, WA and the Tri-Cities of Richland and Kennewick with quality home appliance repairs, parts, and new and used appliances for over three decades. We strive to stay up-to-date on the latest appliances and technologies. We keep only the best in stock and work to make sure we can repair any appliance we come across. Call or contact us today at 509-547-7523.
Master's Appliance & Refrigeration, LLC repairs and sells new and used home appliances in Pasco, WA and the Tri-Cities of Richland and Kennewick. We are celebrating over 30 years of home appliance experience! Our technicians can recognize your appliance issue and have it fixed quickly.
If you need an appliance for your home, you can purchase new or used home appliances in our store. For those who want to do it yourself, Master's Appliance & Refrigeration, LLC features new and used appliance parts for sale.
Copyright © 2019 Master's Appliance & Refrigeration, LLC, all rights reserved.


WELCOME HOME TO DAKOTA CREEK!
Located in a cozy neighborhood, just minutes from the Claremont Colleges, Cal Poly Pomona, Montclair Plaza and plenty of shopping centers, Dakota Creek is the BEST place to call home. COMFORT YOU DESERVE - QUALITY YOU EXPECT. Dakota Creeks large floor plans, up to 1160 square feet, are large enough to give you that comfort you desire. Come home and enjoy a quiet evening in your Custom apartment home, relax in one of our three spas, and lay back and enjoy the gorgeous lush landscaping we love to offer. We are near shopping, fine dinning, Claremont Colleges and major freeways. Don't waste any time! Call today! Our professional staff is waiting anxiously to show you how you can have it all at an affordable price. We look forward to your call.


It's time for another monthly favourites, featuring my fashion and lifestyle loves from the last month of 2016. There are clothes, fashion accessories, books, home decor and work accessories.
Firstly, I want to share with you a couple of bits of loungewear that I've been loving. I literally live in my Food Geek Apparel Made of Sprinkles & Sarcasm Sweater* (£35 from Food Geek Apparel) – it is so cosy, thick and it has a lovely light fleecy interior too. I wear this both around the house and out on casual supermarket trips. I might have to collect all of the cute slogans they do. Brunch Squad is definitely next!
I've also found my Ladies Shirt With Lace Sleeves (£14.99 from Lesara) so handy over the festive period as it's comfy and relaxed enough for when I don't want to get dressed up, but because of the lace sleeves, it looks like I've put effort in when guests come round.
Sticking with fashion, there are also some accessories that I've been using all month. I don't really wear a watch often and until this new one, I've just had one gold-toned metal Kate Spade one. When Swatch invited me to choose one of their timepieces, I had to go for one that was more comfortable and better for day-to-day wear. I love this pale pink one with gold detailing on the face* (£38 from Swatch) as it goes with everything as feels really weightless on.
I've also been loving my Zoella Lifestyle On My Travels Back Pack (£25, was £50, from Boots). The backcpack looks really chic and it's a great alternative to a handbag when you can't be bothered carrying one of when you want a more relaxed look. The backpack came with a cute marble-print travel cup inside it, a great 'Inspire' keyring that is now on my keys and a set of cute slogan pencils.
I haven't seen the Fantastic Beasts & Where To Find Them movie yet, but you don't need to in order to be able to enjoy the Fashion Sketchbook (£9.98 from Amazon). It's actually great for anyone who likes designing beauty or fashion looks as lots of the pages involve you creating your own designs rather than just colouring between the lines like most adult colouring books.
Another book i've really enjoyed is the latest Zoe Sugg aka Zoella novel, Girl Online Going Solo (£7.99 as part of monthly membership from Audible). I listened to this as an audiobook via Audible – Hannah Tointon is a great narrator. I've really enjoyed the whole Girl Online series, even although I'm much older than the intended reader, but this one is defintiely the most grown-up of the books released so far. If you haven't read any of the Girl Online books, you do need to start at the beginning of the series to be able to follow it properly. It follows late-teen blogger Penny and her best friend Elliott as they navigate life and relationships (especially one key one in the public eye).
Finally, I have a couple of more random bits. I got a new marble-print personalised 15-inch laptop case (£28.07 from Case Company) to go with the new marble vinyl sticker that I currently have over the lid. It's really good quality and I got my initials put on the bottom in baby pink.
I'm also obsessed with this numbered wooden set of drawers that I got from Sainsburys a couple of months ago. I'm using it for jewellery storage. I'm not sure if you can still get it, but there might be the odd random one left in your local store.


Stroud Is All Over the Place: Super Fast, Super Chicken Soup!
Super Fast, Super Chicken Soup!
The situation is dire. I've been doing what retired guys do all day. Read. Write. Play golf. Drink beer. Play tennis. Flirt with women young enough to be my daughter, if I had a daughter.
Now my wife is on her way home from a hard day at work and I need to make supper so she won't think I spent the day playing golf, tennis, etc. If you know my wife, don't tell her about the etc. A little secret between kitchen freaks?
I search the refrig and pantry, open a bottle of delicious Italian white wine and have a couple of glasses. One more glass won't be missed, if I save enough to cook with. Put another bottle of white wine in the frig.
Put a splash or two of oil in a medium frying pan and add a pat or two of butter. Set to low medium heat. When the butter melts, toss in the sliced onion and garlic. Keep an eye on the onion/garlic and stir often. Meanwhile, cut the chicken into one inch cubes. If you're OCD and take out your ruler to measure the cubes, you will be not be offered wine or a spoon.
When the onions/garlic are just barely browning, take them off the heat and set aside.
In a good sized large pot or Dutch oven, add oil and butter (see above) and toss in the chicken. When the meat turns white on all sides, add the cup of wine and reduce the liquid to half. Now add the onions, red bell pepper, the chicken broth + packets, and all the herbs. Stir, taste and add salt and pepper. Add the can of stewed Mexican style tomatoes. I pour in the juice and use my hands to break up the big chunks.
When the mixture comes to a boil, add the frozen vegetables. When the soup comes back to a boil, turn off the heat. Taste and add salt and pepper as needed. Cover.
Soup is on and ready to eat, but since my wife is not yet home, I'll have another glass of vino and let the soup flavors mellow while I join in the mellowing.
Ah, here she is! Time to pop another cork, spoon out the soup, add a big dollop of sour cream and a handful of avocado chunks. Just to impress, I'll put a slice or two of buttered, crisped bread on the side of the bowls.
Me: So, how was your day, honey?
She: The usual and yours?
Me: I spent most of the day grocery shopping and in the kitchen.
Me: This wine is delicious! Need a refresh???
Gonna try this this week! I don't drink wine, but wish I do, but gonna try everything!
Sometimes Ya Gotta Have Pie: Cream Pie!
More Than An Italian Deli: It's Issimo!