text:
from __future__ import absolute_import

import operator
import os
import re
import shutil
import subprocess
import tempfile
import time

import h5py
import numpy as np
import PIL.Image

from .train import TrainTask
import digits
from digits import utils
from digits.config import config_value
from digits.utils import subclass, override, constants

# Must import after importing digit.config
import caffe_pb2

# NOTE: Increment this everytime the pickled object changes
PICKLE_VERSION = 1

# Constants
TORCH_MODEL_FILE = 'model.lua'
TORCH_SNAPSHOT_PREFIX = 'snapshot'

def subprocess_visible_devices(gpus):
    """
    Calculates CUDA_VISIBLE_DEVICES for a subprocess
    """
    if not isinstance(gpus, list):
        raise ValueError('gpus should be a list')
    gpus = [int(g) for g in gpus]

    old_cvd = os.environ.get('CUDA_VISIBLE_DEVICES', None)
    if old_cvd is None:
        real_gpus = gpus
    else:
        map_visible_to_real = {}
        for visible, real in enumerate(old_cvd.split(',')):
            map_visible_to_real[visible] = int(real)
        real_gpus = []
        for visible_gpu in gpus:
            real_gpus.append(map_visible_to_real[visible_gpu])
    return ','.join(str(g) for g in real_gpus)

