Exemplo n.º 1
0
def observed_list_chart_legend_img(ra, dec):
    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    if observed_list is None:
        abort(404)

    img_bytes = common_chart_legend_img(None, None, ra, dec, )
    return send_file(img_bytes, mimetype='image/png')
Exemplo n.º 2
0
def observed_list_info():
    """View observed list."""
    add_form = AddToObservedListForm()
    search_form = SearchObservedForm()

    ret, page = process_paginated_session_search('observed_search_page', [
        ('observed_search', search_form.q),
        ('items_per_page', search_form.items_per_page)
    ])

    per_page = get_items_per_page(search_form.items_per_page)

    if not ret:
        return redirect(url_for('main_observed.observed_list_info'))

    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    observed_list_items = observed_list.observed_list_items

    page_offset = (page - 1) * per_page

    if page_offset < len(observed_list_items):
        page_items = observed_list_items[page_offset:page_offset + per_page]
    else:
        page_items = []

    pagination = Pagination(page=page, per_page=per_page, total=len(observed_list.observed_list_items), search=False, record_name='observed',
                            css_framework='semantic', not_passed_args='back')

    return render_template('main/observation/observed_list.html', observed_list=observed_list, type='info', add_form=add_form,
                           search_form=search_form, observed_list_items=enumerate(page_items), page_offset=page_offset, pagination=pagination)
Exemplo n.º 3
0
def observed_list_chart():
    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    if observed_list is None:
        abort(404)

    form  = ChartForm()

    dso_id = request.args.get('dso_id')

    observed_list_item = None
    if dso_id and dso_id.isdigit():
        idso_id = int(dso_id)
        observed_list_item = next((x for x in observed_list.observed_list_items if x.deepskyObject.id == idso_id), None)

    if not observed_list_item:
        observed_list_item = observed_list.observed_list_items[0] if observed_list.observed_list_items else None

    if not common_ra_dec_fsz_from_request(form):
        if form.ra.data is None or form.dec.data is None:
            form.ra.data = observed_list_item.deepskyObject.ra if observed_list_item else 0
            form.dec.data = observed_list_item.deepskyObject.dec if observed_list_item else 0

    chart_control = common_prepare_chart_data(form)

    if observed_list_item:
        default_chart_iframe_url = url_for('main_deepskyobject.deepskyobject_info', back='observedlist', dso_id=observed_list_item.deepskyObject.name, embed='fc', allow_back='true')
    else:
        default_chart_iframe_url = None

    return render_template('main/observation/observed_list.html', fchart_form=form, type='chart', observed_list=observed_list, chart_control=chart_control,
                           default_chart_iframe_url=default_chart_iframe_url,)
Exemplo n.º 4
0
def observed_list_delete():
    """delete observed list."""
    add_form = AddToObservedListForm()
    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    ObservedListItem.query.filter_by(observed_list_id=observed_list.id).delete()
    db.session.commit()
    flash(gettext('Observed list deleted'), 'form-success')
    observed_list_items = enumerate(observed_list.observed_list_items)
    return render_template('main/observation/observed_list.html', observed_list=observed_list, add_form=add_form, observed_list_items=observed_list_items)
Exemplo n.º 5
0
def observed_list_download():
    buf = StringIO()
    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    for observed_item in observed_list.observed_list_items:
        if observed_item.dso_id is not None:
            buf.write(observed_item.deepskyObject.name + '\n')
    mem = BytesIO()
    mem.write(buf.getvalue().encode('utf-8'))
    mem.seek(0)
    return send_file(mem, as_attachment=True,
                     attachment_filename='observed-' + current_user.user_name + '.csv',
                     mimetype='text/csv')
Exemplo n.º 6
0
def session_plan_info(session_plan_id):
    """View a session plan info."""
    session_plan = SessionPlan.query.filter_by(id=session_plan_id).first()
    is_mine_session_plan = _check_session_plan(session_plan, allow_public=True)
    observed = {
        dso.id
        for dso in ObservedList.get_observed_dsos_by_user_id(current_user.id)
    } if not current_user.is_anonymous else None
    return render_template('main/planner/session_plan_info.html',
                           type='info',
                           session_plan=session_plan,
                           is_mine_session_plan=is_mine_session_plan,
                           observed=observed)
