Ejemplo n.º 1
0
class Analysis(models.Model):
    """Represent GeoSAFE analysis"""
    HAZARD_EXPOSURE_CURRENT_VIEW_CODE = 1
    HAZARD_EXPOSURE_CODE = 2
    HAZARD_EXPOSURE_BBOX_CODE = 3

    HAZARD_EXPOSURE_CURRENT_VIEW_TEXT = (
        'Use intersection of hazard, exposure, and current view extent')
    HAZARD_EXPOSURE_TEXT = 'Use intersection of hazard and exposure'
    HAZARD_EXPOSURE_BBOX_TEXT = (
        'Use intersection of hazard, exposure, and bounding box')

    EXTENT_CHOICES = (
        (HAZARD_EXPOSURE_CURRENT_VIEW_CODE, HAZARD_EXPOSURE_CURRENT_VIEW_TEXT),
        (HAZARD_EXPOSURE_CODE, HAZARD_EXPOSURE_TEXT),
        # Disable for now
        # (HAZARD_EXPOSURE_BBOX_CODE, HAZARD_EXPOSURE_BBOX_TEXT),
    )

    class Meta:
        verbose_name_plural = 'Analyses'

    user_title = models.CharField(
        max_length=255,
        verbose_name='User defined title for analysis',
        help_text='Title to assign after analysis is generated.',
        blank=True,
        null=True,
    )
    exposure_layer = models.ForeignKey(
        Layer,
        verbose_name='Exposure Layer',
        help_text='Exposure layer for analysis.',
        blank=False,
        null=False,
        related_name='exposure_layer')
    hazard_layer = models.ForeignKey(Layer,
                                     verbose_name='Hazard Layer',
                                     help_text='Hazard layer for analysis.',
                                     blank=False,
                                     null=False,
                                     related_name='hazard_layer')
    aggregation_layer = models.ForeignKey(
        Layer,
        verbose_name='Aggregation Layer',
        help_text='Aggregation layer for analysis.',
        blank=True,
        null=True,
        related_name='aggregation_layer')
    impact_function_id = models.CharField(
        max_length=100,
        verbose_name='ID of Impact Function',
        help_text='The ID of Impact Function used in the analysis.',
        blank=False,
        null=False)
    extent_option = models.IntegerField(
        choices=EXTENT_CHOICES,
        default=HAZARD_EXPOSURE_CODE,
        verbose_name='Analysis extent',
        help_text='Extent option for analysis.')

    impact_layer = models.ForeignKey(
        Layer,
        verbose_name='Impact Layer',
        help_text='Impact layer from this analysis.',
        blank=True,
        null=True,
        related_name='impact_layer')

    task_id = models.CharField(max_length=40,
                               verbose_name='Task UUID',
                               help_text='Task UUID that runs analysis',
                               blank=True,
                               null=True)

    task_state = models.CharField(max_length=10,
                                  verbose_name='Task State',
                                  help_text='Task State recorded in the model',
                                  blank=True,
                                  null=True)

    keep = models.BooleanField(
        verbose_name='Keep impact result',
        help_text='True if the impact will be kept',
        blank=True,
        default=False,
    )

    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             verbose_name='Author',
                             help_text='The author of the analysis',
                             blank=True,
                             null=True)

    report_map = models.FileField(verbose_name='Report Map',
                                  help_text='The map report of the analysis',
                                  blank=True,
                                  null=True,
                                  upload_to='analysis/report/')

    report_table = models.FileField(
        verbose_name='Report Table',
        help_text='The table report of the analysis',
        blank=True,
        null=True,
        upload_to='analysis/report/')

    def assign_report_map(self, filename):
        try:
            self.report_map.delete()
        except:
            pass
        self.report_map = File(open(filename))

    def assign_report_table(self, filename):
        try:
            self.report_table.delete()
        except:
            pass
        self.report_table = File(open(filename))

    def get_task_result(self):
        return AsyncResult(self.task_id)

    def get_label_class(self):
        state = self.get_task_state()
        if state == 'SUCCESS':
            return 'success'
        elif state == 'FAILURE':
            return 'danger'
        else:
            return 'info'

    def get_task_state(self):
        """Check task state

        State need to be evaluated from task result.
        However after a certain time, the task result is removed from broker.
        In this case, the state will always return 'PENDING'. For this, we
        receive the actual result from self.state, which is the cached state

        :return:
        """
        result = self.get_task_result()
        return self.task_state if result.state == 'PENDING' else result.state

    def get_default_impact_title(self):
        layer_name = '%s on %s' % (self.hazard_layer.name,
                                   self.exposure_layer.name)
        return layer_name

    _impact_function_list = []

    @classmethod
    def impact_function_list(cls):
        if not cls._impact_function_list:
            from geosafe.tasks.headless.analysis import filter_impact_function
            cls._impact_function_list = filter_impact_function.delay().get()
        return cls._impact_function_list

    def impact_function_name(self):
        for i in self.impact_function_list():
            if i['id'] == self.impact_function_id:
                return i['name']
        return ''

    @classmethod
    def get_layer_url(cls, layer):
        layer_id = layer.id
        layer_url = reverse('geosafe:layer-archive',
                            kwargs={'layer_id': layer_id})
        layer_url = urlparse.urljoin(settings.GEONODE_BASE_URL, layer_url)
        return layer_url

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None,
             run_analysis_flag=True):
        super(Analysis, self).save(force_insert=force_insert,
                                   force_update=force_update,
                                   using=using,
                                   update_fields=update_fields)

    def delete(self, using=None):
        try:
            self.report_map.delete()
        except:
            pass

        try:
            self.report_table.delete()
        except:
            pass

        try:
            self.impact_layer.delete()
        except:
            pass
        super(Analysis, self).delete(using=using)