@subclass
class TorchTrainTask(TrainTask):
    """
    Trains a torch model
    """

    TORCH_LOG = 'torch_output.log'

    def __init__(self, **kwargs):
        """
        Arguments:
        network -- a NetParameter defining the network
        """
        super(TorchTrainTask, self).__init__(**kwargs)

        # save network description to file
        with open(os.path.join(self.job_dir, TORCH_MODEL_FILE), "w") as outfile:
            outfile.write(self.network)

        self.pickver_task_torch_train = PICKLE_VERSION

        self.current_epoch = 0

        self.loaded_snapshot_file = None
        self.loaded_snapshot_epoch = None
        self.image_mean = None
        self.classifier = None
        self.solver = None

        self.model_file = TORCH_MODEL_FILE
        self.train_file = constants.TRAIN_DB
        self.val_file = constants.VAL_DB
        self.snapshot_prefix = TORCH_SNAPSHOT_PREFIX
        self.log_file = self.TORCH_LOG

        self.digits_version = digits.__version__

    def __getstate__(self):
        state = super(TorchTrainTask, self).__getstate__()

        # Don't pickle these things
        if 'labels' in state:
            del state['labels']
        if 'image_mean' in state:
            del state['image_mean']
        if 'classifier' in state:
            del state['classifier']
        if 'torch_log' in state:
            del state['torch_log']

        return state

    def __setstate__(self, state):
        super(TorchTrainTask, self).__setstate__(state)

        # Make changes to self
        self.loaded_snapshot_file = None
        self.loaded_snapshot_epoch = None

        # These things don't get pickled
        self.image_mean = None
        self.classifier = None

    # Task overrides

    @override
    def name(self):
        return 'Train Torch Model'

    @override
    def before_run(self):
        super(TorchTrainTask, self).before_run()
        self.torch_log = open(self.path(self.TORCH_LOG), 'a')
        self.saving_snapshot = False
        self.receiving_train_output = False
        self.receiving_val_output = False
        self.last_train_update = None
        self.displaying_network = False
        self.temp_unrecognized_output = []
        return True

    def create_mean_file(self):
        filename = os.path.join(self.job_dir, constants.MEAN_FILE_IMAGE)
        # don't recreate file if it already exists
        if not os.path.exists(filename):
            mean_file = self.dataset.get_mean_file()
            assert mean_file is not None and mean_file.endswith('.binaryproto'), \
                'Mean subtraction required but dataset has no mean file in .binaryproto format'
            blob = caffe_pb2.BlobProto()
            with open(self.dataset.path(mean_file), 'rb') as infile:
                blob.ParseFromString(infile.read())
            data = np.array(blob.data, dtype=np.uint8).reshape(blob.channels, blob.height, blob.width)
            if blob.channels == 3:
                # converting from BGR to RGB
                data = data[[2, 1, 0], ...]  # channel swap
                # convert to (height, width, channels)
                data = data.transpose((1, 2, 0))
            else:
                assert blob.channels == 1
                # convert to (height, width)
                data = data[0]
            # save to file
            image = PIL.Image.fromarray(data)
            image.save(filename)
        return filename

    @override
    def task_arguments(self, resources, env):
        dataset_backend = self.dataset.get_backend()
        assert dataset_backend == 'lmdb' or dataset_backend == 'hdf5'

        args = [config_value('torch')['executable'],
                os.path.join(
                    os.path.dirname(os.path.abspath(digits.__file__)),
                    'tools', 'torch', 'wrapper.lua'),
                'main.lua',
                '--network=%s' % self.model_file.split(".")[0],
                '--epoch=%d' % int(self.train_epochs),
                '--networkDirectory=%s' % self.job_dir,
                '--save=%s' % self.job_dir,
                '--snapshotPrefix=%s' % self.snapshot_prefix,
                '--snapshotInterval=%s' % self.snapshot_interval,
                '--learningRate=%s' % self.learning_rate,
                '--policy=%s' % str(self.lr_policy['policy']),
                '--dbbackend=%s' % dataset_backend
                ]

        if self.batch_size is not None:
            args.append('--batchSize=%d' % self.batch_size)

        if self.use_mean != 'none':
            filename = self.create_mean_file()
            args.append('--mean=%s' % filename)

        if hasattr(self.dataset, 'labels_file'):
            args.append('--labels=%s' % self.dataset.path(self.dataset.labels_file))

        train_feature_db_path = self.dataset.get_feature_db_path(constants.TRAIN_DB)
        train_label_db_path = self.dataset.get_label_db_path(constants.TRAIN_DB)
        val_feature_db_path = self.dataset.get_feature_db_path(constants.VAL_DB)
        val_label_db_path = self.dataset.get_label_db_path(constants.VAL_DB)

        args.append('--train=%s' % train_feature_db_path)
        if train_label_db_path:
            args.append('--train_labels=%s' % train_label_db_path)
        if val_feature_db_path:
            args.append('--validation=%s' % val_feature_db_path)
        if val_label_db_path:
            args.append('--validation_labels=%s' % val_label_db_path)

        # learning rate policy input parameters
        if self.lr_policy['policy'] == 'fixed':
            pass
        elif self.lr_policy['policy'] == 'step':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
            args.append('--stepvalues=%s' % self.lr_policy['stepsize'])
        elif self.lr_policy['policy'] == 'multistep':
            args.append('--stepvalues=%s' % self.lr_policy['stepvalue'])
            args.append('--gamma=%s' % self.lr_policy['gamma'])
        elif self.lr_policy['policy'] == 'exp':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
        elif self.lr_policy['policy'] == 'inv':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
            args.append('--power=%s' % self.lr_policy['power'])
        elif self.lr_policy['policy'] == 'poly':
            args.append('--power=%s' % self.lr_policy['power'])
        elif self.lr_policy['policy'] == 'sigmoid':
            args.append('--stepvalues=%s' % self.lr_policy['stepsize'])
            args.append('--gamma=%s' % self.lr_policy['gamma'])

        if self.shuffle:
            args.append('--shuffle=yes')

        if self.crop_size:
            args.append('--crop=yes')
            args.append('--croplen=%d' % self.crop_size)

        if self.use_mean == 'pixel':
            args.append('--subtractMean=pixel')
        elif self.use_mean == 'image':
            args.append('--subtractMean=image')
        else:
            args.append('--subtractMean=none')

        if self.random_seed is not None:
            args.append('--seed=%s' % self.random_seed)

        if self.solver_type == 'SGD':
            args.append('--optimization=sgd')
        elif self.solver_type == 'NESTEROV':
            args.append('--optimization=nag')
        elif self.solver_type == 'ADAGRAD':
            args.append('--optimization=adagrad')
        elif self.solver_type == 'RMSPROP':
            args.append('--optimization=rmsprop')
        elif self.solver_type == 'ADADELTA':
            args.append('--optimization=adadelta')
        elif self.solver_type == 'ADAM':
            args.append('--optimization=adam')
        else:
            raise ValueError('Unknown solver_type %s' % self.solver_type)

        if self.val_interval > 0:
            args.append('--interval=%s' % self.val_interval)

        if 'gpus' in resources:
            identifiers = []
            for identifier, value in resources['gpus']:
                identifiers.append(identifier)
            # make all selected GPUs visible to the Torch 'th' process.
            # don't make other GPUs visible though since Torch will load
            # CUDA libraries and allocate memory on all visible GPUs by
            # default.
            env['CUDA_VISIBLE_DEVICES'] = subprocess_visible_devices(identifiers)
            # switch to GPU mode
            args.append('--type=cuda')
        else:
            # switch to CPU mode
            args.append('--type=float')

        if self.pretrained_model:
            filenames = self.pretrained_model.split(os.path.pathsep)
            if len(filenames) > 1:
                raise ValueError('Torch does not support multiple pretrained model files')
            args.append('--weights=%s' % self.path(filenames[0]))

        # Augmentations
        assert self.data_aug['flip'] in ['none', 'fliplr', 'flipud', 'fliplrud'], 'Bad or unknown flag "flip"'
        args.append('--augFlip=%s' % self.data_aug['flip'])

        assert self.data_aug['quad_rot'] in ['none', 'rot90', 'rot180', 'rotall'], 'Bad or unknown flag "quad_rot"'
        args.append('--augQuadRot=%s' % self.data_aug['quad_rot'])

        if self.data_aug['rot']:
            args.append('--augRot=%s' % self.data_aug['rot'])

        if self.data_aug['scale']:
            args.append('--augScale=%s' % self.data_aug['scale'])

        if self.data_aug['noise']:
            args.append('--augNoise=%s' % self.data_aug['noise'])

        if self.data_aug['hsv_use']:
            args.append('--augHSVh=%s' % self.data_aug['hsv_h'])
            args.append('--augHSVs=%s' % self.data_aug['hsv_s'])
            args.append('--augHSVv=%s' % self.data_aug['hsv_v'])
        else:
            args.append('--augHSVh=0')
            args.append('--augHSVs=0')
            args.append('--augHSVv=0')

        return args

    @override
    def process_output(self, line):
        regex = re.compile('\x1b\[[0-9;]*m', re.UNICODE)  # TODO: need to include regular expression for MAC color codes
        line = regex.sub('', line).strip()
        self.torch_log.write('%s\n' % line)
        self.torch_log.flush()

        # parse torch output
        timestamp, level, message = self.preprocess_output_torch(line)

        # return false when unrecognized output is encountered
        if not level:
            # network display in progress
            if self.displaying_network:
                self.temp_unrecognized_output.append(line)
                return True
            return False

        if not message:
            return True

        # network display ends
        if self.displaying_network:
            if message.startswith('Network definition ends'):
                self.temp_unrecognized_output = []
                self.displaying_network = False
            return True

        # by default Lua prints infinite numbers as 'inf' however Torch tensor may use 'nan' to represent infinity
        float_exp = '([-]?inf|nan|[-+]?[0-9]*\.?[0-9]+(e[-+]?[0-9]+)?)'

        # loss and learning rate updates
        match = re.match(r'Training \(epoch (\d+\.?\d*)\): \w*loss\w* = %s, lr = %s' % (float_exp, float_exp), message)
        if match:
            index = float(match.group(1))
            l = match.group(2)
            assert not('inf' in l or 'nan' in l), \
                'Network reported %s for training loss. Try decreasing your learning rate.' % l
            l = float(l)
            lr = match.group(4)
            lr = float(lr)
            # epoch updates
            self.send_progress_update(index)

            self.save_train_output('loss', 'SoftmaxWithLoss', l)
            self.save_train_output('learning_rate', 'LearningRate', lr)
            self.logger.debug(message)

            return True

        # testing loss and accuracy updates
        match = re.match(r'Validation \(epoch (\d+\.?\d*)\): \w*loss\w* = %s(, accuracy = %s)?' %
                         (float_exp, float_exp), message, flags=re.IGNORECASE)
        if match:
            index = float(match.group(1))
            l = match.group(2)
            a = match.group(5)
            # note: validation loss could have diverged however
            # if the training loss is still finite, there is a slim possibility
            # that the network keeps learning something useful, so we don't treat
            # infinite validation loss as a fatal error
            if not('inf' in l or 'nan' in l):
                l = float(l)
                self.logger.debug('Network validation loss #%s: %s' % (index, l))
                # epoch updates
                self.send_progress_update(index)
                self.save_val_output('loss', 'SoftmaxWithLoss', l)
                if a and a.lower() != 'inf' and a.lower() != '-inf':
                    a = float(a)
                    self.logger.debug('Network accuracy #%s: %s' % (index, a))
                    self.save_val_output('accuracy', 'Accuracy', a)
            return True

        # snapshot saved
        if self.saving_snapshot:
            if not message.startswith('Snapshot saved'):
                self.logger.warning(
                    'Torch output format seems to have changed. '
                    'Expected "Snapshot saved..." after "Snapshotting to..."')
            else:
                self.logger.info('Snapshot saved.')  # to print file name here, you can use "message"
            self.detect_snapshots()
            self.send_snapshot_update()
            self.saving_snapshot = False
            return True

        # snapshot starting
        match = re.match(r'Snapshotting to (.*)\s*$', message)
        if match:
            self.saving_snapshot = True
            return True

        # network display starting
        if message.startswith('Network definition:'):
            self.displaying_network = True
            return True

        if level in ['error', 'critical']:
            self.logger.error('%s: %s' % (self.name(), message))
            self.exception = message
            return True

        # skip remaining info and warn messages
        return True

    @staticmethod
    def preprocess_output_torch(line):
        """
        Takes line of output and parses it according to caffe's output format
        Returns (timestamp, level, message) or (None, None, None)
        """
        # NOTE: This must change when the logging format changes
        # LMMDD HH:MM:SS.MICROS pid file:lineno] message
        match = re.match(r'(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s\[(\w+)\s*]\s+(\S.*)$', line)
        if match:
            timestamp = time.mktime(time.strptime(match.group(1), '%Y-%m-%d %H:%M:%S'))
            level = match.group(2)
            message = match.group(3)
            if level == 'INFO':
                level = 'info'
            elif level == 'WARNING':
                level = 'warning'
            elif level == 'ERROR':
                level = 'error'
            elif level == 'FAIL':  # FAIL
                level = 'critical'
            return (timestamp, level, message)
        else:
            return (None, None, None)

    def send_snapshot_update(self):
        """
        Sends socketio message about the snapshot list
        """
        # TODO: move to TrainTask
        from digits.webapp import socketio

        socketio.emit('task update',
                      {
                          'task': self.html_id(),
                          'update': 'snapshots',
                          'data': self.snapshot_list(),
                      },
                      namespace='/jobs',
                      room=self.job_id,
                      )

    # TrainTask overrides
    @override
    def after_run(self):
        if self.temp_unrecognized_output:
            if self.traceback:
                self.traceback = self.traceback + ('\n'.join(self.temp_unrecognized_output))
            else:
                self.traceback = '\n'.join(self.temp_unrecognized_output)
                self.temp_unrecognized_output = []
        self.torch_log.close()

    @override
    def after_runtime_error(self):
        if os.path.exists(self.path(self.TORCH_LOG)):
            output = subprocess.check_output(['tail', '-n40', self.path(self.TORCH_LOG)])
            lines = []
            for line in output.split('\n'):
                # parse torch header
                timestamp, level, message = self.preprocess_output_torch(line)

                if message:
                    lines.append(message)
            # return the last 20 lines
            traceback = '\n\nLast output:\n' + '\n'.join(lines[len(lines) - 20:]) if len(lines) > 0 else ''
            if self.traceback:
                self.traceback = self.traceback + traceback
            else:
                self.traceback = traceback

            if 'DIGITS_MODE_TEST' in os.environ:
                print output

    @override
    def detect_snapshots(self):
        self.snapshots = []

        snapshot_dir = os.path.join(self.job_dir, os.path.dirname(self.snapshot_prefix))
        snapshots = []

        for filename in os.listdir(snapshot_dir):
            # find models
            match = re.match(r'%s_(\d+)\.?(\d*)(_Weights|_Model)\.t7' %
                             os.path.basename(self.snapshot_prefix), filename)
            if match:
                epoch = 0
                if match.group(2) == '':
                    epoch = int(match.group(1))
                else:
                    epoch = float(match.group(1) + '.' + match.group(2))
                snapshots.append((
                    os.path.join(snapshot_dir, filename),
                    epoch
                )
                )

        self.snapshots = sorted(snapshots, key=lambda tup: tup[1])

        return len(self.snapshots) > 0

    @override
    def est_next_snapshot(self):
        # TODO: Currently this function is not in use. Probably in future we may have to implement this
        return None

    @override
    def infer_one(self,
                  data,
                  snapshot_epoch=None,
                  layers=None,
                  gpu=None,
                  resize=True):
        # resize parameter is unused
        return self.infer_one_image(data,
                                    snapshot_epoch=snapshot_epoch,
                                    layers=layers,
                                    gpu=gpu)

    def infer_one_image(self, image, snapshot_epoch=None, layers=None, gpu=None):
        """
        Classify an image
        Returns (predictions, visualizations)
            predictions -- an array of [ (label, confidence), ...] for each label, sorted by confidence
            visualizations -- an array of (layer_name, activations, weights) for the specified layers
        Returns (None, None) if something goes wrong

        Arguments:
        image -- a np.array

        Keyword arguments:
        snapshot_epoch -- which snapshot to use
        layers -- which layer activation[s] and weight[s] to visualize
        """
        temp_image_handle, temp_image_path = tempfile.mkstemp(suffix='.png')
        os.close(temp_image_handle)
        image = PIL.Image.fromarray(image)
        try:
            image.save(temp_image_path, format='png')
        except KeyError:
            error_message = 'Unable to save file to "%s"' % temp_image_path
            self.logger.error(error_message)
            raise digits.inference.errors.InferenceError(error_message)

        file_to_load = self.get_snapshot(snapshot_epoch)

        args = [config_value('torch')['executable'],
                os.path.join(
                    os.path.dirname(os.path.abspath(digits.__file__)),
                    'tools', 'torch', 'wrapper.lua'),
                'test.lua',
                '--image=%s' % temp_image_path,
                '--network=%s' % self.model_file.split(".")[0],
                '--networkDirectory=%s' % self.job_dir,
                '--snapshot=%s' % file_to_load,
                '--allPredictions=yes',
                ]
        if hasattr(self.dataset, 'labels_file'):
            args.append('--labels=%s' % self.dataset.path(self.dataset.labels_file))

        if self.use_mean != 'none':
            filename = self.create_mean_file()
            args.append('--mean=%s' % filename)

        if self.use_mean == 'pixel':
            args.append('--subtractMean=pixel')
        elif self.use_mean == 'image':
            args.append('--subtractMean=image')
        else:
            args.append('--subtractMean=none')

        if self.crop_size:
            args.append('--crop=yes')
            args.append('--croplen=%d' % self.crop_size)

        if layers == 'all':
            args.append('--visualization=yes')
            args.append('--save=%s' % self.job_dir)

        # Convert them all to strings
        args = [str(x) for x in args]

        regex = re.compile('\x1b\[[0-9;]*m', re.UNICODE)  # TODO: need to include regular expression for MAC color codes
        self.logger.info('%s classify one task started.' % self.get_framework_id())

        unrecognized_output = []
        predictions = []
        self.visualization_file = None

        env = os.environ.copy()

        if gpu is not None:
            args.append('--type=cuda')
            # make only the selected GPU visible
            env['CUDA_VISIBLE_DEVICES'] = subprocess_visible_devices([gpu])
        else:
            args.append('--type=float')

        p = subprocess.Popen(args,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT,
                             cwd=self.job_dir,
                             close_fds=True,
                             env=env,
                             )

        try:
            while p.poll() is None:
                for line in utils.nonblocking_readlines(p.stdout):
                    if self.aborted.is_set():
                        p.terminate()
                        raise digits.inference.errors.InferenceError(
                            '%s classify one task got aborted. error code - %d'
                            % (self.get_framework_id(), p.returncode))

                    if line is not None:
                        # Remove color codes and whitespace
                        line = regex.sub('', line).strip()
                    if line:
                        if not self.process_test_output(line, predictions, 'one'):
                            self.logger.warning('%s classify one task unrecognized input: %s' %
                                                (self.get_framework_id(), line.strip()))
                            unrecognized_output.append(line)
                    else:
                        time.sleep(0.05)

        except Exception as e:
            if p.poll() is None:
                p.terminate()
            error_message = ''
            if type(e) == digits.inference.errors.InferenceError:
                error_message = e.__str__()
            else:
                error_message = '%s classify one task failed with error code %d \n %s' % (
                    self.get_framework_id(), p.returncode, str(e))
            self.logger.error(error_message)
            if unrecognized_output:
                unrecognized_output = '\n'.join(unrecognized_output)
                error_message = error_message + unrecognized_output
            raise digits.inference.errors.InferenceError(error_message)

        finally:
            self.after_test_run(temp_image_path)

        if p.returncode != 0:
            error_message = '%s classify one task failed with error code %d' % (self.get_framework_id(), p.returncode)
            self.logger.error(error_message)
            if unrecognized_output:
                unrecognized_output = '\n'.join(unrecognized_output)
                error_message = error_message + unrecognized_output
            raise digits.inference.errors.InferenceError(error_message)
        else:
            self.logger.info('%s classify one task completed.' % self.get_framework_id())

        predictions = {'output': np.array(predictions)}

        visualizations = []

        if layers == 'all' and self.visualization_file:
            vis_db = h5py.File(self.visualization_file, 'r')
            # the HDF5 database is organized as follows:
            # <root>
            # |- layers
            #    |- 1
            #    |  |- name
            #    |  |- activations
            #    |  |- weights
            #    |- 2
            for layer_id, layer in vis_db['layers'].items():
                layer_desc = layer['name'][...].tostring()
                if 'Sequential' in layer_desc or 'Parallel' in layer_desc:
                    # ignore containers
                    continue
                idx = int(layer_id)
                # activations
                if 'activations' in layer:
                    data = np.array(layer['activations'][...])
                    # skip batch dimension
                    if len(data.shape) > 1 and data.shape[0] == 1:
                        data = data[0]
                    vis = utils.image.get_layer_vis_square(data)
                    mean, std, hist = self.get_layer_statistics(data)
                    visualizations.append(
                        {
                            'id':         idx,
                            'name':       layer_desc,
                            'vis_type':   'Activations',
                            'vis': vis,
                            'data_stats': {
                                'shape':      data.shape,
                                'mean':       mean,
                                'stddev':     std,
                                'histogram':  hist,
                            }
                        }
                    )
                # weights
                if 'weights' in layer:
                    data = np.array(layer['weights'][...])
                    if 'Linear' not in layer_desc:
                        vis = utils.image.get_layer_vis_square(data)
                    else:
                        # Linear (inner product) layers have too many weights
                        # to display
                        vis = None
                    mean, std, hist = self.get_layer_statistics(data)
                    parameter_count = reduce(operator.mul, data.shape, 1)
                    if 'bias' in layer:
                        bias = np.array(layer['bias'][...])
                        parameter_count += reduce(operator.mul, bias.shape, 1)
                    visualizations.append(
                        {
                            'id':          idx,
                            'name':        layer_desc,
                            'vis_type':    'Weights',
                            'vis':  vis,
                            'param_count': parameter_count,
                            'data_stats': {
                                'shape':      data.shape,
                                'mean':       mean,
                                'stddev':     std,
                                'histogram':  hist,
                            }
                        }
                    )
            # sort by layer ID
            visualizations = sorted(visualizations, key=lambda x: x['id'])
        return (predictions, visualizations)

    def get_layer_statistics(self, data):
        """
        Returns statistics for the given layer data:
            (mean, standard deviation, histogram)
                histogram -- [y, x, ticks]

        Arguments:
        data -- a np.ndarray
        """
        # XXX These calculations can be super slow
        mean = np.mean(data)
        std = np.std(data)
        y, x = np.histogram(data, bins=20)
        y = list(y)
        ticks = x[[0, len(x) / 2, -1]]
        x = [(x[i] + x[i + 1]) / 2.0 for i in xrange(len(x) - 1)]
        ticks = list(ticks)
        return (mean, std, [y, x, ticks])

    def after_test_run(self, temp_image_path):
        try:
            os.remove(temp_image_path)
        except OSError:
            pass

    def process_test_output(self, line, predictions, test_category):
        # parse torch output
        timestamp, level, message = self.preprocess_output_torch(line)

        # return false when unrecognized output is encountered
        if not (level or message):
            return False

        if not message:
            return True

        float_exp = '([-]?inf|nan|[-+]?[0-9]*\.?[0-9]+(e[-+]?[0-9]+)?)'

        # format of output while testing single image
        match = re.match(r'For image \d+, predicted class \d+: \d+ \((.*?)\) %s' % (float_exp), message)
        if match:
            label = match.group(1)
            confidence = match.group(2)
            assert not('inf' in confidence or 'nan' in confidence), \
                'Network reported %s for confidence value. Please check image and network' % label
            confidence = float(confidence)
            predictions.append((label, confidence))
            return True

        # format of output while testing multiple images
        match = re.match(r'Predictions for image \d+: (.*)', message)
        if match:
            values = match.group(1).strip()
            # 'values' should contain a JSON representation of
            # the prediction
            predictions.append(eval(values))
            return True

        # path to visualization file
        match = re.match(r'Saving visualization to (.*)', message)
        if match:
            self.visualization_file = match.group(1).strip()
            return True

        # displaying info and warn messages as we aren't maintaining separate log file for model testing
        if level == 'info':
            self.logger.debug('%s classify %s task : %s' % (self.get_framework_id(), test_category, message))
            return True
        if level == 'warning':
            self.logger.warning('%s classify %s task : %s' % (self.get_framework_id(), test_category, message))
            return True

        if level in ['error', 'critical']:
            raise digits.inference.errors.InferenceError(
                '%s classify %s task failed with error message - %s'
                % (self.get_framework_id(), test_category, message))

        return True           # control never reach this line. It can be removed.

    @override
    def infer_many(self, data, snapshot_epoch=None, gpu=None, resize=True):
        # resize parameter is unused
        return self.infer_many_images(data, snapshot_epoch=snapshot_epoch, gpu=gpu)

    def infer_many_images(self, images, snapshot_epoch=None, gpu=None):
        """
        Returns (labels, results):
        labels -- an array of strings
        results -- a 2D np array:
            [
                [image0_label0_confidence, image0_label1_confidence, ...],
                [image1_label0_confidence, image1_label1_confidence, ...],
                ...
            ]

        Arguments:
        images -- a list of np.arrays

        Keyword arguments:
        snapshot_epoch -- which snapshot to use
        """

        # create a temporary folder to store images and a temporary file
        # to store a list of paths to the images
        temp_dir_path = tempfile.mkdtemp()
        try:  # this try...finally clause is used to clean up the temp directory in any case
            temp_imglist_handle, temp_imglist_path = tempfile.mkstemp(dir=temp_dir_path, suffix='.txt')
            for image in images:
                temp_image_handle, temp_image_path = tempfile.mkstemp(
                    dir=temp_dir_path, suffix='.png')
                image = PIL.Image.fromarray(image)
                try:
                    image.save(temp_image_path, format='png')
                except KeyError:
                    error_message = 'Unable to save file to "%s"' % temp_image_path
                    self.logger.error(error_message)
                    raise digits.inference.errors.InferenceError(error_message)
                os.write(temp_imglist_handle, "%s\n" % temp_image_path)
                os.close(temp_image_handle)
            os.close(temp_imglist_handle)

            file_to_load = self.get_snapshot(snapshot_epoch)

            args = [config_value('torch')['executable'],
                    os.path.join(
                        os.path.dirname(os.path.abspath(digits.__file__)),
                        'tools', 'torch', 'wrapper.lua'),
                    'test.lua',
                    '--testMany=yes',
                    '--allPredictions=yes',  # all predictions are grabbed and formatted as required by DIGITS
                    '--image=%s' % str(temp_imglist_path),
                    '--network=%s' % self.model_file.split(".")[0],
                    '--networkDirectory=%s' % self.job_dir,
                    '--snapshot=%s' % file_to_load,
                    ]

            if hasattr(self.dataset, 'labels_file'):
                args.append('--labels=%s' % self.dataset.path(self.dataset.labels_file))

            if self.use_mean != 'none':
                filename = self.create_mean_file()
                args.append('--mean=%s' % filename)

            if self.use_mean == 'pixel':
                args.append('--subtractMean=pixel')
            elif self.use_mean == 'image':
                args.append('--subtractMean=image')
            else:
                args.append('--subtractMean=none')
            if self.crop_size:
                args.append('--crop=yes')
                args.append('--croplen=%d' % self.crop_size)

            # Convert them all to strings
            args = [str(x) for x in args]

            # TODO: need to include regular expression for MAC color codes
            regex = re.compile('\x1b\[[0-9;]*m', re.UNICODE)
            self.logger.info('%s classify many task started.' % self.name())

            env = os.environ.copy()
            if gpu is not None:
                args.append('--type=cuda')
                # make only the selected GPU visible
                env['CUDA_VISIBLE_DEVICES'] = subprocess_visible_devices([gpu])
            else:
                args.append('--type=float')

            unrecognized_output = []
            predictions = []
            p = subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT,
                                 cwd=self.job_dir,
                                 close_fds=True,
                                 env=env
                                 )

            try:
                while p.poll() is None:
                    for line in utils.nonblocking_readlines(p.stdout):
                        if self.aborted.is_set():
                            p.terminate()
                            raise digits.inference.errors.InferenceError(
                                '%s classify many task got aborted. error code - %d'
                                % (self.get_framework_id(), p.returncode))

                        if line is not None:
                            # Remove whitespace and color codes.
                            # Color codes are appended to beginning and end of line by torch binary
                            # i.e., 'th'. Check the below link for more information
                            # https://groups.google.com/forum/#!searchin/torch7/color$20codes/torch7/8O_0lSgSzuA/Ih6wYg9fgcwJ  # noqa
                            line = regex.sub('', line).strip()
                        if line:
                            if not self.process_test_output(line, predictions, 'many'):
                                self.logger.warning('%s classify many task unrecognized input: %s' %
                                                    (self.get_framework_id(), line.strip()))
                                unrecognized_output.append(line)
                        else:
                            time.sleep(0.05)
            except Exception as e:
                if p.poll() is None:
                    p.terminate()
                error_message = ''
                if type(e) == digits.inference.errors.InferenceError:
                    error_message = e.__str__()
                else:
                    error_message = '%s classify many task failed with error code %d \n %s' % (
                        self.get_framework_id(), p.returncode, str(e))
                self.logger.error(error_message)
                if unrecognized_output:
                    unrecognized_output = '\n'.join(unrecognized_output)
                    error_message = error_message + unrecognized_output
                raise digits.inference.errors.InferenceError(error_message)

            if p.returncode != 0:
                error_message = '%s classify many task failed with error code %d' % (
                    self.get_framework_id(), p.returncode)
                self.logger.error(error_message)
                if unrecognized_output:
                    unrecognized_output = '\n'.join(unrecognized_output)
                    error_message = error_message + unrecognized_output
                raise digits.inference.errors.InferenceError(error_message)
            else:
                self.logger.info('%s classify many task completed.' % self.get_framework_id())
        finally:
            shutil.rmtree(temp_dir_path)

        # task.infer_one() expects dictionary in return value
        return {'output': np.array(predictions)}

    def has_model(self):
        """
        Returns True if there is a model that can be used
        """
        return len(self.snapshots) != 0

    @override
    def get_model_files(self):
        """
        return paths to model files
        """
        return {
            "Network": self.model_file
        }

    @override
    def get_network_desc(self):
        """
        return text description of network
        """
        with open(os.path.join(self.job_dir, TORCH_MODEL_FILE), "r") as infile:
            desc = infile.read()
        return desc

    @override
    def get_task_stats(self, epoch=-1):
        """
        return a dictionary of task statistics
        """

        loc, mean_file = os.path.split(self.dataset.get_mean_file())

        stats = {
            "image dimensions": self.dataset.get_feature_dims(),
            "mean file": mean_file,
            "snapshot file": self.get_snapshot_filename(epoch),
            "model file": self.model_file,
            "framework": "torch"
        }

        if hasattr(self, "digits_version"):
            stats.update({"digits version": self.digits_version})

        if hasattr(self.dataset, "resize_mode"):
            stats.update({"image resize mode": self.dataset.resize_mode})

        if hasattr(self.dataset, "labels_file"):
            stats.update({"labels file": self.dataset.labels_file})

        return stats