Exemplo n.º 7
0
def observed_list_chart_pos_img(ra, dec):
    observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
    if observed_list is None:
        abort(404)

    highlights_dso_list = [ x.deepskyObject for x in observed_list.observed_list_items if observed_list.observed_list_items ]

    flags = request.args.get('json')
    visible_objects = [] if flags else None
    img_bytes = common_chart_pos_img(None, None, ra, dec, visible_objects=visible_objects, highlights_dso_list=highlights_dso_list)
    if visible_objects is not None:
        img = base64.b64encode(img_bytes.read()).decode()
        return jsonify(img=img, img_map=visible_objects)
    else:
        return send_file(img_bytes, mimetype='image/png')
Exemplo n.º 8
0
def observed_list_item_add():
    """Add item to observed list."""
    form = AddToObservedListForm()
    dso_name = normalize_dso_name(form.dso_name.data)
    if request.method == 'POST' and form.validate_on_submit():
        deepsky_object = DeepskyObject.query.filter(DeepskyObject.name==dso_name).first()
        if deepsky_object:
            observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
            dso_id = deepsky_object.master_id if deepsky_object.master_id is not None else deepsky_object.id
            if observed_list.append_deepsky_object(dso_id, current_user.id):
                flash(gettext('Object was added to observed list.'), 'form-success')
            else:
                flash(gettext('Object is already on observed list.'), 'form-info')
        else:
            flash(gettext('Deepsky object not found.'), 'form-error')

    return redirect(url_for('main_observed.observed_list_info'))
Exemplo n.º 9
0
def deepskyobject_switch_observed_list():
    dso_id = request.args.get('dso_id', None, type=int)
    dso, orig_dso = _find_dso(dso_id)
    if dso is None:
        abort(404)
    observed_list = ObservedList.create_get_observed_list_by_user_id(
        current_user.id)
    observed_list_item = ObservedListItem.query.filter_by(
        observed_list_id=observed_list.id, dso_id=dso_id).first()
    if observed_list_item:
        db.session.delete(observed_list_item)
        db.session.commit()
        result = 'off'
    else:
        observed_list.append_new_deepsky_object(dso_id, current_user.id)
        result = 'on'
    return jsonify(result=result)
Exemplo n.º 10
0
def observed_list_upload():
    if 'file' not in request.files:
        flash(gettext('No file part'), 'form-error')
        return redirect(request.url)
    file = request.files['file']
    if file.filename == '':
        flash(gettext('No selected file'))
        return redirect(request.url)
    if file:
        filename = secure_filename(file.filename)
        path = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
        file.save(path)
        with open(path) as csvfile:
            reader = csv.DictReader(csvfile, delimiter=';', fieldnames=['DSO_NAME'])
            observed_list = ObservedList.create_get_observed_list_by_user_id(current_user.id)
            existing_ids = set(item.dso_id for item in observed_list.observed_list_items)
            for row in reader:
                dso_name = row['DSO_NAME']
                if dso_name == 'none':
                    continue
                object_name = dso_name.replace(' ', '')
                dso = DeepskyObject.query.filter_by(name=object_name).first()
                if dso and dso.id not in existing_ids:
                    new_item = ObservedListItem(
                        observed_list_id=observed_list.id,
                        dso_id=dso.id,
                        create_date=datetime.now(),
                        update_date=datetime.now(),
                        )
                    db.session.add(new_item)
                    existing_ids.add(dso.id)
        db.session.commit()
        os.remove(path)
        flash(gettext('Observed list updated.'), 'form-success')

    return redirect(url_for('main_observed.observed_list_info'))
