示例#1
0
    def get_context_data(self, **kwargs):
        context = super(ImageDetailView, self).get_context_data(**kwargs)

        image = context['object']
        r = self.kwargs.get('r')
        if r is None:
            r = '0'

        revision_image = None
        instance_to_platesolve = image
        is_revision = False
        if r != '0':
            try:
                revision_image = ImageRevision.objects.filter(image=image,
                                                              label=r)[0]
                instance_to_platesolve = revision_image
                is_revision = True
            except:
                pass

        #############################
        # GENERATE ACQUISITION DATA #
        #############################
        from astrobin.moon import MoonPhase

        gear_list = (
            (_('Imaging telescopes or lenses'), image.imaging_telescopes.all(),
             'imaging_telescopes'),
            (_('Imaging cameras'), image.imaging_cameras.all(),
             'imaging_cameras'),
            (_('Mounts'), image.mounts.all(), 'mounts'),
            (_('Guiding telescopes or lenses'), image.guiding_telescopes.all(),
             'guiding_telescopes'),
            (_('Guiding cameras'), image.guiding_cameras.all(),
             'guiding_cameras'),
            (_('Focal reducers'), image.focal_reducers.all(),
             'focal_reducers'),
            (_('Software'), image.software.all(), 'software'),
            (_('Filters'), image.filters.all(), 'filters'),
            (_('Accessory'), image.accessories.all(), 'accessories'),
        )

        makes_list = ','.join(
            filter(
                None,
                reduce(lambda x, y: x + y, [
                    list(x.values_list('make', flat=True))
                    for x in [y[1] for y in gear_list]
                ])))

        deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=image)
        ssa = None
        image_type = None
        deep_sky_data = {}

        if is_revision:
            w, h = get_image_resolution(revision_image)
        else:
            w, h = get_image_resolution(image)

        try:
            ssa = SolarSystem_Acquisition.objects.get(image=image)
        except SolarSystem_Acquisition.DoesNotExist:
            pass

        if deep_sky_acquisitions:
            image_type = 'deep_sky'

            moon_age_list = []
            moon_illuminated_list = []

            dsa_data = {
                'dates': [],
                'frames': {},
                'integration': 0,
                'darks': [],
                'flats': [],
                'flat_darks': [],
                'bias': [],
                'bortle': [],
                'mean_sqm': [],
                'mean_fwhm': [],
                'temperature': [],
            }
            for a in deep_sky_acquisitions:
                if a.date is not None and a.date not in dsa_data['dates']:
                    dsa_data['dates'].append(a.date)
                    m = MoonPhase(a.date)
                    moon_age_list.append(m.age)
                    moon_illuminated_list.append(m.illuminated * 100.0)

                if a.number and a.duration:
                    key = ""
                    if a.filter is not None:
                        key = "filter(%s)" % a.filter.get_name()
                    if a.iso is not None:
                        key += '-ISO(%d)' % a.iso
                    if a.gain is not None:
                        key += '-gain(%.2f)' % a.gain
                    if a.sensor_cooling is not None:
                        key += '-temp(%d)' % a.sensor_cooling
                    if a.binning is not None:
                        key += '-bin(%d)' % a.binning
                    key += '-duration(%d)' % a.duration

                    try:
                        current_frames = dsa_data['frames'][key]['integration']
                    except KeyError:
                        current_frames = '0x0"'

                    integration_re = re.match(r'^(\d+)x(\d+)"$',
                                              current_frames)
                    current_number = int(integration_re.group(1))

                    dsa_data['frames'][key] = {}
                    dsa_data['frames'][key][
                        'filter_url'] = a.filter.get_absolute_url(
                        ) if a.filter is not None else '#'
                    dsa_data['frames'][key][
                        'filter'] = a.filter if a.filter is not None else ''
                    dsa_data['frames'][key][
                        'iso'] = 'ISO%d' % a.iso if a.iso is not None else ''
                    dsa_data['frames'][key][
                        'gain'] = '(gain: %.2f)' % a.gain if a.gain is not None else ''
                    dsa_data['frames'][key][
                        'sensor_cooling'] = '%dC' % a.sensor_cooling if a.sensor_cooling is not None else ''
                    dsa_data['frames'][key]['binning'] = 'bin %sx%s' % (
                        a.binning, a.binning) if a.binning else ''
                    dsa_data['frames'][key]['integration'] = '%sx%s"' % (
                        current_number + a.number, a.duration)

                    dsa_data['integration'] += (a.duration * a.number / 3600.0)

                for i in ['darks', 'flats', 'flat_darks', 'bias']:
                    if a.filter and getattr(a, i):
                        dsa_data[i].append("%d" % getattr(a, i))
                    elif getattr(a, i):
                        dsa_data[i].append(getattr(a, i))

                if a.bortle:
                    dsa_data['bortle'].append(a.bortle)

                if a.mean_sqm:
                    dsa_data['mean_sqm'].append(a.mean_sqm)

                if a.mean_fwhm:
                    dsa_data['mean_fwhm'].append(a.mean_fwhm)

                if a.temperature:
                    dsa_data['temperature'].append(a.temperature)

            def average(values):
                if not len(values):
                    return 0
                return float(sum(values)) / len(values)

            frames_list = sorted(dsa_data['frames'].items())

            deep_sky_data = (
                (_('Dates'), sorted(dsa_data['dates'])),
                (_('Frames'), ('\n' if len(frames_list) > 1 else '') +
                 u'\n'.join("%s %s" % (
                     "<a href=\"%s\">%s</a>:" %
                     (f[1]['filter_url'],
                      f[1]['filter']) if f[1]['filter'] else '',
                     "%s %s %s %s %s" %
                     (f[1]['integration'], f[1]['iso'], f[1]['gain'],
                      f[1]['sensor_cooling'], f[1]['binning']),
                 ) for f in frames_list)),
                (_('Integration'),
                 "%.1f %s" % (dsa_data['integration'], _("hours"))),
                (_('Darks'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['darks']))
                  / len(dsa_data['darks'])) if dsa_data['darks'] else 0),
                (_('Flats'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['flats']))
                  / len(dsa_data['flats'])) if dsa_data['flats'] else 0),
                (_('Flat darks'), '~%d' % (int(
                    reduce(lambda x, y: int(x) + int(y),
                           dsa_data['flat_darks'])) /
                                           len(dsa_data['flat_darks']))
                 if dsa_data['flat_darks'] else 0),
                (_('Bias'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['bias'])) /
                  len(dsa_data['bias'])) if dsa_data['bias'] else 0),
                (_('Avg. Moon age'), ("%.2f " % (average(moon_age_list), ) +
                                      _("days")) if moon_age_list else None),
                (_('Avg. Moon phase'),
                 "%.2f%%" % (average(moon_illuminated_list), )
                 if moon_illuminated_list else None),
                (_('Bortle Dark-Sky Scale'),
                 "%.2f" % (average([float(x) for x in dsa_data['bortle']]))
                 if dsa_data['bortle'] else None),
                (_('Mean SQM'),
                 "%.2f" % (average([float(x) for x in dsa_data['mean_sqm']]))
                 if dsa_data['mean_sqm'] else None),
                (_('Mean FWHM'),
                 "%.2f" % (average([float(x) for x in dsa_data['mean_fwhm']]))
                 if dsa_data['mean_fwhm'] else None),
                (_('Temperature'),
                 "%.2f" % (average([float(x)
                                    for x in dsa_data['temperature']]))
                 if dsa_data['temperature'] else None),
            )

        elif ssa:
            image_type = 'solar_system'

        profile = None
        if self.request.user.is_authenticated():
            profile = self.request.user.userprofile

        ##############
        # BASIC DATA #
        ##############

        published_on = \
            to_user_timezone(image.uploaded, profile) \
                if profile else image.uploaded
        if image.published:
            published_on = \
                to_user_timezone(image.published, profile) \
                    if profile else image.published

        alias = 'regular' if not image.sharpen_thumbnails else 'regular_sharpened'
        mod = self.request.GET.get('mod')
        if mod == 'inverted':
            alias = 'regular_inverted'

        subjects = []
        skyplot_zoom1 = None

        if image.solution:
            subjects = SolutionService(image.solution).get_objects_in_field()
            skyplot_zoom1 = image.solution.skyplot_zoom1

        if is_revision and revision_image.solution:
            subjects = SolutionService(
                revision_image.solution).get_objects_in_field()
            if revision_image.solution.skyplot_zoom1:
                skyplot_zoom1 = revision_image.solution.skyplot_zoom1

        licenses = (
            (0, 'cc/c.png', LICENSE_CHOICES[0][1]),
            (1, 'cc/cc-by-nc-sa.png', LICENSE_CHOICES[1][1]),
            (2, 'cc/cc-by-nc.png', LICENSE_CHOICES[2][1]),
            (3, 'cc/cc-by-nc-nd.png', LICENSE_CHOICES[3][1]),
            (4, 'cc/cc-by.png', LICENSE_CHOICES[4][1]),
            (5, 'cc/cc-by-sa.png', LICENSE_CHOICES[5][1]),
            (6, 'cc/cc-by-nd.png', LICENSE_CHOICES[6][1]),
        )

        locations = '; '.join([u'%s' % (x) for x in image.locations.all()])

        ######################
        # PREFERRED LANGUAGE #
        ######################

        preferred_language = image.user.userprofile.language
        if preferred_language:
            try:
                preferred_language = LANGUAGES[preferred_language]
            except KeyError:
                preferred_language = _("English")
        else:
            preferred_language = _("English")

        ##########################
        # LIKE / BOOKMARKED THIS #
        ##########################
        like_this = image.toggleproperties.filter(property_type="like")
        bookmarked_this = image.toggleproperties.filter(
            property_type="bookmark")

        ##############
        # NAVIGATION #
        ##############
        image_next = None
        image_prev = None
        try:
            nav_ctx = self.request.GET.get('nc')
            if nav_ctx is None:
                nav_ctx = self.request.session.get('nav_ctx')
            if nav_ctx is None:
                nav_ctx = 'user'

            nav_ctx_extra = self.request.GET.get('nce')
            if nav_ctx_extra is None:
                nav_ctx_extra = self.request.session.get('nav_ctx_extra')

            # Always only lookup public, non corrupted images!
            if nav_ctx == 'user':
                image_next = Image.objects \
                                 .exclude(corrupted=True) \
                                 .filter(user=image.user, pk__gt=image.pk).order_by('pk')[0:1]
                image_prev = Image.objects \
                                 .exclude(corrupted=True) \
                                 .filter(user=image.user, pk__lt=image.pk).order_by('-pk')[0:1]
            elif nav_ctx == 'collection':
                try:
                    try:
                        collection = image.collections.get(pk=nav_ctx_extra)
                    except ValueError:
                        # Maybe this image is in a single collection
                        collection = image.collections.all()[0]

                    if collection.order_by_tag:
                        collection_images = Image.objects \
                            .exclude(corrupted=True) \
                            .filter(user=image.user, collections=collection, keyvaluetags__key=collection.order_by_tag) \
                            .order_by('keyvaluetags__value')

                        current_index = 0
                        for iter_image in collection_images.all():
                            if iter_image.pk == image.pk:
                                break
                            current_index += 1

                        image_next = collection_images.all()[current_index + 1] \
                            if current_index < collection_images.count() - 1 \
                            else None
                        image_prev = collection_images.all()[current_index - 1] \
                            if current_index > 0 \
                            else None
                    else:
                        image_next = Image.objects \
                                         .exclude(corrupted=True) \
                                         .filter(user=image.user, collections=collection,
                                                 pk__gt=image.pk).order_by('pk')[0:1]
                        image_prev = Image.objects \
                                         .exclude(corrupted=True) \
                                         .filter(user=image.user, collections=collection,
                                                 pk__lt=image.pk).order_by('-pk')[0:1]
                except Collection.DoesNotExist:
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'group':
                try:
                    group = image.part_of_group_set.get(pk=nav_ctx_extra)
                    if group.public:
                        image_next = Image.objects \
                                         .exclude(corrupted=True) \
                                         .filter(part_of_group_set=group, pk__gt=image.pk).order_by('pk')[0:1]
                        image_prev = Image.objects \
                                         .exclude(corrupted=True) \
                                         .filter(part_of_group_set=group, pk__lt=image.pk).order_by('-pk')[0:1]
                except (Group.DoesNotExist, ValueError):
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'all':
                image_next = Image.objects.exclude(corrupted=True).filter(
                    pk__gt=image.pk).order_by('pk')[0:1]
                image_prev = Image.objects.exclude(corrupted=True).filter(
                    pk__lt=image.pk).order_by('-pk')[0:1]
        except Image.DoesNotExist:
            image_next = None
            image_prev = None

        if image_next and isinstance(image_next, QuerySet):
            image_next = image_next[0]
        if image_prev and isinstance(image_prev, QuerySet):
            image_prev = image_prev[0]

        #################
        # RESPONSE DICT #
        #################

        from astrobin_apps_platesolving.solver import Solver

        if skyplot_zoom1 and not skyplot_zoom1.name.startswith('images/'):
            skyplot_zoom1.name = 'images/' + skyplot_zoom1.name

        response_dict = context.copy()
        response_dict.update({
            'SHARE_PATH': settings.SHORT_BASE_URL,

            'alias': alias,
            'mod': mod,
            'revisions': ImageService(image) \
                .get_revisions(include_corrupted=self.request.user == image.user) \
                .select_related('image__user__userprofile'),
            'revisions_with_description': ImageService(image) \
                .get_revisions_with_description(include_corrupted=self.request.user == image.user) \
                .select_related('image__user__userprofile'),
            'is_revision': is_revision,
            'revision_image': revision_image,
            'revision_label': r,

            'instance_to_platesolve': instance_to_platesolve,
            'show_solution': instance_to_platesolve.mouse_hover_image == "SOLUTION"
                             and instance_to_platesolve.solution
                             and instance_to_platesolve.solution.status >= Solver.SUCCESS,
            'show_advanced_solution': instance_to_platesolve.mouse_hover_image == "SOLUTION"
                                      and instance_to_platesolve.solution
                                      and instance_to_platesolve.solution.status == Solver.ADVANCED_SUCCESS,
            'skyplot_zoom1': skyplot_zoom1,

            'image_ct': ContentType.objects.get_for_model(Image),
            'like_this': like_this,
            'user_can_like': can_like(self.request.user, image),
            'bookmarked_this': bookmarked_this,

            'comments_number': NestedComment.objects.filter(
                deleted=False,
                content_type__app_label='astrobin',
                content_type__model='image',
                object_id=image.id).count(),
            'gear_list': gear_list,
            'makes_list': makes_list,
            'image_type': image_type,
            'ssa': ssa,
            'deep_sky_data': deep_sky_data,
            'private_message_form': PrivateMessageForm(),
            'promote_form': ImagePromoteForm(instance=image),
            'upload_revision_form': ImageRevisionUploadForm(),
            'upload_uncompressed_source_form': UncompressedSourceUploadForm(instance=image),
            'dates_label': _("Dates"),
            'published_on': published_on,
            'show_contains': (image.subject_type == SubjectType.DEEP_SKY and subjects) or
                             (image.subject_type != SubjectType.DEEP_SKY),
            'subjects': subjects,
            'subject_type': ImageService(image).get_subject_type_label(),
            'hemisphere': ImageService(image).get_hemisphere(r),
            'license_icon': static('astrobin/icons/%s' % licenses[image.license][1]),
            'license_title': licenses[image.license][2],
            'resolution': '%dx%d' % (w, h) if (w and h) else None,
            'locations': locations,
            'solar_system_main_subject': ImageService(image).get_solar_system_main_subject_label(),
            'content_type': ContentType.objects.get(app_label='astrobin', model='image'),
            'preferred_language': preferred_language,
            'select_group_form': GroupSelectForm(
                user=self.request.user) if self.request.user.is_authenticated() else None,
            'in_public_groups': Group.objects.filter(Q(public=True, images=image)),
            'image_next': image_next,
            'image_prev': image_prev,
            'nav_ctx': nav_ctx,
            'nav_ctx_extra': nav_ctx_extra,
        })

        return response_dict