text:
Q: how could i let user change wall texture image change in 3d mobile app I am very new to unity. I was creating 3d portal mobile app, and was wondering is it possible to let users change the wall texture image. I was thinking if I could change the wall texture image as we could switch items for game characters. If it is possible, could describe how could it be implemented?
Again, I am very new to unity, so appreciate your help.

redpajama_set_name: RedPajamaStackExchange


text:
December 5, 2012 ACFAS.org | FootHealthFacts.org | JFAS | Contact Us
Save on Registration for ACFAS 2013
Take advantage of the "Early Bird" rate and register now. You have less than two weeks until December 17 -- when the rate expires. By registering early, you'll have some extra change in your pocket in February for the Annual Scientific Conference in Las Vegas! Visit acfas.org/vegas to register today or for more information.
2013 Arthroscopic Surgical Skills Course Dates Set
The always popular and increasingly insightful arthroscopy courses have been scheduled for 2013! These interactive, two-day, hands-on courses led by skilled ACFAS arthroscopy surgeons will take place at the state-of-the-art Orthopaedic Learning Center in Rosemont, IL on the following dates in 2013:
March 2-3
December 14-15
Keep watching This Week @ACFAS and acfas.org for further information and to find out when you can register!
Start off the New Year with Patient Education CDs
The new year brings resolutions for patients to finally fix that bunion, hammertoe, heel pain, etc. Give your patients the information they need to proceed with treating the foot and ankle issues they may face by purchasing the Patient Education CD Series and the Perioperative CD Series. Your practice will get the latest in patient-centered, all-inclusive information compiled for ACFAS members' use in the office.
Each CD set includes printable handouts that you can provide to your patients before and after surgery to ease their worries. If your patient is non-surgical, there's information for him or her as well! Also, each printout is fully customizable to suit the marketing needs of your practice, and it's backed with the ACFAS logo, so your patients can rest assured that they are being treated by a quality foot and ankle surgeon.
Visit the acfas.org/marketing to check out all the topics the CDs have to offer or to order your series today.
Professional Liability Chiropractor Had Duty to Warn Of Stroke Risks, Texas Supreme Court Rules
Common law duty requires that chiropractors disclose inherent risks to their patients, the Texas Supreme Court has ruled in Felton v. Lovett. A reasonable healthcare provider must disclose the risks that would influence a reasonable patient in deciding whether to undergo treatment but not those that would be unduly disturbing to an unreasonable patient," the court said, reversing an intermediate appellate court ruling that reversed a jury verdict for a chiropractor's patient.
BNA Health Care Policy Report (12/04/12)
Share | Web Link - Publication Homepage: Link to Full Text Unavailable
West Virginia High Court Says Fired Doctor Not Entitled to Accrued Unused Vacation Pay
A doctor fired from a medical group for leaving signed, blank prescription forms with his assistant when he went on vacation was not entitled to reimbursement for accrued unused vacation under either his employment contract or an employee handbook, a state high court has ruled in Henick v. Fast-Track Anesthesia Associates of West Virginia. The key takeaway from the decision is that where an individual employment contract was silent as to doctor's right to reimbursement for accrued, unused vacation, the terms of employee handbook, which allowed reimbursement only to employees who resigned with notice, applied.
BNA Health Care Policy Report (12/04/12) Pazanowski, Mary Anne
The Influence of Procedure Delay on Resource Utilization: A National Study of Patients with Open Tibial Fracture
A study was conducted to understand national variation in delay of emergency procedures in patients with open tibial fracture at the hospital level, as well as compare length of stay (LOS) and cost in patients cared for at the best and worst performing hospitals for delay. The 2003-2009 Nationwide Inpatient Sample was retroactively analyzed, with adult patients with primary diagnosis of open tibial fracture chosen for inclusion. The final sample encompassed 7,029 patients from 332 hospitals, and adjusted analyses showed that patients treated at hospitals in the fourth or worst quartile for delay were calculated to have 12 percent higher cost versus patients treated at hospitals in the first quartile. Furthermore, LOS of patients treated at hospitals in the fourth quartile was estimated to be 11 percent longer compared to patients treated at hospitals in the first quartile.
Plastic and Reconstructive Surgery (11/08/12) Sears, Erika Davis; Burke, James F.; Davis, Matthew M.; et al.
Treatment of the Stress Positive Ligamentous SE4 Ankle Fracture: Incidence of Syndesmotic Injury and Clinical Decision Making
A study was held to review the researchers' experience with the treatment of stress positive (+) supination and external pattern injuries using shared decision-making with patients. The study involved treatment of 114 patients with stress (+) supination and external rotation type fibula fractures over a period of nine years. X-rays were reviewed, and the medial clear space (MCS) quantified on the presentation, stress and final united radiographs. The option for surgical or nonsurgical treatment was made by the patient and surgeon following discussion of both approaches' risks and benefits. Medial widening and talar subluxation on abduction/external rotation stress after fibular fixation were used to diagnose syndesmotic instability for the operative cases. Fifty-four of the 114 cases were treated in a cast, while 60 were treated operatively. Twenty-seven of the operative cases showed syndesmotic instability on radiographic examination. The MCS on stress examination was statistically different, with more widening observed for operatively treated patients. No subluxation was detected on weight bearing x-rays for any healing patients.
Journal of Orthopaedic Trauma (11/12) Vol. 26, No. 11, P. 659 Tornetta III, Paul; Axelrad, Thomas W.; Sibai, Tarek A.; et al.
The Talar Axis–First Metatarsal Base Angle in CVT Treatment: A Comparison of Idiopathic and Non-Idiopathic Cases Treated with the Dobbs Method
Congenital vertical talus (CVT) is a deformity that can be either idiopathic or non-idiopathic. Researchers analyzed the talar axis–first metatarsal base angle (TAMBA) values of idiopathic and non-idiopathic CVT cases that had been treated with the Dobbs method. The investigators compared TAMBA measurements of CVT successfully treated with the Dobbs method to TAMBA values of CVT unsuccessfully treated with a minimally invasive approach. Of 20 CVT, 14 were successfully treated with the Dobbs method. Five of those 14 feet were non-idiopathic and nine were idiopathic. The feet that did not have complete correction after the Dobbs protocol were associated with arthrogryposis or caudal regression syndrome. Results indicated that the success of the Dobbs method in treating CVT depends on the flexibility in the talonavicular complex. The TAMBA value and the TAMBA neutral minus TAMBA plantarflexion both express the flexibility in the talonavicular joint and may predict the success of a minimally invasive treatment. For the few cases in which the success of the Dobbs method is limited, the feet are associated with a TAMBA greater than 120 degrees in neutral position and a TAMBA difference smaller than 25 degrees.
Journal of Children's Orthopaedics (11/10/12) Eberhardt, Oliver; Fernandez, Francisco; Wirth, Thomas
End-of-Year Tax Tips
Physicians could reap significant cost savings in 2013 by following a number of strategies when they file their 2012 tax returns. These tips could be particularly beneficial in the event Congress fails to take action to block several impending tax hikes. A new law slated to go into effect next year stipulates that married physicians who file their tax return jointly will pay an extra 0.9 percent if their wages, self-employment income or other compensation tops $250,000, on top of the regular 1.45 percent Medicare tax. The payroll tax limit for single filers is $200,000. It thus pays for physicians to put more money into their retirement fund.
Meanwhile, physicians could have to pay an additional 3.8 percent Medicare surtax next year if their modified adjusted gross income surpasses $200,000 for individuals and $250,000 for couples. Those who expect considerable taxable gains next year should boost their 2013 contributions to qualified tax-deferred retirement plans, such as a 401(k) or SEP IRA, to reduce their adjusted gross income and help minimize or avoid the surtax.
The expiration of the Bush-era tax cuts at the end of year means that tax rates on earned income will jump at least three percentage points, and as much as 4.6 for those in the highest income bracket. It might therefore be sensible to take certain taxable payments this year rather than waiting until next year, such as bonuses, honorariums for sitting on advisory boards or income from the goodwill value of one's practice or cashing in stock options.
Making business-related equipment investments also can be advantageous. A physician can write off the full amount of any 2012 purchases up to $139,000, which can cut his or her 2012 tax bill significantly. The IRS' definition of "equipment" applies to commercially sold computer software, which may encourage physicians to add an electronic medical records system or upgrade an existing one. Furthermore, these tax breaks are added to any applicable government-funded incentives.
Medscape (11/27/12) Murray, Dennis G.
Three-Point Plan Protects Medical Practice Technology in Disasters
The American Medical Association and other groups have devised guidance for medical practices developing disaster preparedness and response plans. No matter what plan practices develop, they should retain three core elements: security of the practice's data, a contingency plan for creating records after a disaster strikes and identification of possible backup power and Internet sources. The first component ensures that patient records and other data is backed up at an off-site location so it can be retrieved once the practice resumes online operations following a disaster. It is recommended that practices with locally hosted electronic health record systems have an off-site data backup plan. The optimal solution is a cloud-based vendor that eases the copying of patient data to the cloud's off-site servers. The best location to store the backup data is a site far from the practice so as to avoid the wipeout of both the practice and the data center by the same disaster.
The second guidance point is to establish a contingency plan for every possible disaster category the practice may face. A phone tree should be created with not only with each staff member's number, but also with a list of their service providers. The contingency plan's next step is detailing how the practice will temporarily switch back to paper records and how records will be transferred when patients are referred to different care facilities.
The third guidance point is to find and secure possible backup power and Internet sources. Preparations can include prior acquisition of a backup generator that can be hooked up to natural gas lines. There also are last-minute precautions to take if the practice has the luxury of time and fair warning, such as removing all electronic equipment from the floor in the event of flooding, while one final data backup should be performed before the last person departs the office. If time is short, the practice can save several years' worth of data if staff unplug the servers and take them with them.
American Medical News (11/26/12) Dolan, Pamela Lewis
CMS Names First Medicare Data-Sharing Participants
The Centers for Medicare & Medicaid Services (CMS) has chosen the first three participants in its Medicare data sharing for performance measurement program, which focuses on increasing consumer access to healthcare quality and cost information. The three groups are the Health Improvement Collaborative of Greater Cincinnati, the Kansas City Quality Improvement Consortium and the Oregon Health Care Quality Corporation. The data sharing program, established under the healthcare reform law, provides Medicare claims data to certified groups that can then use it to help create reports on provider performance.
Court Orders Look at Healthcare Challenge
The U.S. Supreme Court has ordered the U.S. Court of Appeals for the Fourth Circuit to reconsider Lynchburg, VA-based Liberty University's challenge to the federal healthcare law in light of the high court's decision to uphold the law. The university says the law violates its religious freedoms, and it is specifically challenging provisions that require most people to carry health insurance or pay a penalty and require many employers to provide health coverage to workers. Experts say the appeals court will decide on issues it chose not to rule on previously and address issues not addressed by the high court.
Associated Press (11/27/12) Sherman, Mark
Medicare Payment Shift Didn't Curb Outlays: Study
A newly issued study published online by the Archives of Internal Medicine shows that Medicare spent more on primary care and specialty physicians in the year following a 2010 policy change that discontinued more expensive consultation payments, but hiked pay for office visits. The higher rate of office visit pay accounted for roughly 66 percent of the approximately 6.5 percent increase in spending that year after the policy change, while an increase in the reported complexity of patients constituted the remainder of the growth. The study examined data for 2.2 million individuals with Medicare supplemental insurance from a large employer between 2007 and 2010. Only persons with diabetes or heart disease diagnoses or prescriptions were included. Fifty-eight percent of the spending expansion was received by primary care physicians, while specialists received the remaining 42 percent. Although the researchers say the study outcome suggests that the policy's budget neutrality goal was not realized in the first year, "it did appear to narrow the gap in Medicare payments for office encounters between" primary care physicians and specialists. The study found no change in the volume of patient visits and concluded that "any pressure to increase volume may have been directed to other, perhaps more profitable, services."
Modern Healthcare (11/26/12) Evans, Melanie
Physician Pay Doesn't Keep Pace: Study
A study tracking physician income growth over a 25-year period found that physician pay has failed to keep pace with that of other health professionals. The results of the report, published in the Journal of the American Medical Association, indicated that adjusted physician earnings rose just 9.6 percent between 1987-1990 and 2006-2010, versus 44 percent for pharmacists. Furthermore, from 1996-2000 and 2006-2010, physician earnings shrank 1.6 percent, while pharmacist earnings increased 34.4 percent. In the period of 1987-1990 physicians earned $143,963 on average, compared to $157,751 during 2006-2010. Possible factors underlying the growth rate disparity include the expansion of managed care, Medicaid payment reductions, "sluggish" Medicare reimbursement increases and bargaining by insurance firms. Still, the study observed that physician earnings continue to top those of other professions.
Modern Physician (11/28/12) Kutscher, Beth
K-Citrate Helps Maintain Bones in Older Adults
A study by researchers at the University of Basel in Switzerland has found that potassium citrate can help increase areal and volumetric bone mineral density (BMD) in elderly men and women who do not have osteoporosis. The study, published in the Journal of Clinical Endocrinology and Metabolism, examined 201 non-osteoporotic men and women who were given 60 mEq of potassium citrate or a placebo each day, in addition to calcium and vitamin D. Patients who were given potassium citrate experienced an average 1.7 percent increase in BMD at the lumbar spine after two years, as well as a 1.3 percent and a 2 percent increase in trabecular density in the non-dominant tibia and radius, respectively. Researchers said that the findings are sufficient evidence that potassium citrate can help strengthen bones when given as a nutritional supplement.
Reuters Health Medical News (11/27/12) Harding, Anne
Medicare is Faulted on Shift to Electronic Records
A new report from the Office of Inspector General for the Department of Health and Human Services (HHS) concluded that the conversion to electronic medical records is susceptible to fraud and abuse because of Medicare officials' failure to develop adequate protections to ensure the accuracy of the information being provided by hospitals and physicians about their electronic records systems. The investigators determined that Medicare "faces obstacles" in administrating the electronic records incentive program "that leave the program vulnerable to paying incentives to professionals and hospitals that do not fully meet the meaningful use requirements." Medicare anticipates spending some $7 billion over five years to induce physicians and hospitals to adopt electronic records.
New York Times (11/29/12) Abelson, Reed
Patients' E-Records Access Tied with Increased Healthcare Use: Study
Patient use of web-based electronic health record system portals is linked to increased use of clinical services, including higher rates of office visits and telephone calls to providers, according to a study published in the Nov. 21 issue of the Journal of the American Medical Association. The study looked at healthcare services by nearly 89,000 patients enrolled for at least 24 months with the integrated delivery network from March 2005 through June 2010. These patients were divided into two equal groups: those who were users of the organization's My Health Management patient online access system and those who were not. Researchers found "a significant increase in the per-member rates of office visits (0.7 per member per year) and telephone encounters (0.3 per member per year) for portal users compared with non-users.
Modern Healthcare (11/20/12) Conn, Joseph