Exemplo n.º 11
0
def constellation_info(constellation_id):
    """View a constellation info."""
    constellation = _find_constellation(constellation_id)
    if constellation is None:
        abort(404)
    user_descr = None
    common_name = None
    dso_descriptions = None
    star_descriptions = None
    title_images = None
    ug_bl_dsos = None
    lang, editor_user = get_lang_and_editor_user_from_request(
        for_constell_descr=True)
    lang_dso, editor_user_dso = get_lang_and_editor_user_from_request(
        for_constell_descr=False)
    cs_editor_user = get_cs_editor_user()

    if editor_user:
        ucd = UserConsDescription.query.filter_by(constellation_id=constellation.id, user_id=editor_user.id, lang_code=lang)\
                .first()

        user_descr = ucd.text if ucd else None
        common_name = ucd.common_name if ucd else None

        star_descriptions = UserStarDescription.query.filter_by(user_id=editor_user.id, lang_code=lang)\
                                                     .filter_by(constellation_id=constellation.id) \
                                                     .all()
        star_descriptions = _sort_star_descr(star_descriptions)

        all_cs_dso_descriptions = UserDsoDescription.query.filter_by(user_id=cs_editor_user.id, lang_code='cs')\
                                                          .join(UserDsoDescription.deepskyObject, aliased=True) \
                                                          .filter(DeepskyObject.constellation_id == constellation.id, DeepskyObject.type != 'AST') \
                                                          .order_by(UserDsoDescription.rating.desc(), DeepskyObject.mag) \
                                                          .all()

        if lang != 'cs':
            # Show all objects that are in CS version plus UG-BL objects
            existing = set(dsod.dso_id for dsod in all_cs_dso_descriptions)
            all_dso_descriptions = []
            available_dso_descriptions = UserDsoDescription.query.filter_by(user_id=editor_user_dso.id, lang_code=lang)\
                                                                 .join(UserDsoDescription.deepskyObject, aliased=True) \
                                                                 .filter(DeepskyObject.constellation_id == constellation.id, DeepskyObject.type != 'AST') \
                                                                 .order_by(UserDsoDescription.rating.desc(), DeepskyObject.mag) \
                                                                 .all()

            available_dso_descriptions_map = {}

            for dsod in available_dso_descriptions:
                available_dso_descriptions_map[dsod.dso_id] = dsod
                if dsod.dso_id in existing:
                    all_dso_descriptions.append(dsod)
                elif dsod.deepskyObject.mag < 10.0:
                    all_dso_descriptions.append(dsod)
                    existing.add(dsod.dso_id)

            constell_ug_bl_dsos = get_ug_bl_dsos()[constellation.id]
            for dso_id in constell_ug_bl_dsos:
                dso = constell_ug_bl_dsos[dso_id]
                loading_dso_id = dso.master_id if dso.master_id is not None else dso_id
                if not dso_id in existing and loading_dso_id in available_dso_descriptions_map:
                    all_dso_descriptions.append(
                        available_dso_descriptions_map[loading_dso_id])

        else:
            all_dso_descriptions = all_cs_dso_descriptions

        existing = set()
        dso_descriptions = []
        title_images = {}
        for dsod in all_dso_descriptions:
            if dsod.dso_id not in existing:
                existing.add(dsod.dso_id)
                dso_descriptions.append(dsod)
            if not dsod.text or not dsod.text.startswith('![<]($IMG_DIR/'):
                image_info = get_dso_image_info_with_imgdir(
                    dsod.deepskyObject.normalized_name_for_img())
                if image_info is not None:
                    title_images[dsod.dso_id] = image_info[0]

        dso_apert_descriptions = UserDsoApertureDescription.query.filter_by(user_id=editor_user_dso.id, lang_code=lang)\
                                                                 .join(UserDsoApertureDescription.deepskyObject, aliased=True) \
                                                                 .filter_by(constellation_id=constellation.id) \
                                                                 .order_by(UserDsoApertureDescription.aperture_class, UserDsoApertureDescription.lang_code) \
                                                                 .all()

        aperture_descr_map = {}
        for apdescr in dso_apert_descriptions:
            if apdescr.dso_id not in aperture_descr_map:
                aperture_descr_map[apdescr.dso_id] = []
            dsoapd = aperture_descr_map[apdescr.dso_id]
            if apdescr.aperture_class not in [cl[0] for cl in dsoapd
                                              ] and apdescr.text:
                if apdescr.aperture_class == '<100':
                    dsoapd.insert(0, (apdescr.aperture_class, apdescr.text))
                else:
                    dsoapd.append((apdescr.aperture_class, apdescr.text))

        ug_bl_dsos = []
        constell_ug_bl_dsos = get_ug_bl_dsos()[constellation.id]
        for dso_id in constell_ug_bl_dsos:
            if dso_id not in existing:
                dso = constell_ug_bl_dsos[dso_id]
                if dso.master_id not in existing:
                    dso_image_info = get_dso_image_info(
                        dso.normalized_name_for_img())
                    ug_bl_dsos.append({'dso': dso, 'img_info': dso_image_info})

        ug_bl_dsos.sort(key=lambda x: x['dso'].mag)
    editable = current_user.is_editor()

    wish_list = None
    observed_list = None
    if current_user.is_authenticated:
        wish_list = [
            item.dso_id for item in WishList.create_get_wishlist_by_user_id(
                current_user.id).wish_list_items
        ]
        observed_list = [
            item.dso_id
            for item in ObservedList.create_get_observed_list_by_user_id(
                current_user.id).observed_list_items
        ]

    return render_template(
        'main/catalogue/constellation_info.html',
        constellation=constellation,
        type='info',
        user_descr=user_descr,
        common_name=common_name,
        star_descriptions=star_descriptions,
        dso_descriptions=dso_descriptions,
        aperture_descr_map=aperture_descr_map,
        editable=editable,
        ug_bl_dsos=ug_bl_dsos,
        wish_list=wish_list,
        observed_list=observed_list,
        title_images=title_images,
    )