示例#2
0
    def get_context_data(self, **kwargs):
        context = super(ImageDetailView, self).get_context_data(**kwargs)

        image = context['object']
        r = self.kwargs.get('r')
        if r is None:
            r = '0'

        revision_image = None
        instance_to_platesolve = image
        is_revision = False
        if r != '0':
            try:
                revision_image = ImageRevision.objects.filter(image=image,
                                                              label=r)[0]
                instance_to_platesolve = revision_image
                is_revision = True
            except:
                pass

        #############################
        # GENERATE ACQUISITION DATA #
        #############################
        from astrobin.moon import MoonPhase

        gear_list = (
            (ungettext('Imaging telescope or lens',
                       'Imaging telescopes or lenses',
                       len(image.imaging_telescopes.all())),
             image.imaging_telescopes.all(), 'imaging_telescopes'),
            (ungettext('Imaging camera', 'Imaging cameras',
                       len(image.imaging_cameras.all())),
             image.imaging_cameras.all(), 'imaging_cameras'),
            (ungettext('Mount', 'Mounts',
                       len(image.mounts.all())), image.mounts.all(), 'mounts'),
            (ungettext('Guiding telescope or lens',
                       'Guiding telescopes or lenses',
                       len(image.guiding_telescopes.all())),
             image.guiding_telescopes.all(), 'guiding_telescopes'),
            (ungettext('Guiding camera', 'Guiding cameras',
                       len(image.guiding_cameras.all())),
             image.guiding_cameras.all(), 'guiding_cameras'),
            (ungettext('Focal reducer', 'Focal reducers',
                       len(image.focal_reducers.all())),
             image.focal_reducers.all(), 'focal_reducers'),
            (_('Software'), image.software.all(), 'software'),
            (ungettext('Filter', 'Filters', len(image.filters.all())),
             image.filters.all(), 'filters'),
            (ungettext('Accessory',
                       'Accessories', len(image.accessories.all())),
             image.accessories.all(), 'accessories'),
        )

        gear_list_has_commercial = False
        gear_list_has_paid_commercial = False
        for g in gear_list:
            if g[1].exclude(commercial=None).count() > 0:
                gear_list_has_commercial = True
                break
        for g in gear_list:
            for i in g[1].exclude(commercial=None):
                if i.commercial.is_paid(
                ) or i.commercial.producer == self.request.user:
                    gear_list_has_paid_commercial = True
                    # It would be faster if we exited the outer loop, but really,
                    # how many gear items can an image have?
                    break

        makes_list = ','.join(
            filter(
                None,
                reduce(lambda x, y: x + y, [
                    list(x.values_list('make', flat=True))
                    for x in [y[1] for y in gear_list]
                ])))

        deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=image)
        ssa = None
        image_type = None
        deep_sky_data = {}

        try:
            ssa = SolarSystem_Acquisition.objects.get(image=image)
        except SolarSystem_Acquisition.DoesNotExist:
            pass

        if deep_sky_acquisitions:
            image_type = 'deep_sky'

            moon_age_list = []
            moon_illuminated_list = []

            dsa_data = {
                'dates': [],
                'frames': {},
                'integration': 0,
                'darks': [],
                'flats': [],
                'flat_darks': [],
                'bias': [],
                'bortle': [],
                'mean_sqm': [],
                'mean_fwhm': [],
                'temperature': [],
            }
            for a in deep_sky_acquisitions:
                if a.date is not None and a.date not in dsa_data['dates']:
                    dsa_data['dates'].append(a.date)
                    m = MoonPhase(a.date)
                    moon_age_list.append(m.age)
                    moon_illuminated_list.append(m.illuminated * 100.0)

                if a.number and a.duration:
                    key = ""
                    if a.filter:
                        key = "filter(%s)" % a.filter.get_name()
                    if a.iso:
                        key += '-ISO(%d)' % a.iso
                    if a.gain:
                        key += '-gain(%.2f)' % a.gain
                    if a.sensor_cooling:
                        key += '-temp(%d)' % a.sensor_cooling
                    if a.binning:
                        key += '-bin(%d)' % a.binning
                    key += '-duration(%d)' % a.duration

                    try:
                        current_frames = dsa_data['frames'][key]['integration']
                    except KeyError:
                        current_frames = '0x0"'

                    integration_re = re.match(r'^(\d+)x(\d+)"$',
                                              current_frames)
                    current_number = int(integration_re.group(1))

                    dsa_data['frames'][key] = {}
                    dsa_data['frames'][key][
                        'filter_url'] = a.filter.get_absolute_url(
                        ) if a.filter else '#'
                    dsa_data['frames'][key][
                        'filter'] = a.filter if a.filter else ''
                    dsa_data['frames'][key][
                        'iso'] = 'ISO%d' % a.iso if a.iso else ''
                    dsa_data['frames'][key][
                        'gain'] = '(gain: %.2f)' % a.gain if a.gain else ''
                    dsa_data['frames'][key][
                        'sensor_cooling'] = '%dC' % a.sensor_cooling if a.sensor_cooling else ''
                    dsa_data['frames'][key]['binning'] = 'bin %sx%s' % (
                        a.binning, a.binning) if a.binning else ''
                    dsa_data['frames'][key]['integration'] = '%sx%s"' % (
                        current_number + a.number, a.duration)

                    dsa_data['integration'] += (a.duration * a.number / 3600.0)

                for i in ['darks', 'flats', 'flat_darks', 'bias']:
                    if a.filter and getattr(a, i):
                        dsa_data[i].append("%d" % getattr(a, i))
                    elif getattr(a, i):
                        dsa_data[i].append(getattr(a, i))

                if a.bortle:
                    dsa_data['bortle'].append(a.bortle)

                if a.mean_sqm:
                    dsa_data['mean_sqm'].append(a.mean_sqm)

                if a.mean_fwhm:
                    dsa_data['mean_fwhm'].append(a.mean_fwhm)

                if a.temperature:
                    dsa_data['temperature'].append(a.temperature)

            def average(values):
                if not len(values):
                    return 0
                return float(sum(values)) / len(values)

            frames_list = sorted(dsa_data['frames'].items())

            deep_sky_data = (
                (_('Dates'), sorted(dsa_data['dates'])),
                (_('Frames'), ('\n' if len(frames_list) > 1 else '') +
                 u'\n'.join("%s %s" % (
                     "<a href=\"%s\">%s</a>:" %
                     (f[1]['filter_url'],
                      f[1]['filter']) if f[1]['filter'] else '',
                     "%s %s %s %s %s" %
                     (f[1]['integration'], f[1]['iso'], f[1]['gain'],
                      f[1]['sensor_cooling'], f[1]['binning']),
                 ) for f in frames_list)),
                (_('Integration'),
                 "%.1f %s" % (dsa_data['integration'], _("hours"))),
                (_('Darks'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['darks']))
                  / len(dsa_data['darks'])) if dsa_data['darks'] else 0),
                (_('Flats'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['flats']))
                  / len(dsa_data['flats'])) if dsa_data['flats'] else 0),
                (_('Flat darks'), '~%d' % (int(
                    reduce(lambda x, y: int(x) + int(y),
                           dsa_data['flat_darks'])) /
                                           len(dsa_data['flat_darks']))
                 if dsa_data['flat_darks'] else 0),
                (_('Bias'), '~%d' %
                 (int(reduce(lambda x, y: int(x) + int(y), dsa_data['bias'])) /
                  len(dsa_data['bias'])) if dsa_data['bias'] else 0),
                (_('Avg. Moon age'), ("%.2f " % (average(moon_age_list), ) +
                                      _("days")) if moon_age_list else None),
                (_('Avg. Moon phase'),
                 "%.2f%%" % (average(moon_illuminated_list), )
                 if moon_illuminated_list else None),
                (_('Bortle Dark-Sky Scale'),
                 "%.2f" % (average([float(x) for x in dsa_data['bortle']]))
                 if dsa_data['bortle'] else None),
                (_('Mean SQM'),
                 "%.2f" % (average([float(x) for x in dsa_data['mean_sqm']]))
                 if dsa_data['mean_sqm'] else None),
                (_('Mean FWHM'),
                 "%.2f" % (average([float(x) for x in dsa_data['mean_fwhm']]))
                 if dsa_data['mean_fwhm'] else None),
                (_('Temperature'),
                 "%.2f" % (average([float(x)
                                    for x in dsa_data['temperature']]))
                 if dsa_data['temperature'] else None),
            )

        elif ssa:
            image_type = 'solar_system'

        # Image resolution, aka size in pixels
        try:
            if is_revision:
                w, h = revision_image.w, revision_image.h
                if not (w and h):
                    w, h = get_image_dimensions(revision_image.image_file)
            else:
                w, h = image.w, image.h
                if not (w and h):
                    w, h = get_image_dimensions(image.image_file)
        except TypeError:
            # This might happen in unit tests
            w, h = 0, 0

        # Data that's common to both DS and SS images
        basic_data = ((_('Resolution'), '%dx%d' % (w, h) if
                       (w and h) else None), )

        profile = None
        if self.request.user.is_authenticated():
            profile = self.request.user.userprofile

        ##############
        # BASIC DATA #
        ##############

        published_on = \
            to_user_timezone(image.uploaded, profile) \
                if profile else image.uploaded
        if image.published:
            published_on = \
                to_user_timezone(image.published, profile) \
                    if profile else image.published

        alias = 'regular'
        mod = self.request.GET.get('mod')
        if mod == 'inverted':
            alias = 'regular_inverted'

        subjects = image.solution.objects_in_field.split(
            ',') if image.solution and image.solution.objects_in_field else ''
        skyplot_zoom1 = None

        if is_revision:
            if revision_image.solution:
                if revision_image.solution.objects_in_field:
                    subjects = revision_image.solution.objects_in_field.split(
                        ',')
                if revision_image.solution.skyplot_zoom1:
                    skyplot_zoom1 = revision_image.solution.skyplot_zoom1
        else:
            if image.solution:
                if image.solution.objects_in_field:
                    subjects = image.solution.objects_in_field.split(',')
                if image.solution.skyplot_zoom1:
                    skyplot_zoom1 = image.solution.skyplot_zoom1

        subjects_limit = 5

        licenses = (
            (0, 'cc/c.png', LICENSE_CHOICES[0][1]),
            (1, 'cc/cc-by-nc-sa.png', LICENSE_CHOICES[1][1]),
            (2, 'cc/cc-by-nc.png', LICENSE_CHOICES[2][1]),
            (3, 'cc/cc-by-nc-nd.png', LICENSE_CHOICES[3][1]),
            (4, 'cc/cc-by.png', LICENSE_CHOICES[4][1]),
            (5, 'cc/cc-by-sa.png', LICENSE_CHOICES[5][1]),
            (6, 'cc/cc-by-nd.png', LICENSE_CHOICES[6][1]),
        )

        locations = '; '.join([u'%s' % (x) for x in image.locations.all()])

        ######################
        # PREFERRED LANGUAGE #
        ######################

        preferred_language = image.user.userprofile.language
        if preferred_language:
            try:
                preferred_language = LANGUAGES[preferred_language]
            except KeyError:
                preferred_language = _("English")
        else:
            preferred_language = _("English")

        ##########################
        # LIKE / BOOKMARKED THIS #
        ##########################
        like_this = image.toggleproperties.filter(property_type="like")
        bookmarked_this = image.toggleproperties.filter(
            property_type="bookmark")

        ##############
        # NAVIGATION #
        ##############
        image_next = None
        image_prev = None
        try:
            nav_ctx = self.request.GET.get('nc')
            if nav_ctx is None:
                nav_ctx = self.request.session.get('nav_ctx')
            if nav_ctx is None:
                nav_ctx = 'user'

            nav_ctx_extra = self.request.GET.get('nce')
            if nav_ctx_extra is None:
                nav_ctx_extra = self.request.session.get('nav_ctx_extra')

            # Always only lookup public images!
            if nav_ctx == 'user':
                image_next = Image.objects.filter(
                    user=image.user, pk__gt=image.pk).order_by('pk')[0:1]
                image_prev = Image.objects.filter(
                    user=image.user, pk__lt=image.pk).order_by('-pk')[0:1]
            elif nav_ctx == 'collection':
                try:
                    try:
                        collection = image.collections.get(pk=nav_ctx_extra)
                    except ValueError:
                        # Maybe this image is in a single collection
                        collection = image.collections.all()[0]

                    if collection.order_by_tag:
                        collection_images = Image.objects\
                            .filter(user=image.user, collections=collection, keyvaluetags__key=collection.order_by_tag)\
                            .order_by('keyvaluetags__value')

                        current_index = 0
                        for iter_image in collection_images.all():
                            if iter_image.pk == image.pk:
                                break
                            current_index += 1

                        image_next = collection_images.all()[current_index + 1] \
                            if current_index < collection_images.count() - 1\
                            else None
                        image_prev = collection_images.all()[current_index - 1]\
                            if current_index > 0 \
                            else None
                    else:
                        image_next = Image.objects.filter(
                            user=image.user,
                            collections=collection,
                            pk__gt=image.pk).order_by('pk')[0:1]
                        image_prev = Image.objects.filter(
                            user=image.user,
                            collections=collection,
                            pk__lt=image.pk).order_by('-pk')[0:1]
                except Collection.DoesNotExist:
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'group':
                try:
                    group = image.part_of_group_set.get(pk=nav_ctx_extra)
                    if group.public:
                        image_next = Image.objects.filter(
                            part_of_group_set=group,
                            pk__gt=image.pk).order_by('pk')[0:1]
                        image_prev = Image.objects.filter(
                            part_of_group_set=group,
                            pk__lt=image.pk).order_by('-pk')[0:1]
                except Group.DoesNotExist:
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'all':
                image_next = Image.objects.filter(
                    pk__gt=image.pk).order_by('pk')[0:1]
                image_prev = Image.objects.filter(
                    pk__lt=image.pk).order_by('-pk')[0:1]
            elif nav_ctx == 'iotd':
                try:
                    iotd = Iotd.objects.get(image=image)
                    iotd_next = Iotd.objects.filter(
                        date__gt=iotd.date,
                        date__lte=datetime.now().date()).order_by('date')[0:1]
                    iotd_prev = Iotd.objects.filter(
                        date__lt=iotd.date,
                        date__lte=datetime.now().date()).order_by('-date')[0:1]

                    if iotd_next:
                        image_next = [iotd_next[0].image]
                    if iotd_prev:
                        image_prev = [iotd_prev[0].image]
                except Iotd.DoesNotExist:
                    pass
            elif nav_ctx == 'picks':
                picks = Image.objects.exclude(iotdvote=None).filter(iotd=None)
                image_next = picks.filter(pk__gt=image.pk).order_by('pk')[0:1]
                image_prev = picks.filter(pk__lt=image.pk).order_by('-pk')[0:1]
        except Image.DoesNotExist:
            image_next = None
            image_prev = None

        if image_next and isinstance(image_next, QuerySet):
            image_next = image_next[0]
        if image_prev and isinstance(image_prev, QuerySet):
            image_prev = image_prev[0]

        #################
        # RESPONSE DICT #
        #################

        from astrobin_apps_platesolving.solver import Solver

        if skyplot_zoom1 and not skyplot_zoom1.name.startswith('images/'):
            skyplot_zoom1.name = 'images/' + skyplot_zoom1.name

        response_dict = context.copy()
        response_dict.update({
            'SHARE_PATH': settings.SHORT_BASE_URL,

            'alias': alias,
            'mod': mod,
            'revisions': ImageRevision.objects.select_related('image__user__userprofile').filter(image=image),
            'revisions_with_description':
                ImageRevision.objects \
                    .select_related('image__user__userprofile') \
                    .filter(image=image) \
                    .exclude(Q(description=None) | Q(description='')),
            'is_revision': is_revision,
            'revision_image': revision_image,
            'revision_label': r,

            'instance_to_platesolve': instance_to_platesolve,
            'show_solution': instance_to_platesolve.mouse_hover_image == "SOLUTION"
                             and instance_to_platesolve.solution
                             and instance_to_platesolve.solution.status == Solver.SUCCESS,
            'skyplot_zoom1': skyplot_zoom1,

            'image_ct': ContentType.objects.get_for_model(Image),
            'like_this': like_this,
            'user_can_like': can_like(self.request.user, image),
            'bookmarked_this': bookmarked_this,
            'min_index_to_like': settings.MIN_INDEX_TO_LIKE,

            'comments_number': NestedComment.objects.filter(
                deleted=False,
                content_type__app_label='astrobin',
                content_type__model='image',
                object_id=image.id).count(),
            'gear_list': gear_list,
            'makes_list': makes_list,
            'gear_list_has_commercial': gear_list_has_commercial,
            'gear_list_has_paid_commercial': gear_list_has_paid_commercial,
            'image_type': image_type,
            'ssa': ssa,
            'basic_data': basic_data,
            'deep_sky_data': deep_sky_data,
            # TODO: check that solved image is correcly laid on top
            'private_message_form': PrivateMessageForm(),
            'upload_revision_form': ImageRevisionUploadForm(),
            'dates_label': _("Dates"),
            'published_on': published_on,
            'show_contains': (image.subject_type == 100 and subjects) or (image.subject_type >= 200),
            'subjects_short': subjects[:subjects_limit],
            'subjects_reminder': subjects[subjects_limit:],
            'subjects_all': subjects,
            'subjects_limit': subjects_limit,
            'subject_type': [x[1] for x in Image.SUBJECT_TYPE_CHOICES if x[0] == image.subject_type][
                0] if image.subject_type else 0,
            'license_icon': static('astrobin/icons/%s' % licenses[image.license][1]),
            'license_title': licenses[image.license][2],
            'locations': locations,
            # Because of a regression introduced at
            # revision e1dad12babe5, now we have to
            # implement this ugly hack.

            'solar_system_main_subject_id': image.solar_system_main_subject,
            'solar_system_main_subject': SOLAR_SYSTEM_SUBJECT_CHOICES[image.solar_system_main_subject][
                1] if image.solar_system_main_subject is not None else None,
            'content_type': ContentType.objects.get(app_label='astrobin', model='image'),
            'preferred_language': preferred_language,
            'select_group_form': GroupSelectForm(
                user=self.request.user) if self.request.user.is_authenticated() else None,
            'in_public_groups': Group.objects.filter(Q(public=True, images=image)),
            'select_datapool_form': PublicDataPool_SelectExistingForm(),
            'select_sharedfolder_form': PrivateSharedFolder_SelectExistingForm(
                user=self.request.user) if self.request.user.is_authenticated() else None,
            'has_sharedfolders': PrivateSharedFolder.objects.filter(
                Q(creator=self.request.user) |
                Q(users=self.request.user)).count() > 0 if self.request.user.is_authenticated() else False,

            'image_next': image_next,
            'image_prev': image_prev,
            'nav_ctx': nav_ctx,
            'nav_ctx_extra': nav_ctx_extra,
        })

        return response_dict