redpajama_set_name: RedPajamaCommonCrawl


text:
Fred Hembeck
All Series1-23 of 23
Amazing Spider-Man Family (2008-2009)
We all know Spider-Man's origin - but what happened the day after Uncle Ben died? Find out in Spider-Man: 48 Hours! Also, see the life of MayDay before she became Spider-Girl with Mr. and Mrs. Spider-Man! Also, check out Aunt May, Agent of F.E.A.S.T. and a flashback to the birth of Spidey's nemesis, VENOM!
Born into affluence, Bruce Wayne was fundamentally changed the night his parents were murdered before his eyes. From that day on, Bruce trained his mind and body beyond peak human perfection to become Batman--a symbol of terror, striking at the hearts of criminals and villains across the globe.
The Black Suit of Death
When Doctor Seitsan presents the Black Suit of Death (B.S.D.), a killing machine, as a solution to control the rampaging overpopulation on the planet Utopia IX, he is declared a traitor... ... Here the true Epic Legend of the Grim Reaper can finally be told! Follow the destructive path of the Reaper of Souls throughout the history of Earth to the modern day Pilot of The Black Suit of Death!
Detective Comics (1937-2011)
Bruce Wayne has trained his body beyond the peak human perfection; he's trained his mind to focus on minute details to deter criminal enterprises. As the Batman, he's a symbol of terror, striking at the hearts of criminals and villains across the globe.
Fantastic Four (2018-)
Collects Fantastic Four (2018) #1-4. The wait is over! The Thing, the Human Torch, the Invisible Woman and Mister Fantastic — the first four heroes of the Marvel Age of Comics — are about to be reunited! Experience the grand return of the greatest family in the Marvel Universe! As an event occurs that will radically alter the Fantastic Four, Reed and Sue Richards return home with their chil
The Flash (1959-1985)
The Flash of the Silver Age races onto the scene! After being doused in chemicals and struck by a bolt of lightning, police scientist Barry Allen became the Flash, the Fastest Man Alive! As the defender of Central City, the Flash battles against his colorful Rogues Gallery, including Captain Cold, Mirror Master and more!
This May, everyone's favorite lasagna-scarfing cat opens the fridge to an all-new ongoing comic book series! Join Garfield as he begins his monthly exploits with Jon, Odie, and the rest of the gang in the latest all-ages must-read from KaBOOM! The Garfield Show writer and comics luminary Mark Evanier teams up with beloved Garfield strip cartoonist Gary Barker to bring you all the laughs (and lasag
The Horror Lovers
Horror meets Humor in THE HORROR LOVERS, a slapstick murder mystery set against the backdrop of glorious B-movie schlockery written by Valerie D'Orazio (PunisherMAX, X-Men, Hellraiser) and illustrated by Harvey-nominated artist Bobby Timony (The Night Owls, Goblin Hood, Detectobot).
House of Hem (2015)
For over thirty years, cartoonist Fred Hembeck has been poking fun at Marvel's mightiest heroes. Now, some of his greatest works are collected in a giant-sized one-shot that's bursting with belly laughs! Fred relentlessly roasts the Fantastic Four with the help of an all-star cast of artists! Fred wipes out the Marvel Universe in the tale they said couldn't be published (and almost wasn't)! Even S
Mars Attacks
The invasion begins! The first stories of an all-new MARS ATTACKS universe are here, bringing outrageous action and dark humor to the comics page. Eisner-winning writer John Layman (Chew) is joined by Eisner-winning artist John McCrea (Hitman) to sound the alarm. Beware! The Martians are coming!
Marvel Holiday Specials
Santa's carryin' a swingin' bag of sweet surprises this Christmas as the MARVEL HOLIDAY SPECTACULAR comes your way with a giant-size extravaganza of Marvel fun! Besides an exclusive interview with St. Nick himself, we'll be compiling the ultimate Christmas gift-giving guide for Marvel fans. (Because Santa can't put everything under the tree!) Plus, we'll have a bevy of classic Christmas-themed com
The Marvel Universe According To Hembeck
Collects material from Peter Parker, the Spectacular Spider-Man #86; Amazing Spider-Man Digital #11, 16; Marvel Tales (1964) #216-217, 224-226, 235, 248, 250-252; Petey #1; Fantastic Four Roast; Fred Hembeck Destroys the Marvel Universe; Fred Hembeck Sells the Marvel Universe; Amazing Spider-Man Annual #23; Spectacular Spider-Man Annual #9, 11; Web of Spider-Man Annual #5; Untold Tales of Spider-M
Peter Parker (2010)
Collects Peter Parker (2009) #1-5. With public opinion dropping day by day, Mayor Jameson tries to boost his image, sending the aptly named Anti-Spider-Squad on 24 Hour duty and scheduling appearances with major celebrities. But will his plans be derailed by the color-bending SPECTRUM? And also...Who are the SPIDER-GIRLS? And how will they turn Peter Parker's life upside down? The webs are
Peter Parker, The Spectacular Spider-Man (1976-1998)
Peter Parker and his clone Ben Reilly join forces in an effort to defeat the Traveler!
Peter Porker, The Spectacular Spider-Ham (1985-1987)
Spider-Ham visits the mysterious island of Ducktor Doom. But why has the Fantastic Fur driven him off to his own island?
So Buttons
So Buttons is an auto-biographical comic series written by Jonathan Baylis. In the tradition of Harvey Pekar's American Splendor, Baylis matches his stories with groundbreaking artists to capture his always appealing down to earth stories that are slices of everyday life.
Spider-Man Family (2005)
Of all Spider-Man's many foes, the Jackal and the Hobgoblin are two of the most tenacious. Both master manipulators, they've caused Spidey pain aplenty in the past -- and now their shadows are again looming large! As a great evil emerges, peel back the layers of time and learn where it all began as we present the Jackal and Hobgoblin's classic first appearances, fully remastered with modern colori
Stan Lee Meets... (2006)
Stan makes the mistake of bicycling past Yancy Street, as drawn by Lee Weeks! Then, Roy Thomas and Scott Kolins depict an untold incident set during Stan's years in the service, guest starring some of the wildest characters of comics' golden age!
Superboy (1949-1979)
The classic, Silver Age adventures of the Man of Steel...back when he was merely the Boy of Steel! As Superboy, the young Clark Kent protects his hometown of Smallville from threats large, small and downright bizarre--all while trying to keep his secret identity hidden from his boyhood crush Lana Lang! These stories continue in: Superboy and the Legion of Super-Heroes!
Untold Tales of Spider-Man (1995-1997)
It's an intricate web of "lost" stories from Peter Parker's earliest days as the Amazing Spider-Man! Swing along with Spidey during a series of untold gems in which he encounters the likes of the Human Torch, Dr. Octopus, the Vulture, Sandman and more classic characters - along with some new ones like Batwing and Bluebird - on his way to becoming Marvel's premiere super hero!
Vision and the Scarlet Witch (1985-1986)
He's a synthetic man! She's a mutant sorceress! Once they were outcasts, but now they have each other, and a love which can withstand every danger they face! Steve Englehart and Richard Howell present…Vision and the Scarlet Witch!
What If? (1977-1984)
Marvel asks the age old questions - WHAT IF? See alternate endings and changed universes of your favorite Marvel stories and characters.
Collects What If? Annihilation, Civil War, Planet Hulk, X-Men: Rise and Fall of the Shiar Empire And Spider-Man Vs. Wolverine. Marvel once again poses the question, "What If...?" What if Annihilus had not been defeated in the outskirts of our galaxy, and instead had brought his devastating alien armada to Earth? What if Iron Man had lost the Civil War? What If Captain America led all the heroes


text:
Super Tic Tac Toe is an Interesting Twist to a Classic Game
March 11, 2018 September 28, 2012 by outside contributor
Hey there. Who doesn't know the game Tic Tac Toe? It's a game that anyone can pick up and play. As a kid, I would grab a sheet a paper, grab a pencil, and draw many Tic Tac Toe grids on it and play with my brother. The majority of the games were draws but every once in a while, one of us would actually win a game. It really is such a basic game that after awhile you can easily become bored with it. How can you continue to make Tic Tac Toe interesting? Our good friends at Canny Group came up with an Android mobile game that adds a strategic twist to the classic game of Tic Tac Toe. They gave us, Super Tic Tac Toe.
The rules of Super Tic Tac Toe are simple, yet strategy based. Instead of a single grid for a single game of Tic Tac Toe, you are presented with a 3 by 3 grid of 9 Tic Tac Toe grids. Winning a game of Tic Tac Toe in any of the 9 grids will award you that "square." In order to win in Super Tic Tac Toe, you need to win 3 squares that form a line (3 horizontal, vertical, or diagonal). Sounds simple enough, right? Now here is where the strategic twist comes into play. Depending on where your opponent played their X or O, that spot will correspond to the Tic Tac Toe game that will be played next. Yeah, you cannot chose any spot on the Super Tic Tac Toe grid, your opponent chooses it for you! For example, if my opponent places their O in the lower left corner of the Tic Tac Toe grid, my move will HAVE to be play in the lower left corner of the Super Tic Tac Toe grid! Sounds confusing? It's not once you start playing!
It's one big tic tac toe game made up of 9 smaller ones!!!
Being able to force your opponent to play in certain grids really adds strategy to the game. Will you risk playing a bad spot in order to move your opponent to a grid that you do not need or do you play every grid to win it but risk your opponent pushing you to strategic spots? I really had fun playing the game… once I got started. Once I signed up, there really weren't any players playing Super Tic Tac Toe. I had to wait in a queue until the game found an opponent for me to play. I waited patiently for a few minutes for a random player to appear. I was surprised that there was no CPU opponent. Many games like this would have a CPU opponent to go against with varying degree of difficulty to test your skills. In Super Tic Tac Toe, you play against other players only. So if you want to pick it up and play a game to two, you will need to have a friend readily available to play or you may be waiting for a random player to join for quite awhile. At least the game will notify you when a player is ready. A neat Tic Tac Toe symbol pops up on your home screen when the game is ready!
No one is available to play?!?!?!
Another feature of note in Super Tic Tac Toe is the chat feature. You can chat with your opponent while playing. You can engage in a little trash talk, which always makes game a little more fun, or you can have a casual conversation with a friend. The one thing that I really wish the game had was the option to turn off the chat feature. Since I was playing with a random player, the player continuously sent chat messages. They easily became a huge distraction since I had to step away from the game, by clicking on the chat bubble in the top right, to read them. In this instance, I would have loved to turn the chat off and get on with the game. A game that should have lasted a few minutes dragged on to over 30 mins.
The strategic element of Super Tic Tac Toe makes it a game that you must check out. Taking a classic game that everyone is familiar with and adding that strategic element enhances the gameplay and breathes new life to Tic Tac Toe. If you have an Android phone and looking for a free game to download, I recommend you get Super Tic Tac Toe. And the best part of it all??? It's absolutely free! Later!
Click here to go to Super Tic Tac Toe and download it for free for iOS or Android Operating Systems.
Windows 8 Series: Desktop mode and Office 2013 Buggy on Windows RT
Frankenweenie a Stop-Motion Horror Movie?


Kenneth D. King demonstrates a couture technique for making a padded jacket hem.
Kenneth D. King demonstrates a couture technique for making a jacket hem. The process consists of padding the hemline to prevent a hard crease and using a nearly invisible stitching method. He offers tips for choosing padding material, needles, and threads to achieve the best results.
I would like to use this on a project, but how and where is the lining attached to this hem?
I think I know, but want it to be easier. I like to bag the lining and that does not seem to be possible with this method.


Rab Ascent 700 - Men's sleeping bag with European duck down fill.
The travellers choice: highly packable summer bag. Comfort +13°C.
Men's sleeping bag with European duck down fill. -2°C...-8,5°C.
A spacious fall/winter bag with quilt function. -5°C...-10°C.
A sure choice for three season use. -4°C...-10°C. 1.2 kg.
Top notch three season bag. +5°C...-1°C. 500g.


text:
How Exercise Helps During and After Menopause
Selene Yeager was in her late 40s when she started noticing strange changes in her body and mood.
A lifelong competitive athlete, Selene noticed that her training wasn't having its usual effect. She had night sweats and anxiety, but she brushed it all off.
She learned later that she had begun going through menopause. Now she is devoted to helping women understand what menopause does to their bodies and brains, and how exercise helps lessen circumstances and improve overall health later in life.
"I didn't know what was going on, and that is true for a lot of women," Selene, a writer and trainer, and podcast host now in her 50s. "We're in 2021, and it's still radical to talk about menopause. Something got to change."
In addition to hormonal changes, many women experience mood swings, trouble sleeping, brain fog, and more. Bone density diminishes, which can be especially troubling since all people lose muscle mass as we age. Weak muscles and bones can often mean falls and fractures. Also, women can have trouble with tummy fat and a higher risk of heart disease after menopause.
"Exercise is the best medicine for all kinds of changes that women are going through at this time," says Selene, who leads the Feisty Menopause movement and hosts its Press Play Not Pause podcast.
Why Exercise Is So Important Now
Exercise works by improving muscle mass, strength, balance and coordination, according to the National Institutes of Health and other experts
"Research indicates that postmenopausal women who engage in the comprehensive exercise program, benefit by maintaining a healthy body, bone density levels, and good mental health," the government agency says. "Osteoporosis, the greatest ailment in older women, can be kept under control with exercise.
"Even a moderate exercise schedule can not only keep the weight in check, but it also lowers the risk of stress, anxiety, and depression, all of which tend to show up liberally during and beyond menopause."
As for hot flashes, though? Well, "the role of exercise, however, in hot flashes remains inconclusive."
Lifting Weights Is Particularly Helpful
Medical and fitness experts cite many studies (including one in the Journal of the American Medical Association) saying that women can reduce body fat, increase muscle mass, build up bones, and improve balance by lifting moderately heavy weights on a regular basis.
We agree, of course. And so does Selene. (And no, you won't get big and bulky!)
"Without the anabolic stimulation of estrogen, you need to make up the difference, and lifting weights does it," she says. "Women in this age category need to lift weights, and they're not being told that enough. And they need people to teach them because of lot of them haven't been shown."
Let us show you how effective, safe and fun resistance training is – and how to integrate it into a healthy lifestyle no matter your age or gender.
And if you have questions about menopause, please talk to your doctor.
>Additional sources: The Department of Health & Human Services; WebMD; The American College of Sports Medicine.
Stay Fit to Enjoy Your Grandkids All Year Round
9 Simple Steps to a Healthier Life in 2023About new year resolutions, there's bad news, and then t
Meme: Aging Well


text:
Myovant aspires to redefine care for women and for men through purpose-driven science, empowering medicines, and transformative advocacy.
As part of our work, we conduct clinical trials to evaluate the safety and efficacy of investigational drug candidates. Clinical trials are controlled research studies in humans designed to determine if an investigational drug candidate is safe and effective. Myovant encourages awareness of and participation in our clinical trials. Please visit http://myovant.com/our-science/pipeline and http://clinicaltrials.gov for more information about our clinical programs.
In certain cases, when it is not possible for a patient to participate in a clinical trial and all other available medical options have been exhausted, a patient's doctor may attempt to seek special access to an investigational drug candidate for that patient outside of a clinical trial. This is known, among other terms, as expanded access. For a patient to obtain access to an investigational drug candidate through expanded access, the patient's physician, the drug's sponsor and the U.S. Food and Drug Administration must all approve the use.
Making decisions about requests for expanded access to an investigational drug candidate is complicated, multi-faceted, patient-specific and fact-heavy. This is because investigational drug candidates—which, by definition, have not yet obtained regulatory approval—may present numerous risks for the patient and the clinical development program. For patients, expanded access may involve potential safety risks and/or offer false hope. Likewise, for the clinical development program, expanded access may delay or jeopardize the approval of a new therapy or treatment. None of our product candidates have clinical data demonstrating their safety and efficacy. For these and other reasons, therefore, Myovant believes that participating in clinical trials is the best way for patients to access investigational drug candidates and, at this point in time, we have not established an expanded access program.
If a treating doctor finds that expanded access may be the only option for a patient, the doctor should formally contact Myovant to make a written request. The following are some of the general considerations for expanded access: the patient must be suffering from a serious or immediately life-threatening disease for which no satisfactory treatment alternative exists; the medication must be undergoing clinical development by Myovant; and the provision of the medication must not compromise the clinical development program (e.g., the initiation, conduct, or completion of trials) or the potential regulatory approval of the medication; Myovant must have adequate supply of the medication; sufficient data must exist to support its use in the specific clinical condition from which the patient suffers and adequate data must also exist to identify an appropriate dose for use in such patients; overall, the potential benefit to the patient must outweigh the potential risks to the patient.