Exemplo n.º 12
0
def _get_prev_next_dso(dso):
    back = request.args.get('back')
    back_id = request.args.get('back_id')

    has_item = False
    next_item = None

    if back == 'observation':
        observing_session = ObservingSession.query.filter_by(
            id=back_id).first()
        if observing_session and (observing_session.is_public
                                  or observing_session.user_id
                                  == current_user.id):
            prev_item, next_item = observing_session.get_prev_next_item(dso.id)
            return (
                prev_item,
                prev_item.denormalized_name() if prev_item else None,
                next_item,
                next_item.denormalized_name() if next_item else None,
            )
    elif back == 'stobservation':
        pass
    elif back == 'constell_dso':
        constell_dsos = DeepskyObject.query.filter_by(constellation_id=dso.constellation_id, master_id=None) \
                                           .order_by(DeepskyObject.mag) \
                                           .all()
        num_dsos = len(constell_dsos)
        for dso_idx in range(num_dsos):
            constell_dso = constell_dsos[dso_idx]
            if constell_dso.id == dso.id:
                prev_item, next_item = None, None
                if dso_idx > 0:
                    prev_item = constell_dsos[dso_idx - 1]
                if dso_idx < num_dsos - 1:
                    next_item = constell_dsos[dso_idx + 1]
                return (
                    prev_item,
                    prev_item.denormalized_name() if prev_item else None,
                    next_item,
                    next_item.denormalized_name() if next_item else None,
                )
    elif back == 'wishlist':
        if current_user.is_authenticated:
            wish_list = WishList.create_get_wishlist_by_user_id(
                current_user.id)
            prev_item, next_item = wish_list.get_prev_next_item(
                dso.id, _get_season_constell_ids())
            has_item = True
    elif back == 'observed_list':
        if current_user.is_authenticated:
            observed_list = ObservedList.create_get_observed_list_by_user_id(
                current_user.id)
            prev_item, next_item = observed_list.get_prev_next_item(
                dso.id, _get_season_constell_ids())
            has_item = True
    elif back == 'session_plan':
        session_plan = SessionPlan.query.filter_by(id=back_id).first()
        if _allow_view_session_plan(session_plan):
            prev_item, next_item = session_plan.get_prev_next_item(
                dso.id, _get_season_constell_ids())
            has_item = True
    elif back == 'dso_list' and not (back_id is None):
        dso_list = DsoList.query.filter_by(id=back_id).first()
        if dso_list:
            prev_item, next_item = dso_list.get_prev_next_item(
                dso.id, _get_season_constell_ids())
            return (
                prev_item.deepskyObject if prev_item else None,
                prev_item.item_id if prev_item else None,
                next_item.deepskyObject if next_item else None,
                next_item.item_id if next_item else None,
            )
    elif back == 'running_plan':
        observation_plan_run = ObsSessionPlanRun.query.filter_by(
            id=back_id).first()
        if observation_plan_run and _allow_view_session_plan(
                observation_plan_run.session_plan):
            prev_item, next_item = observation_plan_run.session_plan.get_prev_next_item(
                dso.id, _get_season_constell_ids())
            has_item = True

    if has_item:
        return (
            prev_item.deepskyObject if prev_item else None,
            prev_item.deepskyObject.denormalized_name() if prev_item else None,
            next_item.deepskyObject if next_item else None,
            next_item.deepskyObject.denormalized_name() if next_item else None,
        )

    prev_dso, next_dso = dso.get_prev_next_dso()
    return (prev_dso, prev_dso.catalog_number() if prev_dso else None,
            next_dso, next_dso.catalog_number() if next_dso else None)