示例#3
0
    def get_context_data(self, **kwargs):
        context = super(ImageDetailView, self).get_context_data(**kwargs)

        image = context['object']
        r = self.kwargs.get('r')
        if r is None:
            r = '0'

        revision_image = None
        instance_to_platesolve = image
        is_revision = False
        if r != '0':
            try:
                revision_image = ImageRevision.objects.filter(image = image, label = r)[0]
                instance_to_platesolve = revision_image
                is_revision = True
            except:
                pass

        #############################
        # GENERATE ACQUISITION DATA #
        #############################
        from astrobin.moon import MoonPhase;

        gear_list = (
            (ungettext('Imaging telescope or lens',
                       'Imaging telescopes or lenses',
                       len(image.imaging_telescopes.all())),
             image.imaging_telescopes.all(), 'imaging_telescopes'),
            (ungettext('Imaging camera',
                       'Imaging cameras',
                       len(image.imaging_cameras.all())),
             image.imaging_cameras.all(), 'imaging_cameras'),
            (ungettext('Mount',
                       'Mounts',
                       len(image.mounts.all())),
             image.mounts.all(), 'mounts'),
            (ungettext('Guiding telescope or lens',
                       'Guiding telescopes or lenses',
                       len(image.guiding_telescopes.all())),
             image.guiding_telescopes.all(), 'guiding_telescopes'),
            (ungettext('Guiding camera',
                       'Guiding cameras',
                       len(image.guiding_cameras.all())),
             image.guiding_cameras.all(), 'guiding_cameras'),
            (ungettext('Focal reducer',
                       'Focal reducers',
                       len(image.focal_reducers.all())),
             image.focal_reducers.all(), 'focal_reducers'),
            (_('Software'), image.software.all(), 'software'),
            (ungettext('Filter',
                       'Filters',
                       len(image.filters.all())),
             image.filters.all(), 'filters'),
            (ungettext('Accessory',
                       'Accessories',
                       len(image.accessories.all())),
             image.accessories.all(), 'accessories'),
        )

        gear_list_has_commercial = False
        gear_list_has_paid_commercial = False
        for g in gear_list:
            if g[1].exclude(commercial = None).count() > 0:
                gear_list_has_commercial = True
                break
        for g in gear_list:
            for i in g[1].exclude(commercial = None):
                if i.commercial.is_paid() or i.commercial.producer == self.request.user:
                    gear_list_has_paid_commercial = True
                    # It would be faster if we exited the outer loop, but really,
                    # how many gear items can an image have?
                    break

        makes_list = ','.join(
            filter(None, reduce(
                lambda x,y: x+y,
                [list(x.values_list('make', flat = True)) for x in [y[1] for y in gear_list]])))

        deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=image)
        ssa = None
        image_type = None
        deep_sky_data = {}

        try:
            ssa = SolarSystem_Acquisition.objects.get(image=image)
        except SolarSystem_Acquisition.DoesNotExist:
            pass

        if deep_sky_acquisitions:
            image_type = 'deep_sky'

            moon_age_list = []
            moon_illuminated_list = []

            dsa_data = {
                'dates': [],
                'frames': {},
                'integration': 0,
                'darks': [],
                'flats': [],
                'flat_darks': [],
                'bias': [],
                'bortle': [],
                'mean_sqm': [],
                'mean_fwhm': [],
                'temperature': [],
            }
            for a in deep_sky_acquisitions:
                if a.date is not None and a.date not in dsa_data['dates']:
                    dsa_data['dates'].append(a.date)
                    m = MoonPhase(a.date)
                    moon_age_list.append(m.age)
                    moon_illuminated_list.append(m.illuminated * 100.0)

                if a.number and a.duration:
                    key = ""
                    if a.filter:
                        key = "filter(%s)" % a.filter.get_name()
                    if a.iso:
                        key += '-ISO(%d)' % a.iso
                    if a.gain:
                        key += '-gain(%.2f)' % a.gain
                    if a.sensor_cooling:
                        key += '-temp(%d)' % a.sensor_cooling
                    if a.binning:
                        key += '-bin(%d)' % a.binning
                    key += '-duration(%d)' % a.duration

                    try:
                        current_frames = dsa_data['frames'][key]['integration']
                    except KeyError:
                        current_frames = '0x0"'

                    integration_re = re.match(r'^(\d+)x(\d+)"$', current_frames)
                    current_number = int(integration_re.group(1))

                    dsa_data['frames'][key] = {}
                    dsa_data['frames'][key]['filter_url'] = a.filter.get_absolute_url() if a.filter else '#'
                    dsa_data['frames'][key]['filter'] = a.filter if a.filter else ''
                    dsa_data['frames'][key]['iso'] = 'ISO%d' % a.iso if a.iso else ''
                    dsa_data['frames'][key]['gain'] = '(gain: %.2f)' % a.gain if a.gain else ''
                    dsa_data['frames'][key]['sensor_cooling'] = '%dC' % a.sensor_cooling if a.sensor_cooling else ''
                    dsa_data['frames'][key]['binning'] = 'bin %sx%s' % (a.binning, a.binning) if a.binning else ''
                    dsa_data['frames'][key]['integration'] = '%sx%s"' % (current_number + a.number, a.duration)

                    dsa_data['integration'] += (a.duration * a.number / 3600.0)

                for i in ['darks', 'flats', 'flat_darks', 'bias']:
                    if a.filter and getattr(a, i):
                        dsa_data[i].append("%d" % getattr(a, i))
                    elif getattr(a, i):
                        dsa_data[i].append(getattr(a, i))

                if a.bortle:
                    dsa_data['bortle'].append(a.bortle)

                if a.mean_sqm:
                    dsa_data['mean_sqm'].append(a.mean_sqm)

                if a.mean_fwhm:
                    dsa_data['mean_fwhm'].append(a.mean_fwhm)

                if a.temperature:
                    dsa_data['temperature'].append(a.temperature)

            def average(values):
                if not len(values):
                    return 0
                return float(sum(values)) / len(values)

            frames_list = sorted(dsa_data['frames'].items())

            deep_sky_data = (
                (_('Dates'), sorted(dsa_data['dates'])),
                (_('Frames'),
                    ('\n' if len(frames_list) > 1 else '') +
                    u'\n'.join("%s %s" % (
                        "<a href=\"%s\">%s</a>:" % (f[1]['filter_url'], f[1]['filter']) if f[1]['filter'] else '',
                        "%s %s %s %s %s" % (f[1]['integration'], f[1]['iso'], f[1]['gain'], f[1]['sensor_cooling'], f[1]['binning']),
                    ) for f in frames_list)),
                (_('Integration'), "%.1f %s" % (dsa_data['integration'], _("hours"))),
                (_('Darks'), '~%d' % (int(reduce(lambda x, y: int(x) + int(y), dsa_data['darks'])) / len(dsa_data['darks'])) if dsa_data['darks'] else 0),
                (_('Flats'), '~%d' % (int(reduce(lambda x, y: int(x) + int(y), dsa_data['flats'])) / len(dsa_data['flats'])) if dsa_data['flats'] else 0),
                (_('Flat darks'), '~%d' % (int(reduce(lambda x, y: int(x) + int(y), dsa_data['flat_darks'])) / len(dsa_data['flat_darks'])) if dsa_data['flat_darks'] else 0),
                (_('Bias'), '~%d' % (int(reduce(lambda x, y: int(x) + int(y), dsa_data['bias'])) / len(dsa_data['bias'])) if dsa_data['bias'] else 0),
                (_('Avg. Moon age'), ("%.2f " % (average(moon_age_list), ) + _("days")) if moon_age_list else None),
                (_('Avg. Moon phase'), "%.2f%%" % (average(moon_illuminated_list), ) if moon_illuminated_list else None),
                (_('Bortle Dark-Sky Scale'), "%.2f" % (average([float(x) for x in dsa_data['bortle']])) if dsa_data['bortle'] else None),
                (_('Mean SQM'), "%.2f" % (average([float(x) for x in dsa_data['mean_sqm']])) if dsa_data['mean_sqm'] else None),
                (_('Mean FWHM'), "%.2f" % (average([float(x) for x in dsa_data['mean_fwhm']])) if dsa_data['mean_fwhm'] else None),
                (_('Temperature'),
                 "%.2f" % (average([float(x) for x in dsa_data['temperature']])) if dsa_data['temperature'] else None),
            )

        elif ssa:
            image_type = 'solar_system'

        # Image resolution, aka size in pixels
        try:
            if is_revision:
                w, h = revision_image.w, revision_image.h
                if not (w and h):
                    w, h = get_image_dimensions(revision_image.image_file)
            else:
                w, h = image.w, image.h
                if not (w and h):
                    w, h = get_image_dimensions(image.image_file)
        except TypeError:
            # This might happen in unit tests
            w, h = 0, 0

        # Data that's common to both DS and SS images
        basic_data = (
            (_('Resolution'), '%dx%d' % (w, h) if (w and h) else None),
        )

        profile = None
        if self.request.user.is_authenticated():
            profile = self.request.user.userprofile


        ##############
        # BASIC DATA #
        ##############

        published_on = \
            to_user_timezone(image.uploaded, profile) \
            if profile else image.uploaded
        if image.published:
            published_on = \
                to_user_timezone(image.published, profile) \
                if profile else image.published

        alias = 'regular'
        mod = self.request.GET.get('mod')
        if mod == 'inverted':
            alias = 'regular_inverted'

        subjects = image.solution.objects_in_field.split(',') if image.solution and image.solution.objects_in_field else ''
        skyplot_zoom1 = None

        if is_revision:
            if revision_image.solution:
                if revision_image.solution.objects_in_field:
                   subjects = revision_image.solution.objects_in_field.split(',')
                if revision_image.solution.skyplot_zoom1:
                    skyplot_zoom1 = revision_image.solution.skyplot_zoom1
        else:
            if image.solution:
                if image.solution.objects_in_field:
                    subjects = image.solution.objects_in_field.split(',')
                if image.solution.skyplot_zoom1:
                    skyplot_zoom1 = image.solution.skyplot_zoom1

        subjects_limit = 5

        licenses = (
            (0, 'cc/c.png',           LICENSE_CHOICES[0][1]),
            (1, 'cc/cc-by-nc-sa.png', LICENSE_CHOICES[1][1]),
            (2, 'cc/cc-by-nc.png',    LICENSE_CHOICES[2][1]),
            (3, 'cc/cc-by-nc-nd.png', LICENSE_CHOICES[3][1]),
            (4, 'cc/cc-by.png',       LICENSE_CHOICES[4][1]),
            (5, 'cc/cc-by-sa.png',    LICENSE_CHOICES[5][1]),
            (6, 'cc/cc-by-nd.png',    LICENSE_CHOICES[6][1]),
        )

        locations = '; '.join([u'%s' % (x) for x in image.locations.all()])


        ######################
        # PREFERRED LANGUAGE #
        ######################

        preferred_language = image.user.userprofile.language
        if preferred_language:
            try:
                preferred_language = LANGUAGES[preferred_language]
            except KeyError:
                preferred_language = _("English")
        else:
            preferred_language = _("English")


        ##########################
        # LIKE / BOOKMARKED THIS #
        ##########################
        like_this = image.toggleproperties.filter(property_type = "like")
        bookmarked_this = image.toggleproperties.filter(property_type = "bookmark")


        ##############
        # NAVIGATION #
        ##############
        image_next = None
        image_prev = None
        try:
            nav_ctx = self.request.GET.get('nc')
            if nav_ctx is None:
                nav_ctx = self.request.session.get('nav_ctx')
            if nav_ctx is None:
                nav_ctx = 'user'

            nav_ctx_extra = self.request.GET.get('nce')
            if nav_ctx_extra is None:
                nav_ctx_extra = self.request.session.get('nav_ctx_extra')

            # Always only lookup public images!
            if nav_ctx == 'user':
                image_next = Image.objects.filter(user = image.user, pk__gt = image.pk).order_by('pk')[0:1]
                image_prev = Image.objects.filter(user = image.user, pk__lt = image.pk).order_by('-pk')[0:1]
            elif nav_ctx == 'collection':
                try:
                    try:
                        collection = image.collections.get(pk = nav_ctx_extra)
                    except ValueError:
                        # Maybe this image is in a single collection
                        collection = image.collections.all()[0]

                    image_next = Image.objects.filter(user = image.user, collections = collection, pk__gt = image.pk).order_by('pk')[0:1]
                    image_prev = Image.objects.filter(user = image.user, collections = collection, pk__lt = image.pk).order_by('-pk')[0:1]
                except Collection.DoesNotExist:
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'group':
                try:
                    group = image.part_of_group_set.get(pk = nav_ctx_extra)
                    if group.public:
                        image_next = Image.objects.filter(part_of_group_set = group, pk__gt = image.pk).order_by('pk')[0:1]
                        image_prev = Image.objects.filter(part_of_group_set = group, pk__lt = image.pk).order_by('-pk')[0:1]
                except Group.DoesNotExist:
                    # image_prev and image_next will remain None
                    pass
            elif nav_ctx == 'all':
                image_next = Image.objects.filter(pk__gt = image.pk).order_by('pk')[0:1]
                image_prev = Image.objects.filter(pk__lt = image.pk).order_by('-pk')[0:1]
            elif nav_ctx == 'iotd':
                try:
                    iotd = Iotd.objects.get(image = image)
                    iotd_next = Iotd.objects.filter(date__gt = iotd.date, date__lte = datetime.now().date()).order_by('date')[0:1]
                    iotd_prev = Iotd.objects.filter(date__lt = iotd.date, date__lte = datetime.now().date()).order_by('-date')[0:1]

                    if iotd_next:
                        image_next = [iotd_next[0].image]
                    if iotd_prev:
                        image_prev = [iotd_prev[0].image]
                except Iotd.DoesNotExist:
                    pass
            elif nav_ctx == 'picks':
                picks = Image.objects.exclude(iotdvote = None).filter(iotd = None)
                image_next = picks.filter(pk__gt = image.pk).order_by('pk')[0:1]
                image_prev = picks.filter(pk__lt = image.pk).order_by('-pk')[0:1]
        except Image.DoesNotExist:
            image_next = None
            image_prev = None

        if image_next:
            image_next = image_next[0]
        if image_prev:
            image_prev = image_prev[0]


        #################
        # RESPONSE DICT #
        #################

        from astrobin_apps_platesolving.solver import Solver

        if skyplot_zoom1 and not skyplot_zoom1.name.startswith('images/'):
                skyplot_zoom1.name = 'images/' + skyplot_zoom1.name

        response_dict = context.copy()
        response_dict.update({
            'SHARE_PATH': settings.SHORT_BASE_URL,

            'alias': alias,
            'mod': mod,
            'revisions': ImageRevision.objects.select_related('image__user__userprofile').filter(image = image),
            'revisions_with_description':
                ImageRevision.objects\
                    .select_related('image__user__userprofile')\
                    .filter(image = image)\
                    .exclude(Q(description = None) | Q(description = '')),
            'is_revision': is_revision,
            'revision_image': revision_image,
            'revision_label': r,

            'instance_to_platesolve': instance_to_platesolve,
            'show_solution': instance_to_platesolve.solution and instance_to_platesolve.solution.status == Solver.SUCCESS,
            'skyplot_zoom1': skyplot_zoom1,

            'image_ct': ContentType.objects.get_for_model(Image),
            'like_this': like_this,
            'user_can_like': can_like(self.request.user, image),
            'bookmarked_this': bookmarked_this,
            'min_index_to_like': settings.MIN_INDEX_TO_LIKE,

            'comments_number': NestedComment.objects.filter(
                deleted = False,
                content_type__app_label = 'astrobin',
                content_type__model = 'image',
                object_id = image.id).count(),
            'gear_list': gear_list,
            'makes_list': makes_list,
            'gear_list_has_commercial': gear_list_has_commercial,
            'gear_list_has_paid_commercial': gear_list_has_paid_commercial,
            'image_type': image_type,
            'ssa': ssa,
            'basic_data': basic_data,
            'deep_sky_data': deep_sky_data,
            # TODO: check that solved image is correcly laid on top
            'private_message_form': PrivateMessageForm(),
            'upload_revision_form': ImageRevisionUploadForm(),
            'dates_label': _("Dates"),
            'published_on': published_on,
            'show_contains': (image.subject_type == 100 and subjects) or (image.subject_type >= 200),
            'subjects_short': subjects[:subjects_limit],
            'subjects_reminder': subjects[subjects_limit:],
            'subjects_all': subjects,
            'subjects_limit': subjects_limit,
            'subject_type': [x[1] for x in Image.SUBJECT_TYPE_CHOICES if x[0] == image.subject_type][0] if image.subject_type else 0,
            'license_icon': static('astrobin/icons/%s' % licenses[image.license][1]),
            'license_title': licenses[image.license][2],
            'locations': locations,
            # Because of a regression introduced at
            # revision e1dad12babe5, now we have to
            # implement this ugly hack.

            'solar_system_main_subject_id': image.solar_system_main_subject,
            'solar_system_main_subject': SOLAR_SYSTEM_SUBJECT_CHOICES[image.solar_system_main_subject][1] if image.solar_system_main_subject is not None else None,
            'content_type': ContentType.objects.get(app_label = 'astrobin', model = 'image'),
            'preferred_language': preferred_language,
            'select_group_form': GroupSelectForm(user = self.request.user) if self.request.user.is_authenticated() else None,
            'in_public_groups': Group.objects.filter(Q(public = True, images = image)),
            'select_datapool_form': PublicDataPool_SelectExistingForm(),
            'select_sharedfolder_form': PrivateSharedFolder_SelectExistingForm(user = self.request.user) if self.request.user.is_authenticated() else None,
            'has_sharedfolders': PrivateSharedFolder.objects.filter(
                Q(creator = self.request.user) |
                Q(users = self.request.user)).count() > 0 if self.request.user.is_authenticated() else False,

            'image_next': image_next,
            'image_prev': image_prev,
            'nav_ctx': nav_ctx,
            'nav_ctx_extra': nav_ctx_extra,
        })

        return response_dict