Exemplo n.º 13
0
def deepskyobjects():
    """View deepsky objects."""
    search_form = SearchDsoForm()

    sort_by = request.args.get('sortby')

    ret, page = process_paginated_session_search(
        'dso_search_page', [('dso_search', search_form.q),
                            ('dso_type', search_form.dso_type),
                            ('dso_catal', search_form.catalogue),
                            ('dso_maglim', search_form.maglim),
                            ('items_per_page', search_form.items_per_page)])

    if not ret:
        return redirect(
            url_for('main_deepskyobject.deepskyobjects',
                    page=page,
                    sortby=sort_by))

    per_page = get_items_per_page(search_form.items_per_page)

    offset = (page - 1) * per_page

    dso_query = DeepskyObject.query
    if search_form.q.data:
        dso_query = dso_query.filter(
            DeepskyObject.name.like('%' +
                                    normalize_dso_name(search_form.q.data) +
                                    '%'))

    mag_scale = (8, 16)

    if search_form.dso_type.data and search_form.dso_type.data != 'All':
        dso_query = dso_query.filter(
            DeepskyObject.type == search_form.dso_type.data)

    if search_form.catalogue.data and search_form.catalogue.data != 'All':
        cat_id = Catalogue.get_catalogue_id_by_cat_code(
            search_form.catalogue.data)
        if cat_id:
            dso_query = dso_query.filter_by(catalogue_id=cat_id)

    if not search_form.q.data and search_form.maglim.data is not None and search_form.maglim.data < mag_scale[
            1]:
        dso_query = dso_query.filter(
            DeepskyObject.mag < search_form.maglim.data)

    sort_def = {
        'name': DeepskyObject.name,
        'type': DeepskyObject.type,
        'ra': DeepskyObject.ra,
        'dec': DeepskyObject.dec,
        'constellation': DeepskyObject.constellation_id,
        'mag': DeepskyObject.mag,
    }

    table_sort = create_table_sort(sort_by, sort_def.keys())

    order_by_field = None
    if sort_by:
        desc = sort_by[0] == '-'
        sort_by_name = sort_by[1:] if desc else sort_by
        order_by_field = sort_def.get(sort_by_name)
        if order_by_field and desc:
            order_by_field = order_by_field.desc()

    if order_by_field is None:
        order_by_field = DeepskyObject.id

    shown_dsos = dso_query.order_by(order_by_field).limit(per_page).offset(
        offset).all()

    observed = set()
    if not current_user.is_anonymous:
        for dso in ObservedList.get_observed_dsos_by_user_id(current_user.id):
            observed.add(dso.id)

    pagination = Pagination(page=page,
                            per_page=per_page,
                            total=dso_query.count(),
                            search=False,
                            record_name='deepskyobjects',
                            css_framework='semantic',
                            not_passed_args='back')

    return render_template('main/catalogue/deepskyobjects.html',
                           deepskyobjects=shown_dsos,
                           mag_scale=mag_scale,
                           pagination=pagination,
                           search_form=search_form,
                           table_sort=table_sort,
                           observed=observed)
Exemplo n.º 14
0
def deepskyobject_chart_pos_img(dso_id, ra, dec):
    dso, orig_dso = _find_dso(dso_id)
    if dso is None:
        abort(404)

    flags = request.args.get('json')
    visible_objects = [] if flags else None

    highlights_dso_list = None

    back = request.args.get('back')
    back_id = request.args.get('back_id')

    if back == 'dso_list' and back_id is not None:
        dso_list = DsoList.query.filter_by(id=back_id).first()
        if dso_list:
            highlights_dso_list = [
                x.deepskyObject for x in dso_list.dso_list_items if dso_list
            ]
    elif back == 'wishlist' and current_user.is_authenticated:
        wish_list = WishList.create_get_wishlist_by_user_id(current_user.id)
        highlights_dso_list = [
            x.deepskyObject for x in wish_list.wish_list_items
            if wish_list.wish_list_items
        ]
    elif back == 'session_plan':
        session_plan = SessionPlan.query.filter_by(id=back_id).first()
        if _allow_view_session_plan(session_plan):
            highlights_dso_list = [
                x.deepskyObject for x in session_plan.session_plan_items
                if session_plan
            ]
    elif back == 'observation':
        observing_session = ObservingSession.query.filter_by(
            id=back_id).first()
        if observing_session and (observing_session.is_public
                                  or observing_session.user_id
                                  == current_user.id):
            highlights_dso_list = []
            for observation in observing_session.observations:
                highlights_dso_list.extend(observation.deepsky_objects)
    elif back == 'observed_list' and current_user.is_authenticated:
        observed_list = ObservedList.create_get_observed_list_by_user_id(
            current_user.id)
        highlights_dso_list = [
            x.deepskyObject for x in observed_list.observed_list_items
            if observed_list.observed_list_items
        ]
    elif back == 'running_plan' and back_id is not None:
        observation_plan_run = ObsSessionPlanRun.query.filter_by(
            id=back_id).first()
        if observation_plan_run and _allow_view_session_plan(
                observation_plan_run.session_plan):
            highlights_dso_list = [
                x.deepskyObject
                for x in observation_plan_run.session_plan.session_plan_items
            ]

    img_bytes = common_chart_pos_img(dso.ra,
                                     dso.dec,
                                     ra,
                                     dec,
                                     dso_names=(dso.name, ),
                                     visible_objects=visible_objects,
                                     highlights_dso_list=highlights_dso_list)

    if visible_objects is not None:
        img = base64.b64encode(img_bytes.read()).decode()
        return jsonify(img=img, img_map=visible_objects)
    else:
        return send_file(img_bytes, mimetype='image/png')
Exemplo n.º 15
0
def dso_list_info(dso_list_id):
    """View a dso list info."""
    dso_list = _find_dso_list(dso_list_id)
    if dso_list is None:
        abort(404)

    search_form = SearchDsoListForm()
    if search_form.season.data == 'All':
        search_form.season.data = None

    if not process_session_search([
        ('dso_list_season', search_form.season),
    ]):
        return redirect(
            url_for('main_dso_list.dso_list_info',
                    dso_list_id=dso_list_id,
                    season=search_form.season.data))

    season = request.args.get('season', None)

    lang, editor_user = get_lang_and_editor_user_from_request(
        for_constell_descr=False)

    if season:
        constell_ids = set()
        for constell_id in db.session.query(
                Constellation.id).filter(Constellation.season == season):
            constell_ids.add(constell_id[0])
    else:
        constell_ids = None

    dso_list_descr = DsoListDescription.query.filter_by(
        dso_list_id=dso_list.id, lang_code=lang).first()

    observed = {
        dso.id
        for dso in ObservedList.get_observed_dsos_by_user_id(current_user.id)
    } if not current_user.is_anonymous else None

    user_descrs = {} if dso_list.show_descr_name else None
    dso_list_items = []
    for dso_list_item in dso_list.dso_list_items:
        if constell_ids is None or dso_list_item.deepskyObject.constellation_id in constell_ids:
            dso_list_items.append(dso_list_item)
            if user_descrs is not None:
                udd = UserDsoDescription.query.filter_by(
                    dso_id=dso_list_item.dso_id,
                    user_id=editor_user.id,
                    lang_code=lang).first()
                if udd and udd.common_name:
                    user_descrs[dso_list_item.dso_id] = udd.common_name
                else:
                    user_descrs[dso_list_item.
                                dso_id] = dso_list_item.deepskyObject.name

    theme = request.args.get('theme', '')
    inverted_accordion = theme in ['dark', 'night']

    return render_template('main/catalogue/dso_list_info.html',
                           dso_list=dso_list,
                           type='info',
                           dso_list_descr=dso_list_descr,
                           dso_list_items=dso_list_items,
                           user_descrs=user_descrs,
                           season=season,
                           search_form=search_form,
                           inverted_accordion=inverted_accordion,
                           observed=observed)