Esempio n. 1
0
def PrjEditPriv(PrjId):
    Prj=database.Projects.query.filter_by(projid=PrjId).first()
    g.headcenter="<h4><a href='/prj/{0}'>{1}</a></h4>".format(Prj.projid,XSSEscape(Prj.title))
    if Prj is None:
        flash("Project doesn't exists",'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not Prj.CheckRight(2): # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot edit settings for this project','error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")

    if gvp('save')=="Y":
        # print(request.form)
        for m in Prj.projmembers:
            if gvp('priv_%s_delete'%m.id)=='Y':
                db.session.delete(m)
            elif gvp('priv_%s_member'%m.id)!='': # si pas delete c'est update
                m.member=int(gvp('priv_%s_member'%m.id))
                m.privilege=gvp('priv_%s_privilege'%m.id)
        if gvp('priv_new_member')!='':
            new=database.ProjectsPriv(member=int(gvp('priv_new_member')),privilege=gvp('priv_new_privilege'),projid=PrjId)
            db.session.add(new)
        try:
            db.session.commit()
            flash("Project settings Saved successfuly","success")
        except Exception as E:
            flash("Database exception : %s"%E,"error")
            db.session.rollback()

    g.users=GetAssoc2Col("select id,name from users order by lower(name)",dicttype=collections.OrderedDict)
    return render_template('project/editprojectpriv.html',data=Prj)
Esempio n. 2
0
def PrjEdit(PrjId):
    g.useselect4 = True
    Prj = database.Projects.query.filter_by(projid=PrjId).first()
    g.headcenter = "<h4><a href='/prj/{0}'>{1}</a></h4>".format(
        Prj.projid, XSSEscape(Prj.title))
    if Prj is None:
        flash("Project doesn't exists", 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not Prj.CheckRight(2):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot edit settings for this project', 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")

    if gvp('save') == "Y":
        PreviousCNN = Prj.cnn_network_id
        for f in request.form:
            if f in dir(Prj):
                setattr(Prj, f, gvp(f))
        if PreviousCNN != Prj.cnn_network_id:
            database.ExecSQL(
                "delete from obj_cnn_features where objcnnid in (select objid from obj_head where projid=%s)",
                [PrjId])
            flash("SCN features erased", "success")
        Prj.visible = True if gvp('visible') == 'Y' else False
        # print(request.form)
        for m in Prj.projmembers:
            if gvp('priv_%s_delete' % m.id) == 'Y':
                db.session.delete(m)
            elif gvp('priv_%s_member' %
                     m.id) != '':  # si pas delete c'est update
                m.member = int(gvp('priv_%s_member' % m.id))
                m.privilege = gvp('priv_%s_privilege' % m.id)
        if gvp('priv_new_member') != '':
            new = database.ProjectsPriv(member=int(gvp('priv_new_member')),
                                        privilege=gvp('priv_new_privilege'),
                                        projid=PrjId)
            db.session.add(new)
        try:
            db.session.commit()
            flash("Project settings Saved successfuly", "success")
        except Exception as E:
            flash("Database exception : %s" % E, "error")
            db.session.rollback()

    if Prj.initclassiflist is None:
        lst = []
    else:
        lst = [int(x) for x in Prj.initclassiflist.split(",") if x.isdigit()]

    g.predeftaxo = GetAll(
        """select t.id,t.display_name as name
        from taxonomy t
        left join taxonomy t2 on t.parent_id=t2.id
        where t.id= any(%s) order by upper(t.display_name) """, (lst, ))
    g.users = GetAssoc2Col("select id,name from users order by lower(name)",
                           dicttype=collections.OrderedDict)
    g.maplist = [
        'objtime', 'objdate', 'latitude', 'longitude', 'depth_min', 'depth_max'
    ] + sorted(DecodeEqualList(Prj.mappingobj).values())
    g.scn = GetSCNNetworks()
    return render_template('project/editproject.html', data=Prj)
Esempio n. 3
0
def TaskMonitor(TaskID):
    AddTaskSummaryForTemplate()
    try:
        task = LoadTask(TaskID)
        ProjectID = getattr(task.param, 'ProjectId', None)
        if ProjectID:
            Prj = database.Projects.query.filter_by(projid=ProjectID).first()
            g.headcenter = "<h4>Project : <a href='/prj/{0}'>{1}</a></h4>".format(
                Prj.projid, XSSEscape(Prj.title))
        return render_template('task/monitor.html', TaskID=task.task.id)
    except:
        return PrintInCharte(
            "This task doesn't exists anymore, peraphs it was automaticaly purged"
        )
Esempio n. 4
0
def TaskShow(TaskID):
    AddTaskSummaryForTemplate()
    try:
        task = LoadTask(TaskID)
    except:
        return PrintInCharte(
            "This task doesn't exists anymore, peraphs it was automaticaly purged"
        )

    txt = ""
    if gvg('log') == "Y":
        WorkingDir = task.GetWorkingDir()
        # app.send_static_file(os.path.join(WorkingDir,"TaskLog.txt"))
        return flask.send_from_directory(WorkingDir, "TaskLog.txt")
    if gvg('CustomDetails') == "Y":
        return task.ShowCustomDetails()
    if "GetResultFile" in dir(task):
        f = task.GetResultFile()
        if f is None:
            txt += "Error, final file not available"
        else:
            txt += "<a href='/Task/GetFile/%d/%s' class='btn btn-primary btn-sm ' role='button'>Get file %s</a>" % (
                TaskID, f, f)

    CustomDetailsAvail = "ShowCustomDetails" in dir(task)
    try:
        decodedsteperrors = json.loads(task.task.inputparam).get("steperrors")
    except:
        decodedsteperrors = ["Task Decoding Error"]
    ProjectID = getattr(task.param, 'ProjectId', None)
    if ProjectID:
        Prj = database.Projects.query.filter_by(projid=ProjectID).first()
        g.headcenter = "<h4>Project : <a href='/prj/{0}'>{1}</a></h4>".format(
            Prj.projid, XSSEscape(Prj.title))
    return render_template('task/show.html',
                           task=task.task,
                           steperror=decodedsteperrors,
                           CustomDetailsAvail=CustomDetailsAvail,
                           extratext=txt)
Esempio n. 5
0
 def StartTask(self,
               param=None,
               step=1,
               FileToSave=None,
               FileToSaveFileName=None):
     if param is not None:
         self.task.inputparam = json.dumps(param.__dict__)
     self.task.taskstep = step
     self.task.taskstate = "Running"
     if self.task.id is None:
         db.session.add(self.task)
     db.session.commit()
     workingdir = self.GetWorkingDir()
     if not os.path.exists(workingdir):
         os.mkdir(workingdir)
     if FileToSave is not None:
         FileToSave.save(
             os.path.join(self.GetWorkingDir(), FileToSaveFileName))
     # cmd=os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../runtask.py"))
     cmdfull = app.PythonExecutable + " " + os.path.normpath(
         os.path.join(os.path.dirname(os.path.realpath(__file__)),
                      "../../runtask.py " + str(self.task.id)))
     app.logger.info("Start Task process : %s" % (cmdfull, ))
     # os.spawnv(os.P_NOWAIT,  sys.executable, (sys.executable,cmd, str(self.task.id))) # Ne marche pas
     # system marche, mais c'est un appel bloquant donc on le met dans une thread separé
     # avec uwsgi il faut specifier l'option close-on-exec=true dans uwsgi.ini sinon c'est un appel bloquant.
     import _thread
     _thread.start_new_thread(os.system, (cmdfull, ))
     flash("Taks %d subprocess Created " % (self.task.id, ), "success")
     ProjectID = getattr(self.param, 'ProjectId', None)
     if ProjectID:
         Prj = database.Projects.query.filter_by(projid=ProjectID).first()
         g.headcenter = "<h4>Project : <a href='/prj/{0}'>{1}</a></h4>".format(
             Prj.projid, XSSEscape(Prj.title))
     return render_template('task/monitor.html',
                            TaskID=self.task.id,
                            RedirectToMonitor=True)
Esempio n. 6
0
def GetAll(sql,
           params=None,
           debug=False,
           cursor_factory=psycopg2.extras.DictCursor,
           doXSSEscape=False):
    if g.db is None:
        g.db = db.engine.raw_connection()
    if doXSSEscape:
        cursor_factory = psycopg2.extras.RealDictCursor
    cur = g.db.cursor(cursor_factory=cursor_factory)
    try:
        starttime = datetime.datetime.now()
        cur.execute(sql, params)
        res = cur.fetchall()
        if doXSSEscape:
            for rid, row in enumerate(res):
                for k, v in row.items():
                    if isinstance(v, str):
                        res[rid][k] = XSSEscape(v)
    except psycopg2.InterfaceError:
        app.logger.debug(
            "Connection was invalidated!, Try to reconnect for next HTTP request"
        )
        db.engine.connect()
        raise
    except:
        app.logger.debug("GetAll Exception SQL = %s %s", sql, params)
        cur.connection.rollback()
        raise
    finally:
        if debug or GlobalDebugSQL:
            app.logger.debug("GetAll (%s) SQL = %s %s",
                             (datetime.datetime.now() -
                              starttime).total_seconds(), sql, params)
        cur.close()
    return res
Esempio n. 7
0
def PrjMerge(PrjId):
    Prj = database.Projects.query.filter_by(projid=PrjId).first()
    if Prj is None:
        flash("Project doesn't exists", 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not Prj.CheckRight(2):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot edit settings for this project', 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    g.headcenter = "<h4><a href='/prj/{0}'>{1}</a></h4>".format(
        Prj.projid, XSSEscape(Prj.title))
    txt = "<h3>Project Merge / Fusion </h3>"

    if not gvg('src'):
        txt += """<ul><li>You are allowed to merge projects that you are allowed to manage
<li>User privileges from both projects will be added
<li>This tool allow to merge two projects in a single projet (called Current project). The added project will then be automatically deleted. If object data are not consistent between both projects :
<ul><li>New data fields are added to the Current project
    <li>The resulting project will thus contain partially documented datafields.
</ul><li>Note : Next screen will indicate compatibility issues (if exists) and allow you to Confirm the merging operation.
</ul>
                """
        sql = "select p.projid,title,status,coalesce(objcount,0) objcount,coalesce(pctvalidated,0) pctvalidated,coalesce(pctclassified,0) pctclassified from projects p"
        if not current_user.has_role(database.AdministratorLabel):
            sql += " Join projectspriv pp on p.projid = pp.projid and pp.member=%d" % (
                current_user.id, )
        sql += " where p.projid!=%d order by title" % Prj.projid
        res = GetAll(sql, doXSSEscape=True)  #,debug=True
        txt += """<table class='table table-bordered table-hover table-verycondensed'>
                <tr><th width=120>ID</td><th>Title</td><th width=100>Status</th><th width=100>Nbr Obj</th>
            <th width=100>% Validated</th><th width=100>% Classified</th></tr>"""
        for r in res:
            txt += """<tr><td><a class="btn btn-primary" href='/prj/merge/{activeproject}?src={projid}'>Select</a> {projid}</td>
            <td>{title}</td>
            <td>{status}</td>
            <td>{objcount:0.0f}</td>
            <td>{pctvalidated:0.2f}</td>
            <td>{pctclassified:0.2f}</td>
            </tr>""".format(activeproject=Prj.projid, **r)
        txt += "</table>"
        return PrintInCharte(txt)

    PrjSrc = database.Projects.query.filter_by(projid=int(gvg('src'))).first()
    if PrjSrc is None:
        flash("Source project doesn't exists", 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not PrjSrc.CheckRight(2):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot merge for this project', 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    txt += """<h4>Source Project : {0} - {1} (This project will be destroyed)</h4>
            """.format(PrjSrc.projid, XSSEscape(PrjSrc.title))
    if not gvg('merge'):  # Ici la src à été choisie et vérifiée
        if PrjSrc.mappingobj != Prj.mappingobj:
            flash("Object mapping differ With source project ", "warning")
        if PrjSrc.mappingsample != Prj.mappingsample:
            flash("Sample mapping differ With source project ", "warning")
        if PrjSrc.mappingacq != Prj.mappingacq:
            flash("Acquisition mapping differ With source project ", "warning")
        if PrjSrc.mappingprocess != Prj.mappingprocess:
            flash("Process mapping differ With source project ", "warning")
        txt += FormatError(
            """ <span class='glyphicon glyphicon-warning-sign'></span>
        Warning project {1} - {2}<br>
        Will be destroyed, its content will be transfered in the target project.<br>
        This operation is irreversible</p>
        <br><a class='btn btn-lg btn-warning' href='/prj/merge/{0}?src={1}&merge=Y'>Start Project Fusion</a>        
        """,
            Prj.projid,
            PrjSrc.projid,
            XSSEscape(PrjSrc.title),
            DoNotEscape=True)
        return PrintInCharte(txt)

    if gvg('merge') == 'Y':
        ExecSQL("update acquisitions set projid={0} where projid={1}".format(
            Prj.projid, PrjSrc.projid))
        ExecSQL("update process set projid={0} where projid={1}".format(
            Prj.projid, PrjSrc.projid))
        ExecSQL("update samples set projid={0} where projid={1}".format(
            Prj.projid, PrjSrc.projid))
        ExecSQL("update obj_head set projid={0} where projid={1}".format(
            Prj.projid, PrjSrc.projid))
        ExecSQL("update part_projects set projid={0} where projid={1}".format(
            Prj.projid, PrjSrc.projid))
        # garde le privilege le plus elevé des 2 projets
        ExecSQL("""UPDATE projectspriv ppdst
                  set privilege=case when 'Manage' in (ppsrc.privilege,ppdst.privilege) then 'Manage'
                        when 'Annotate' in (ppsrc.privilege,ppdst.privilege) then 'Annotate'
                        else 'View' end
                from projectspriv  ppsrc
                where ppsrc.projid={1} and ppdst.projid={0} and ppsrc.member=ppdst.member"""
                .format(Prj.projid, PrjSrc.projid),
                debug=True)
        # Transfere les privilege depuis le projet source
        ExecSQL("""update projectspriv
                set projid={0}
                where projid={1} and member not in (select member from projectspriv where projid={0})"""
                .format(Prj.projid, PrjSrc.projid))
        # Efface ceux qui etait des 2 cotés
        ExecSQL("delete from projectspriv where projid={0}".format(
            PrjSrc.projid))
        ExecSQL("delete from projects where projid={0}".format(PrjSrc.projid))
        appli.project.main.RecalcProjectTaxoStat(Prj.projid)
        appli.project.main.UpdateProjectStat(Prj.projid)

        txt += "<div class='alert alert-success' role='alert'>Fusion Done successfully</div>"
        txt += "<br><a class='btn btn-lg btn-primary' href='/prj/%s'>Back to target project</a>" % Prj.projid
        return PrintInCharte(txt)
Esempio n. 8
0
def ExploreLoadRightPane():
    # récupération des parametres d'affichage
    Filt = {}
    for k, v in FilterList.items():
        Filt[k] = gvp(k, v)
    ipp = int(Filt["ipp"])
    zoom = int(Filt["zoom"])
    t = ["<a name='toppage'/>"]
    sqlparam = {'projid': gvp("projid")}
    #     sql="""select o.objid,t.name taxoname,o.classif_qual,u.name classifwhoname,i.file_name
    #   ,i.height,i.width,i.thumb_file_name,i.thumb_height,i.thumb_width
    #   ,o.depth_min,o.depth_max,s.orig_id samplename,o.objdate,to_char(o.objtime,'HH24:MI') objtime
    #   ,o.latitude,o.orig_id,o.imgcount
    #    from objects o
    # left Join images i on o.img0id=i.imgid
    # left JOIN taxonomy t on o.classif_id=t.id
    # LEFT JOIN users u on o.classif_who=u.id
    # LEFT JOIN  samples s on o.sampleid=s.sampleid
    # where o.classif_qual='V'
    # """
    whereclause = ""
    sql = """select o.objid,o.classif_qual  ,o.objdate,to_char(o.objtime,'HH24:MI') objtime
  ,o.imgcount,o.img0id,o.classif_id,o.classif_who,o.sampleid,random_value,o.projid
   from obj_head o
where o.classif_qual='V'
"""
    if gvp("taxo[]"):
        taxoids = ",".join(
            (str(int(x)) for x in request.form.getlist("taxo[]")))
        if gvp("taxochild") == "1":
            # whereclause+=""" and o.classif_id in (WITH RECURSIVE rq(id) as ( select id FROM taxonomy where id in(%s)
            #                         union
            #                         SELECT t.id FROM rq JOIN taxonomy t ON rq.id = t.parent_id and (t.nbrobjcum>0 or t.nbrobj>0)
            #                         ) select id from rq)"""%(taxoids,)
            # Sur les petits nombres de ref le in est plus performant que la sous requete
            taxoids = ",".join((str(int(x[0])) for x in GetAll(
                """WITH RECURSIVE rq(id) as ( select id FROM taxonomy where id in(%s)
                                    union
                                    SELECT t.id FROM rq JOIN taxonomy t ON rq.id = t.parent_id 
                                    ) select id from rq """ % (taxoids, ))))
            whereclause += " and o.classif_id in (" + taxoids + ")"  # optimisation qui provoque de faux résultats : and (t.nbrobjcum>0 or t.nbrobj>0)
        else:
            whereclause += " and o.classif_id in (" + taxoids + ")"

    if gvp("MapN") != "" and gvp("MapW") != "" and gvp("MapE") != "" and gvp(
            "MapS") != "":
        whereclause += " and o.latitude between %(MapS)s and %(MapN)s and o.longitude between %(MapW)s and %(MapE)s  "
        sqlparam['MapN'] = gvp("MapN")
        sqlparam['MapW'] = gvp("MapW")
        sqlparam['MapE'] = gvp("MapE")
        sqlparam['MapS'] = gvp("MapS")

    if gvp("depthmin") != "" and gvp("depthmax") != "":
        whereclause += " and o.depth_min between %(depthmin)s and %(depthmax)s and o.depth_max between %(depthmin)s and %(depthmax)s  "
        sqlparam['depthmin'] = gvp("depthmin")
        sqlparam['depthmax'] = gvp("depthmax")

    if gvp("samples") != "":
        whereclause += " and o.sampleid= any (%(samples)s) "
        sqlparam['samples'] = [int(x) for x in gvp("samples").split(',')]

    if gvp("instrum") != "":
        whereclause += " and o.acquisid in (select acquisid  from acquisitions  where instrument ilike %(instrum)s " + (
            "and projid= any (%(projid)s)"
            if gvp("projid") != "" else "") + " )"
        sqlparam['instrum'] = '%' + gvp("instrum") + '%'
    PageTopProjectLink = MapForProject = None
    if gvp("projid") != "":
        whereclause += " and o.projid= any (%(projid)s) "
        sqlparam['projid'] = [int(x) for x in gvp("projid").split(',')]
        if len(sqlparam['projid']) == 1:
            PageTopProjectLink = "<p class='bg-info' style='font-size: larger;font-weight: bold;'>You can explore this project in more details on its <a href='/prj/{0}'>dedicated page</a></p>".format(
                str(sqlparam['projid'][0]))
    if gvp("fromdate") != "":
        whereclause += " and o.objdate>= to_date(%(fromdate)s,'YYYY-MM-DD') "
        sqlparam['fromdate'] = gvp("fromdate")
    if gvp("todate") != "":
        whereclause += " and o.objdate<= to_date(%(todate)s,'YYYY-MM-DD') "
        sqlparam['todate'] = gvp("todate")
    if gvp("month") != "":
        whereclause += " and extract(month from o.objdate) = any (%(month)s) "
        sqlparam['month'] = [int(x) for x in gvp("month").split(',')]
    if gvp("daytime") != "":
        whereclause += " and o.sunpos= any (%(daytime)s) "
        sqlparam['daytime'] = [x for x in gvp("daytime").split(',')]

    if gvp("inverttime") == "1":
        if gvp("fromtime") != "" and gvp("totime") != "":
            whereclause += " and (o.objtime<= time %(fromtime)s or o.objtime>= time %(totime)s)"
            sqlparam['fromtime'] = gvp("fromtime")
            sqlparam['totime'] = gvp("totime")
    else:
        if gvp("fromtime") != "":
            whereclause += " and o.objtime>= time %(fromtime)s "
            sqlparam['fromtime'] = gvp("fromtime")
        if gvp("totime") != "":
            whereclause += " and objtime<= time %(totime)s "
            sqlparam['totime'] = gvp("totime")
    sql += whereclause
    ExtraEndScript = ""
    if whereclause == "":  # si aucune clause, on prend un projet au hasard
        randomproject = GetAll(
            "select projid,title from projects where visible=true and pctvalidated>1 order by random() limit 1"
        )
        if randomproject:
            randomproject = randomproject[0]
            MapForProject = str(randomproject[0])
            sql += " and o.projid= %s " % (randomproject[0])
            ExtraEndScript = """$('#headersubtitle').html('Randomly selected project : <a href="?projid={0}">{1}</a>');""".format(
                randomproject['projid'], XSSEscape(randomproject['title']))
    sql += "  order by random_value Limit %d" % (2 * ipp, )
    # pour de meilleure perf plus de random ici et du coup on prend 20xipp pour créer un peu d'aléa
    # sql+="  Limit %d"%(20*ipp,) # desactivé suite à split table objects mais pourrait devoir revenir.

    #filt_fromdate,#filt_todate
    sql = """select o.*,t.display_name taxoname,u.name classifwhoname,i.file_name,s.orig_id samplename
                  ,i.height,i.width,i.thumb_file_name,i.thumb_height,i.thumb_width,ofi.orig_id
                  from (""" + sql + """)o
left Join images i on o.img0id=i.imgid
left JOIN taxonomy t on o.classif_id=t.id
LEFT JOIN users u on o.classif_who=u.id
LEFT JOIN  samples s on o.sampleid=s.sampleid
left Join obj_field ofi on ofi.objfid=o.objid
where o.projid in (select projid from projects where visible=true)"""
    # if whereclause!="": # on ne tri pas en random global s'il n'y a aucune criteres, impact de perf
    sql += " order by random_value  "
    # sql+=" order by random()  "
    sql += " Limit %d  " % (ipp, )
    res = GetAll(sql, sqlparam, debug=False, doXSSEscape=True)
    trcount = 1
    LineStart = ""
    if (PageTopProjectLink):
        t.append(PageTopProjectLink)
    if MapForProject:
        t.append(
            render_template("search/explore_inserted_popup.html",
                            Projid=MapForProject))
    t.append("<table class=imgtab><tr id=tr1>" + LineStart)
    WidthOnRow = 0
    #récuperation et ajustement des dimensions de la zone d'affichage
    try:
        PageWidth = int(
            gvp("resultwidth"
                )) - 40  # on laisse un peu de marge à droite et la scroolbar
        if PageWidth < 200: PageWidth = 200
    except:
        PageWidth = 200
    try:
        WindowHeight = int(
            gvp("windowheight")) - 100  # on enleve le bandeau du haut
        if WindowHeight < 200: WindowHeight = 200
    except:
        WindowHeight = 200
    #print("PageWidth=%s, WindowHeight=%s"%(PageWidth,WindowHeight))
    # Calcul des dimmensions et affichage des images
    for r in res:
        filename = r['file_name']
        origwidth = r['width']
        origheight = r['height']
        thumbfilename = r['thumb_file_name']
        thumbwidth = r['thumb_width']
        if origwidth is None:  # pas d'image associé, pas trés normal mais arrive pour les subset sans images
            width = 80
            height = 40
        else:
            width = origwidth * zoom // 100
            height = origheight * zoom // 100
        if max(
                width, height
        ) < 120:  # en dessous de 120 px de coté on ne fait plus le scaling
            if max(origwidth, origheight) < 120:
                width = origwidth  # si l'image originale est petite on l'affiche telle quelle
                height = origheight
            elif max(origwidth, origheight) == origwidth:
                width = 120
                height = origheight * 120 // origwidth
                if height < 1: height = 1
            else:
                height = 120
                width = origwidth * 120 // origheight
                if width < 1: width = 1

        # On limite les images pour qu'elles tiennent toujours dans l'écran
        if width > PageWidth:
            width = PageWidth
            height = math.trunc(r['height'] * width / r['width'])
            if height == 0: height = 1
        if height > WindowHeight:
            height = WindowHeight
            width = math.trunc(r['width'] * height / r['height'])
            if width == 0: width = 1
        if WidthOnRow != 0 and (WidthOnRow + width) > PageWidth:
            trcount += 1
            t.append("</tr></table><table class=imgtab><tr id=tr%d>%s" %
                     (trcount, LineStart))
            WidthOnRow = 0
        cellwidth = width + 22
        if cellwidth < 80:
            cellwidth = 80  # on considère au moins 80 car avec les label c'est rarement moins
        # Met la fenetre de zoon la ou il y plus de place, sachant qu'elle fait 400px et ne peut donc pas être callée à gauche des premieres images.
        if (WidthOnRow + cellwidth) > (PageWidth / 2):
            pos = 'left'
        else:
            pos = 'right'
        #Si l'image affiché est plus petite que la miniature, afficher la miniature.
        if thumbwidth is None or thumbwidth < width or thumbfilename is None:  # sinon (si la miniature est plus petite que l'image à afficher )
            thumbfilename = filename  # la miniature est l'image elle même
        txt = "<td width={0}>".format(cellwidth)
        if filename:
            txt+="<img class='lazy' id=I{3} data-src='/vault/{5}' data-zoom-image='{0}' width={1} height={2} pos={4}>"\
                .format(filename,width,height,r['objid'],pos,thumbfilename)
        else:
            txt += "No Image"
        # Génération de la popover qui apparait pour donner quelques détails sur l'image
        poptitletxt = "%s" % (r['orig_id'], )
        # poptxt="%s"%(r['taxoname'],)
        poptxt = ""
        if r['classifwhoname'] != "":
            poptxt += "<em>by</em> %s" % (r['classifwhoname'])
        poptxt += "<br><em>in</em> " + ntcv(r['samplename'])
        popattribute = "data-title=\"{0}\" data-content=\"{1}\" data-placement='{2}'".format(
            poptitletxt, poptxt, 'left' if WidthOnRow > 500 else 'right')

        txt+="""<div class='subimg {1}' {2}>
<div class='taxo'>{0}</div> </div>
<div class=ddet><span class=ddets><span class='glyphicon glyphicon-eye-open'></span> {3}</div>"""\
            .format(r['taxoname'],"",popattribute
                    ,"(%d)"%(r['imgcount'],) if r['imgcount'] is not None and r['imgcount']>1 else "")
        txt += "</td>"

        # WidthOnRow+=max(cellwidth,80) # on ajoute au moins 80 car avec les label c'est rarement moins
        WidthOnRow += cellwidth + 5  # 5 = border-spacing = espace inter image
        t.append(txt)

    t.append("</tr></table>")
    if len(res) == 0:
        t.append(
            """<div class='alert alert-warning' role='alert' style='margin: 10px;font-size:larger;' >
        <span class='glyphicon glyphicon-remove-sign' style='color:#DD2222;'></span>
        Your selection does not return any object. <br>It may be too limited by the selected filters. <br>Try again releasing the selection criteria</div>"""
        )
    t.append("""
    <script>
        PostAddImages();
        %s
    </script>""" % ExtraEndScript)
    return "\n".join(t)
Esempio n. 9
0
def browsetaxoajax():
    sql = """select t.id,t.parent_id,t.display_name as name,t.taxotype,t.taxostatus,t.creator_email,t.id_source
      ,to_char(t.creation_datetime,'yyyy-mm-dd hh24:mi') creation_datetime,to_char(t.lastupdate_datetime,'yyyy-mm-dd hh24:mi') lastupdate_datetime,{}
    from taxonomy t 
    {}
    where 1=1
    """.format(SQLTreeSelect, SQLTreeJoin)
    params = {}
    sqlcrit = ""
    start = 0
    length = 200
    if gvp('start').isdigit():
        start = int(gvp('start'))
    if gvp('length').isdigit():
        length = int(gvp('length'))

    if gvp('columns[0][search][value]').isdigit():
        sqlcrit += " and t.id = %(id)s"
        params['id'] = int(gvp('columns[0][search][value]'))
    if gvp('columns[1][search][value]').isdigit():
        if int(gvp('columns[1][search][value]')) == 0:
            sqlcrit += " and t.parent_id is null "
        else:
            sqlcrit += " and (t.parent_id = %(parent_id)s or t.id=%(parent_id)s ) "  # or id pour faciliter la navigation
            params['parent_id'] = int(gvp('columns[1][search][value]'))
    if gvp('columns[2][search][value]'):
        sqlcrit += " and t.display_name ilike %(name)s"
        params['name'] = '%' + gvp('columns[2][search][value]') + '%'
    if gvp('columns[3][search][value]'):
        sqlcrit += " and t.taxotype = %(taxotype)s"
        params['taxotype'] = gvp('columns[3][search][value]')
    if gvp('columns[4][search][value]'):
        sqlcrit += " and t.taxostatus = %(taxostatus)s"
        params['taxostatus'] = gvp('columns[4][search][value]')
    if gvp('columns[5][search][value]'):
        sqlcrit += " and t.creator_email ilike %(creator_email)s"
        params['creator_email'] = '%' + gvp('columns[5][search][value]') + '%'
    if gvp('columns[6][search][value]'):
        sqlcrit += " and t.id_source ilike %(id_source)s"
        params['id_source'] = '%' + gvp('columns[6][search][value]') + '%'
    if gvp('columns[8][search][value]').isdigit():
        sqlcrit += " and lastupdate_datetime like %(lastupdate)s"
        params['lastupdate'] = int(gvp('columns[8][search][value]'))
    if gvp('columns[9][search][value]'):
        sqlcrit += """ and tree ilike %(tree)s"""
        params['tree'] = '%' + gvp('columns[9][search][value]') + '%'

    sqlcount = "select count(*) from taxonomy t where 1=1 "
    if 'tree' in params:
        sqlcount = "select count(*) from ({}) t where 1=1 ".format(sql)
        sql = "select t.* from ({}) t where 1=1 ".format(
            sql)  # permet de mettre des critères sur la colonne calculée tree
    orderclause = ""
    if gvp('order[0][column]').isdigit():
        orderclause = " order by {} {}".format(
            int(gvp('order[0][column]')) + 1,
            'desc' if gvp('order[0][dir]') == 'desc' else 'asc')
    sql += sqlcrit + orderclause + (" offset {} limit {}".format(
        start, length))
    lst = GetAll(sql, params)
    for lstitem in lst:  # Post traitement sur les chaines
        lstitem['tree'] = PackTreeTxt(lstitem['tree'])
        lstitem['name'] = XSSEscape(lstitem['name'])
        if lstitem['parent_id'] is None:
            lstitem['parent_id'] = ""

    sqlcount += sqlcrit
    if len(lst) >= length or start != 0:
        recordsFiltered = GetAll(sqlcount, params)[0][0]
    else:
        recordsFiltered = len(lst)
    nbrtaxon = GetAll("select count(*) from taxonomy")[0][0]
    res = {
        'draw': int(gvp('draw')),
        'recordsTotal': nbrtaxon,
        'recordsFiltered': recordsFiltered,
        'data': lst
    }

    return json.dumps(res)
Esempio n. 10
0
    def QuestionProcess(self):
        Prj=database.Projects.query.filter_by(projid=gvg("projid")).first()
        if not Prj.CheckRight(1):
            return PrintInCharte("ACCESS DENIED for this project<br>")
        g.prjtitle=Prj.title
        for k in sharedfilter.FilterList:
            self.param.filtres[k] = gvg(k, "")
        g.headcenter="<h4><a href='/prj/{0}'>{1}</a></h4>".format(Prj.projid,XSSEscape(Prj.title))
        txt=""
        errors=[]
        # Le projet de base est choisi second écran ou validation du second ecran
        if gvp('starttask')=="Y":
            # validation du second ecran
            self.param.ProjectId=gvg("projid")
            if gvg("src",gvp("src",""))!="":
                self.param.BaseProject=database.CSVIntStringToInClause(gvg("src",gvp("src","")))
            self.param.CritVar=gvp("CritVar")
            self.param.Perimeter=gvp("Perimeter")
            self.param.usemodel_foldername = gvp('modeldir', '')
            if gvp('ReadPostTaxoMappingFromLB') =="Y":
                self.param.PostTaxoMapping = ",".join((x[6:] + ":" + gvp(x) for x in request.form if x[0:6] == "taxolb"))
            else:
                self.param.PostTaxoMapping = gvp("PostTaxoMapping")
            self.param.learninglimit = gvp("learninglimit")
            self.param.keeplog=gvp("keeplog")
            self.param.savemodel_foldername = gvp("savemodel_foldername")
            self.param.savemodel_title = gvp("savemodel_title")
            self.param.savemodel_comments = gvp("savemodel_comments")
            self.param.usescn=gvp("usescn","")
            # self.param.Taxo=",".join( (x[4:] for x in request.form if x[0:4]=="taxo") )
            self.param.Taxo =gvp('Taxo')
            self.param.CustSettings=DecodeEqualList(gvp("TxtCustSettings"))
            g.TxtCustSettings=gvp("TxtCustSettings")
            # Verifier la coherence des données
            if self.param.usemodel_foldername=='':
                if self.param.CritVar=='' and self.param.usescn=="":
                    errors.append("You must select some variable")
                if self.param.Taxo=='' : errors.append("You must select some category")
            if len(errors)>0:
                for e in errors:
                    flash(e,"error")
            else: # Pas d'erreur, on memorize les parametres dans le projet et on lance la tache
                # On ajoute les valeurs dans CustSettings pour les sauver dans le ClassifSettings du projet
                PrjCS = DecodeEqualList(Prj.classifsettings)
                d=self.param.CustSettings.copy()
                if gvg("src", gvp("src", "")) != "": # on écrase que si les données sont saisies, sinon on prend dans le projet
                    d['critvar']=self.param.CritVar
                    d['baseproject']=self.param.BaseProject
                    d['seltaxo'] = self.param.Taxo
                    if "usemodel_foldername" in PrjCS: d["usemodel_foldername"]=PrjCS["usemodel_foldername"]
                else:
                    d['usemodel_foldername']=self.param.usemodel_foldername
                    if "critvar" in PrjCS: d["critvar"]=PrjCS["critvar"]
                    if "baseproject" in PrjCS: d["baseproject"]=PrjCS["baseproject"]
                    if "seltaxo" in PrjCS: d["seltaxo"] = PrjCS["seltaxo"]
                d['posttaxomapping'] =self.param.PostTaxoMapping
                Prj.classifsettings=EncodeEqualList(d)
                return self.StartTask(self.param)
        else: # valeurs par default
            if gvp('frommodel', gvg('frommodel')) == "Y":
                if gvp('modeldir')=='':
                    return self.QuestionProcessScreenSelectModel(Prj)
                elif gvp('displaytaxomap')=='Y':
                    return self.QuestionProcessScreenSelectModelTaxo(Prj)
            else:
                if gvp('src', gvg('src')) == "":
                    return self.QuestionProcessScreenSelectSource(Prj)
                elif gvp('seltaxo', gvg('seltaxo')) == "":
                    return self.QuestionProcessScreenSelectSourceTaxo(Prj)

            d=DecodeEqualList(Prj.classifsettings)
            # Certaines variable on leur propre zone d'edition, les autres sont dans la zone texte custom settings
            self.param.CritVar=d.get("critvar","")
            self.param.Taxo=d.get("seltaxo","")
            self.param.Perimeter="nmc"
            self.param.learninglimit = int(gvp("learninglimit","5000"))
            if "critvar" in d : del d["critvar"]
            if "perimeter" in d : del d["perimeter"]
            if "methode" in d: del d["methode"]
            if "learninglimit" in d: del d["learninglimit"]
            if "seltaxo" in d : del d["seltaxo"]
            if "PostTaxoMapping" in d: del d["PostTaxoMapping"]
            if "baseproject" in d : del d["baseproject"]
            g.TxtCustSettings=EncodeEqualList(d)
            self.param.Taxo = ",".join((x[4:] for x in request.form if x[0:4] == "taxo" and x[0:6] != "taxolb"))
            self.param.PostTaxoMapping = ",".join((x[6:]+":"+gvp(x) for x in request.form if x[0:6] == "taxolb"))
        # Determination des criteres/variables utilisées par l'algo de learning
        revobjmap = self.GetReverseObjMap(Prj)
        PrjListInClause=database.CSVIntStringToInClause(gvp("src",gvg("src")))
        LstPrjSrc=GetAll("select projid,mappingobj from projects where projid in({0})".format(PrjListInClause))
        revobjmapbaseByProj={}
        CommonKeys = set(revobjmap.keys())
        for PrjBase in LstPrjSrc:
            revobjmapbaseByProj[PrjBase['projid']] = self.GetReverseObjMap(PrjBase)
            CommonKeys = CommonKeys.intersection(set(revobjmapbaseByProj[PrjBase['projid']].keys()))
        # critlist[NomCol] 0:NomCol , 1:LS % validé rempli , 2:LS Nbr distincte ,3:Cible % rempli ,4:Cible % NV Rempli Inutile ?
        critlist={k:[k,0,0,0,0] for k in CommonKeys}
        # Calcul des stat des projets du LearningSet
        sql="select count(*) nbrtot"
        for k in CommonKeys:
            case="case "
            for PrjBase in LstPrjSrc:
                case +=" when projid={0} then {1} ".format(PrjBase['projid'],revobjmapbaseByProj[PrjBase['projid']][k])
Esempio n. 11
0
def PrjEditDataMass(PrjId):
    request.form  # Force la lecture des données POST sinon il y a une erreur 504
    Prj = database.Projects.query.filter_by(projid=PrjId).first()
    if Prj is None:
        flash("Project doesn't exists", 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not Prj.CheckRight(2):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot edit settings for this project', 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    g.headcenter = "<h4><a href='/prj/{0}'>{1}</a></h4>".format(
        Prj.projid, XSSEscape(Prj.title))
    txt = "<h3>Project Mass data edition </h3>"
    sqlparam = {}
    filtres = {}
    for k in sharedfilter.FilterList:
        if gvg(k):
            filtres[k] = gvg(k, "")
    field = gvp('field')
    if field and gvp('newvalue'):
        tables = {
            'f': 'obj_field',
            'h': 'obj_head',
            's': 'samples',
            'a': 'acquisitions',
            'p': 'process'
        }
        tablecode = field[0]
        table = tables[
            tablecode]  # on extrait la table à partir de la premiere lettre de field
        field = field[
            1:]  # on supprime la premiere lettre qui contenait le nom de la table
        sql = "update " + table + " set " + field + "=%(newvalue)s  "
        if field == 'classif_id':
            sql += " ,classif_when=current_timestamp,classif_who=" + str(
                current_user.id)
        sql += " where "
        if tablecode == "h": sql += " objid in ( select objid from objects o "
        elif tablecode == "f":
            sql += " objfid in ( select objid from objects o "
        elif tablecode == "s":
            sql += " sampleid in ( select distinct sampleid from objects o "
        elif tablecode == "a":
            sql += " acquisid in ( select distinct acquisid from objects o "
        elif tablecode == "p":
            sql += " processid in ( select distinct processid from objects o "
        sql += "  where projid=" + str(Prj.projid)
        sqlparam['newvalue'] = gvp('newvalue')
        if len(filtres):
            sql += " " + sharedfilter.GetSQLFilter(filtres, sqlparam,
                                                   str(current_user.id))
        sql += ")"
        if field == 'classif_id':
            sqlhisto = """insert into objectsclassifhisto(objid,classif_date,classif_type,classif_id,classif_qual,classif_who)
                          select objid,classif_when,'M', classif_id,classif_qual,classif_who
                            from objects o
                            where projid=""" + str(
                Prj.projid) + " and classif_when is not null "
            sqlhisto += sharedfilter.GetSQLFilter(filtres, sqlparam,
                                                  str(current_user.id))
            ExecSQL(sqlhisto, sqlparam)
        ExecSQL(sql, sqlparam)
        flash('Data updated', 'success')
    if field == 'latitude' or field == 'longitude' or gvp('recompute') == 'Y':
        ExecSQL(
            """update samples s set latitude=sll.latitude,longitude=sll.longitude
              from (select o.sampleid,min(o.latitude) latitude,min(o.longitude) longitude
              from obj_head o
              where projid=%(projid)s and o.latitude is not null and o.longitude is not null
              group by o.sampleid) sll where s.sampleid=sll.sampleid and projid=%(projid)s """,
            {'projid': Prj.projid})
        flash('sample latitude and longitude updated', 'success')
    sql = "select objid FROM objects o where projid=" + str(Prj.projid)
    if len(filtres):
        sql += sharedfilter.GetSQLFilter(filtres, sqlparam,
                                         str(current_user.id))
        ObjList = GetAll(sql, sqlparam)
        ObjListTxt = "\n".join((str(r['objid']) for r in ObjList))
        txt += "<span style='color:red;font-weight:bold;font-size:large;'>USING Active Project Filters, {0} objects</span>".format(
            len(ObjList))
    else:
        txt += "<span style='color:red;font-weight:bold;font-size:large;'>Apply to ALL OBJETS OF THE PROJECT (NO Active Filters)</span>"
    Lst = GetFieldList(Prj)
    # txt+="%s"%(Lst,)

    return PrintInCharte(
        render_template("project/prjeditdatamass.html", Lst=Lst, header=txt))
Esempio n. 12
0
def PrjResetToPredicted(PrjId):
    request.form  # Force la lecture des données POST sinon il y a une erreur 504
    Prj = database.Projects.query.filter_by(projid=PrjId).first()
    if Prj is None:
        flash("Project doesn't exists", 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    if not Prj.CheckRight(2):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot edit settings for this project', 'error')
        return PrintInCharte("<a href=/prj/>Select another project</a>")
    g.headcenter = "<h4><a href='/prj/{0}'>{1}</a></h4>".format(
        Prj.projid, XSSEscape(Prj.title))
    txt = "<h3>Reset status to predicted</h3>"
    sqlparam = {}
    filtres = {}
    for k in sharedfilter.FilterList:
        if gvg(k):
            filtres[k] = gvg(k, "")
    process = gvp('process')
    if process == 'Y':
        sqlhisto = """insert into objectsclassifhisto(objid,classif_date,classif_type,classif_id,classif_qual,classif_who)
                      select objid,classif_when,'M', classif_id,classif_qual,classif_who
                        from objects o
                        where projid=""" + str(
            Prj.projid
        ) + """ and classif_when is not null and classif_qual in ('V','D')
                         and not exists(select 1 from objectsclassifhisto och where och.objid=o.objid and och.classif_date=o.classif_when)
                        """
        sqlhisto += sharedfilter.GetSQLFilter(filtres, sqlparam,
                                              str(current_user.id))
        ExecSQL(sqlhisto, sqlparam)

        sqlhisto = """update obj_head set classif_qual='P'
                        where projid={0} and objid in (select objid from objects o   
                                              where projid={0} and classif_qual in ('V','D') {1})
                                              """.format(
            Prj.projid,
            sharedfilter.GetSQLFilter(filtres, sqlparam, str(current_user.id)))
        ExecSQL(sqlhisto, sqlparam)

        # flash('Data updated', 'success')
        txt += "<a href='/prj/%s' class='btn btn-primary'>Back to project</a> " % (
            Prj.projid)
        appli.project.main.RecalcProjectTaxoStat(Prj.projid)
        appli.project.main.UpdateProjectStat(Prj.projid)
        return PrintInCharte(txt)
    sql = "select objid FROM objects o where projid=" + str(Prj.projid)
    if len(filtres):
        sql += sharedfilter.GetSQLFilter(filtres, sqlparam,
                                         str(current_user.id))
        ObjList = GetAll(sql, sqlparam)
        ObjListTxt = "\n".join((str(r['objid']) for r in ObjList))
        txt += "<span style='color:red;font-weight:bold;font-size:large;'>USING Active Project Filters, {0} objects</span>".format(
            len(ObjList))
    else:
        txt += "<span style='color:red;font-weight:bold;font-size:large;'>Apply to ALL OBJETS OF THE PROJECT (NO Active Filters)</span>"
    Lst = GetFieldList(Prj)
    # txt+="%s"%(Lst,)

    return PrintInCharte(
        render_template("project/prjresettopredicted.html",
                        Lst=Lst,
                        header=txt))
Esempio n. 13
0
    def QuestionProcess(self):
        Prj=database.Projects.query.filter_by(projid=gvg("projid")).first()
        txt="<a href='/prj/%d'>Back to project</a>"%Prj.projid
        if not Prj.CheckRight(1):
            return PrintInCharte("ACCESS DENIED for this project<br>"+txt)
        txt+="<h3>Text export Task creation</h3>"
        txt+="<h5>Exported Project : #%d - %s</h5>"%(Prj.projid,XSSEscape(Prj.title))
        errors=[]
        self.param.filtres = {}
        for k in sharedfilter.FilterList:
            if gvg(k, "") != "":
                self.param.filtres[k] = gvg(k, "")
        if len(self.param.filtres) > 0:
            TxtFiltres = ",".join([k + "=" + v for k, v in self.param.filtres.items() if v != ""])
        else: TxtFiltres=""

        if self.task.taskstep==0:
            # Le projet de base est choisi second écran ou validation du second ecran
            if gvp('starttask')=="Y":
                # validation du second ecran
                self.param.ProjectId=gvg("projid")
                self.param.what=gvp("what")
                self.param.samplelist=gvp("samplelist")
                self.param.objectdata=gvp("objectdata")
                self.param.processdata=gvp("processdata")
                self.param.acqdata=gvp("acqdata")
                self.param.sampledata=gvp("sampledata")
                self.param.histodata=gvp("histodata")
                self.param.commentsdata=gvp("commentsdata")
                self.param.usecomasepa=gvp("usecomasepa")
                self.param.sumsubtotal=gvp("sumsubtotal")
                self.param.internalids = gvp("internalids")
                self.param.use_internal_image_name = gvp("use_internal_image_name")
                self.param.exportimagesbak = gvp("exportimagesbak")
                self.param.exportimagesdoi = gvp("exportimagesdoi")
                self.param.typeline = gvp("typeline")
                self.param.splitcsvby = gvp("splitcsvby")
                self.param.putfileonftparea = gvp("putfileonftparea")
                if self.param.splitcsvby=='sample': # si on splitte par sample, il faut les données du sample
                    self.param.sampledata='1'
                # Verifier la coherence des données
                # errors.append("TEST ERROR")
                if self.param.what=='' : errors.append("You must select What you want to export")
                if len(errors)>0:
                    for e in errors:
                        flash(e,"error")
                else: # Pas d'erreur, on lance la tache
                    return self.StartTask(self.param)
            else: # valeurs par default
                self.param.what ="TSV"
                self.param.objectdata = "1"
                self.param.processdata = "1"
                self.param.acqdata = "1"
                self.param.sampledata = "1"
                self.param.splitcsvby=""
            #recupere les samples
            sql="""select sampleid,orig_id
                    from samples where projid =%(projid)s
                    order by orig_id"""
            g.SampleList=GetAll(sql,{"projid":gvg("projid")},cursor_factory=None)
            g.headcenter="<h4>Project : <a href='/prj/{0}'>{1}</a></h4>".format(Prj.projid,XSSEscape(Prj.title));
            if TxtFiltres!="":
                g.headcenter = "<h4>Project : <a href='/prj/{0}?{2}'>{1}</a></h4>".format(Prj.projid, Prj.title,
                    "&".join([k + "=" + v for k, v in self.param.filtres.items() if v != ""]))
            LstUsers = database.GetAll("""select distinct u.email,u.name,Lower(u.name)
                        FROM users_roles ur join users u on ur.user_id=u.id
                        where ur.role_id=2
                        and u.active=TRUE and email like '%@%'
                        order by Lower(u.name)""")
            g.LstUser = "******".join(["<a href='mailto:{0}'>{0}</a></li> ".format(*r) for r in LstUsers])
            return render_template('task/textexport_create.html',header=txt,data=self.param,TxtFiltres=TxtFiltres)
Esempio n. 14
0
    def QuestionProcess(self):
        self.param.ProjectId = gvg("p")
        Prj = database.Projects.query.filter_by(
            projid=self.param.ProjectId).first()
        if not Prj.CheckRight(1):
            return PrintInCharte("ACCESS DENIED for this project<br>" +
                                 Prj.title)
        txt = ""
        g.headcenter = "<h4><a href='/prj/{0}'>{1}</a></h4>".format(
            Prj.projid, XSSEscape(Prj.title))
        errors = []
        if self.task.taskstep == 0:
            if gvg('eps') == "":  # eps = Extra Project selected
                # Premier écran de configuration, choix du projet de base
                txt = "<h3>SUBSET PROJECT SELECTION Page (1/2)</h3>"
                txt += """<h4>SELECT ADDITIONAL PROJECT TO INCLUDE IN THE SUBSET</h4>
                <form action="?p={0}&eps=y" method=post>
                """.format(Prj.projid)

                from flask_login import current_user
                sql = "select projid,title from projects "
                if not current_user.has_role(database.AdministratorLabel):
                    sql += " where projid in (select projid from projectspriv where member=%d and privilege='Manage')" % current_user.id
                sql += " order by title"
                ProjList = database.GetAll(sql)
                txt += """<select name=extraprojects id= extraprojects multiple>"""
                for r in ProjList:
                    txt += "<option value='{0}'>{1} ({0})</option>".format(*r)
                txt += """</select><br><br>
                <input class="btn btn-primary" type=submit value="Go to the next page">
                <script>
                $(document).ready(function() {
                        $("#extraprojects").select2();
                        });
                </script>
                </form>
                <br><br>
                <div class='panel panel-default' style="width:600px;margin-left:10px;">
A SUBSET is a selection of images (objects) randomly copied from one or more source projects<br>
A SUBSET can have different usages:<br>
<ul>
<li>It can be utilized as a Learning Set for the automatic classification
<li>It can be utilized as a Test Set to evaluate the quality of the prediction or the validation
</ul>
                </div>
                """
                return PrintInCharte(txt)

            self.param.filtres = {}
            for k in sharedfilter.FilterList:
                if gvg(k, "") != "":
                    self.param.filtres[k] = gvg(k, "")
            filtertxt = ""
            if len(self.param.filtres) > 0:
                filtertxt += ",".join([
                    k + "=" + v for k, v in self.param.filtres.items()
                    if v != ""
                ])
                g.headcenter = "<h4><a href='/prj/{0}?{2}'>{1}</a></h4>".format(
                    Prj.projid, XSSEscape(Prj.title), "&".join([
                        k + "=" + v for k, v in self.param.filtres.items()
                        if v != ""
                    ]))

            # Le projet de base est choisi second écran ou validation du second ecran
            if gvp('starttask') == "Y":
                # validation du second ecran
                self.param.extraprojects = gvp("extraprojects")
                self.param.samplelist = gvp("samplelist")
                self.param.withimg = gvp("withimg")
                self.param.subsetprojecttitle = gvp("subsetprojecttitle")
                self.param.valtype = gvp("valtype")
                if self.param.valtype == 'V':
                    try:
                        self.param.valeur = int(gvp("vvaleur"))
                        if self.param.valeur <= 0:
                            errors.append("Absolute value not in range")
                    except:
                        errors.append("Invalid Absolute value")
                if self.param.valtype == 'P':
                    try:
                        self.param.valeur = int(gvp("pvaleur"))
                        if self.param.valeur <= 0 or self.param.valeur > 100:
                            errors.append("% value not in range")
                    except:
                        errors.append("Invalid % value")

                tmp = []
                if gvp('what_v'): tmp.append('V')
                if gvp('what_d'): tmp.append('D')
                if gvp('what_p'): tmp.append('P')
                if gvp('what_n'): tmp.append('N')
                self.param.what = ",".join(tmp)
                # Verifier la coherence des données
                # errors.append("TEST ERROR")
                # if self.param.what=='' : errors.append("You must select at least one Flag")
                if self.param.valtype == '':
                    errors.append(
                        "You must select the object selection parameter '% of values' or '# of objects'"
                    )
                if len(errors) > 0:
                    for e in errors:
                        flash(e, "error")
                else:  # Pas d'erreur, on lance la tache
                    return self.StartTask(self.param)
            else:  # valeurs par default
                self.param.what = "V"
                self.param.subsetprojecttitle = (
                    Prj.title + " - Subset created on " +
                    (datetime.date.today().strftime('%Y-%m-%d')))[0:255]
                self.param.extraprojects = ",".join(
                    request.form.getlist('extraprojects'))
                if filtertxt != "":  # s'il y a un filtre on coche toutes les cases et on masque la zone à l'affichage
                    self.param.what = "V,D,P,N"

            txt = "<h3>SUBSET SETTINGS Page (2/2)</h3>"
            if self.param.extraprojects:
                ExtraPrj = database.Projects.query.filter(
                    text("projid in (%s)" % self.param.extraprojects)).all()
                g.dispextraprojects = " ".join([
                    "<br>- {1} ({0}) ".format(r.projid, r.title)
                    for r in ExtraPrj
                ])
                for p in ExtraPrj:
                    if p.mappingobj != Prj.mappingobj:
                        flash(
                            "Object variables and metadata differ on project %d (%s). The subset should not be utilized as a Learning Set"
                            % (p.projid, p.title), "warning")
                    if p.mappingsample != Prj.mappingsample:
                        flash(
                            "Sample variables mapping differ on project %d (%s)."
                            % (p.projid, p.title), "warning")
                    if p.mappingacq != Prj.mappingacq:
                        flash(
                            "Acquisition variables mapping differ on project %d (%s)"
                            % (p.projid, p.title), "warning")
                    if p.mappingprocess != Prj.mappingprocess:
                        flash(
                            "Process variables mapping differ on project %d (%s)"
                            % (p.projid, p.title), "warning")
            else:
                g.dispextraprojects = "None"
                #recupere les samples
                sql = """select sampleid,orig_id
                        from samples where projid =%(projid)s
                        order by orig_id"""
                g.SampleList = GetAll(sql, {"projid": gvg("p")},
                                      cursor_factory=None)
            return render_template('task/subset_create.html',
                                   header=txt,
                                   data=self.param,
                                   prevpost=request.form,
                                   filtertxt=filtertxt)
Esempio n. 15
0
def objectdetails(objid):
    #récuperation et ajustement des dimensions de la zone d'affichage
    try:
        PageWidth = int(gvg(
            "w")) - 40  # on laisse un peu de marge à droite et la scroolbar
        if PageWidth < 200: PageWidth = 20000
        WindowHeight = int(gvg("h")) - 40  # on laisse un peu de marge en haut
        if WindowHeight < 200: WindowHeight = 20000
    except:
        PageWidth = 20000
        WindowHeight = 20000

    obj = database.Objects.query.filter_by(objid=objid).first()
    t = list()
    # Dans cet écran on utilise ElevateZoom car sinon en mode popup il y a conflit avec les images sous la popup
    t.append("<script src='/static/jquery.elevatezoom.js'></script>")
    Prj = obj.project
    if Prj.visible == False and not Prj.CheckRight(
            0):  # Level 0 = Read, 1 = Annotate, 2 = Admin
        flash('You cannot view this project', 'error')
        return PrintInCharte("<a href=/>Back to home</a>")
    g.Projid = Prj.projid
    PrjManager = [(m.memberrel.email, m.memberrel.name)
                  for m in Prj.projmembers if m.privilege == 'Manage']
    t.append("<p>Project: <b><a href='/prj/%d'>%s</a></b> (managed by : %s)" %
             (Prj.projid, XSSEscape(Prj.title), ",".join(
                 ("<a href ='mailto:%s'>%s</a>" % m for m in PrjManager))))
    if len(PrjManager) > 0:
        t.append(
            "<br>To report a mistake, contact <a href ='mailto:{0}?subject=Ecotaxa%20mistake%20notification&body={2}'>{1}</a>"
            .format(
                PrjManager[0][0], PrjManager[0][1],
                urllib.parse.quote(
                    "Hello,\n\nI have discovered a mistake on this page " +
                    request.base_url + "\n")))


# //window.location="mailto:?subject=Ecotaxa%20page%20share&body="+encodeURIComponent("Hello,\n\nAn Ecotaxa user want share this page with you \n"+url);
    t.append("</p><p>Classification :")
    if obj.classif:
        t.append("<br>&emsp;<b>%s</b>" % XSSEscape(obj.classif.display_name))
        TaxoHierarchie = (r[0] for r in GetAll(
            """WITH RECURSIVE rq(id,name,parent_id) as ( select id,name,parent_id FROM taxonomy where id =%(taxoid)s
                        union
                        SELECT t.id,t.name,t.parent_id FROM rq JOIN taxonomy t ON t.id = rq.parent_id )
                        select name from rq""", {"taxoid": obj.classif.id}))
        t.append("<br>&emsp;" + (" &lt; ".join(TaxoHierarchie)) +
                 " (id=%s)" % obj.classif_id)
    else:
        t.append("<br>&emsp;<b>Unknown</b>")
    if obj.classiffier is not None:
        t.append(
            "<br>&emsp;%s " %
            (database.ClassifQual.get(obj.classif_qual, "To be classified")))
        t.append(" by %s (%s) " %
                 (obj.classiffier.name, obj.classiffier.email))
        if obj.classif_when is not None:
            t.append(" on %s " % (obj.classif_when.strftime("%Y-%m-%d %H:%M")))
    t.append("</p>")
    if obj.objfrel.object_link is not None:
        t.append("<p>External link :<a href='{0}' target=_blank> {0}</a></p>".
                 format(obj.objfrel.object_link))
    t.append(
        "<table><tr><td valign=top>Complementaty information <a href='javascript:gotocommenttab();' > ( edit )</a>: </td><td> <span id=spancomplinfo> {0}</span></td></tr></table>"
        .format(ntcv(obj.complement_info).replace('\n', '<br>\n')))
    # On affiche la liste des images, en selectionnant une image on changera le contenu de l'image Img1 + Redim
    # l'approche avec des onglets de marchait pas car les images sont superposées
    obj.images.sort(key=lambda x: x.imgrank)
    t.append("""<p>Image list : """)
    for img in obj.images:
        (width, height) = ComputeLimitForImage(img.width, img.height,
                                               PageWidth, WindowHeight)
        if img.thumb_file_name:
            minifile = img.thumb_file_name
            (miniwidth,
             miniheight) = ComputeLimitForImage(img.thumb_width,
                                                img.thumb_height, 30, 30)
        else:
            minifile = img.file_name
            (miniwidth,
             miniheight) = ComputeLimitForImage(img.width, img.height, 30, 30)
        t.append(
            """<a href="javascript:SwapImg1('{1}',{2},{3});" >{0} <img src=/vault/{4} width={5} height={6}></a> """
            .format(img.imgrank + 1, img.file_name, width, height, minifile,
                    miniwidth, miniheight))
    # Ajout de la 1ère image
    (width, height) = ComputeLimitForImage(obj.images[0].width,
                                           obj.images[0].height, PageWidth,
                                           WindowHeight)
    t.append(
        "</p><p><img id=img1 src=/vault/{1} data-zoom-image=/vault/{1} width={2} height={0}></p>"
        .format(height, obj.images[0].file_name, width))
    # Affichage de l'onglet de classification
    if Prj.CheckRight(1):
        t.append("""
<table><tr><td>Set a new classification :</td>
 <td style="width: 230px;">
     <div class="input-group">
       <select id="taxolbpop" name="taxolbpop" style="width: 200px" class='taxolb' > </select>"""
                 )
        if gvg("ajax", "0") == "0":
            t.append("""<span class="input-group-btn">
                    <button class="btn btn-default btn-sm" type="button"  data-toggle="modal" data-target="#TaxoModal" data-mytargetid="taxolbpop" title="Search on Taxonomy Tree">
                        <span id=OpenTaxoLB class="glyphicon glyphicon-th-list" aria-hidden="true"/></button>
                    </span>""")
        else:
            t.append("<br>")
        t.append("""</div><!-- /input-group -->
 <span id=PendingChangesPop></span></td><td width=30px></td><td valign=top>
    <button type="button" class="btn btn-success btn-xs" onclick="Save1Object('V');">Save as Validated</button>
    <button type="button" class="btn btn-warning btn-xs" onclick="Save1Object('D');">Save as dubious</button>
    <button id=btenableedit type="button" class="btn btn-gris btn-xs" onclick="EnableEdit();">Enable Editing</button>
    <button type="button" class="btn btn-default btn-xs"  onclick="$('#PopupDetails').modal('hide');">Close</button>
    </td></tr></table>
    """)
    # Ajout des Onglets sous l'image
    t.append("""<br><div><ul class="nav nav-tabs" role="tablist">
    <li role="presentation" class="active"><a href="#tabdobj" aria-controls="tabdobj" role="tab" data-toggle="tab"> Object details</a></li>
    <li role="presentation" ><a href="#tabdsample" aria-controls="tabdsample" role="tab" data-toggle="tab"> Sample details</a></li>
    <li role="presentation" ><a href="#tabdacquis" aria-controls="tabdacquis" role="tab" data-toggle="tab"> Acquisition details</a></li>
    <li role="presentation" ><a href="#tabdprocessrel" aria-controls="tabdprocess" role="tab" data-toggle="tab"> Processing details</a></li>
    <li role="presentation" ><a href="#tabdclassiflog" aria-controls="tabdclassiflog" role="tab" data-toggle="tab">Classification change log</a></li>
    <li role="presentation" ><a href="#tabdmap" aria-controls="tabdmap" role="tab" data-toggle="tab" id=atabdmap style="background: #5CB85C;color:white;">Map</a></li>
    """)
    if Prj.CheckRight(1):
        t.append(
            """<li role="presentation" ><a id=linktabdaddcomments href="#tabdaddcomments" aria-controls="tabdaddcomments" role="tab" data-toggle="tab">Edit complementary informations</a></li>"""
        )
    if obj.classif_auto:
        classif_auto_name = obj.classif_auto.name
        if obj.classif_auto_score:
            classif_auto_name += " (%0.3f)" % (obj.classif_auto_score, )
    else:
        classif_auto_name = ''
    t.append("""</ul>
    <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="tabdobj">
    <table class='table table-bordered table-condensed' data-table='object'><tr>
    <td style=' background-color: #f2f2f2;' data-edit='longitude'><b>longitude</td><td>{0}</td>
    <td style=' background-color: #f2f2f2;' data-edit='latitude'><b>latitude</td><td>{1}</td>
    <td style=' background-color: #f2f2f2;' data-edit='objdate'><b>Date</td><td>{2}</td>
    <td style=' background-color: #f2f2f2;'><b>Time (daytime)</td><td>{3} ({10})</td>
    </tr><tr><td style=' background-color: #f2f2f2;' data-edit='depth_min'><b>Depth min</td><td>{4}</td>
    <td style=' background-color: #f2f2f2;' data-edit='depth_max'><b>Depth max</td><td>{5}</td>
    <td><b>Classif auto</td><td>{6}</td><td><b>Classif auto when</td><td>{7}</td>
    </tr><tr><td><b>Object #</td><td>{8}</td>
    <td data-edit='orig_id'><b>Original Object ID</td><td colspan=5>{9}</td></tr><tr>"""
             .format(nonetoformat(obj.longitude, '.5f'),
                     nonetoformat(obj.latitude,
                                  '.5f'), obj.objdate, obj.objtime,
                     obj.depth_min, obj.depth_max, classif_auto_name,
                     obj.classif_auto_when, objid, obj.objfrel.orig_id,
                     database.DayTimeList.get(obj.sunpos, '?')))
    cpt = 0
    # Insertion des champs object
    for k, v in collections.OrderedDict(
            sorted(DecodeEqualList(Prj.mappingobj).items())).items():
        if cpt > 0 and cpt % 4 == 0:
            t.append("</tr><tr>")
        cpt += 1
        t.append("<td data-edit='{2}'><b>{0}</td><td>{1}</td>".format(
            v, ScaleForDisplay(getattr(obj.objfrel, k, "???")), k))
    t.append("</tr></table></div>")
    # insertion des champs Sample, Acquisition & Processing dans leurs onglets respectifs
    for r in (("Sample", "mappingsample", "sample"), ("Acquisition",
                                                      "mappingacq", "acquis"),
              ("Processing", "mappingprocess", "processrel")):
        t.append(
            '<div role="tabpanel" class="tab-pane" id="tabd' + r[2] + '">' +
            r[0] +
            " details :<table class='table table-bordered table-condensed'  data-table='"
            + r[2] + "'><tr>")
        cpt = 0
        if getattr(obj, r[2]):
            if r[2] == "sample":
                t.append(
                    "<td data-edit='orig_id'><b>{0}</td><td colspan=3>{1}</td><td data-edit='longitude'><b>{2}</td><td>{3}</td><td data-edit='latitude'><b>{4}</td><td>{5}</td></tr><tr>"
                    .format(
                        "Original ID",
                        ScaleForDisplay(obj.sample.orig_id),
                        "longitude",
                        ScaleForDisplay(obj.sample.longitude),
                        "latitude",
                        ScaleForDisplay(obj.sample.latitude),
                    ))
            elif r[2] == "acquis":
                t.append(
                    "<td data-edit='orig_id'><b>{0}</td><td colspan=3>{1}</td><td data-edit='instrument'><b>{2}</td><td>{3}</td></tr><tr>"
                    .format(
                        "Original ID",
                        ScaleForDisplay(obj.acquis.orig_id),
                        "Instrument",
                        ScaleForDisplay(obj.acquis.instrument),
                    ))
            else:
                t.append(
                    "<td data-edit='orig_id'><b>{0}</td><td>{1}</td></tr><tr>".
                    format(
                        "Original ID.",
                        ScaleForDisplay(
                            getattr(getattr(obj, r[2]), "orig_id", "???"))))
            for k, v in collections.OrderedDict(
                    sorted(DecodeEqualList(getattr(Prj,
                                                   r[1])).items())).items():
                if cpt > 0 and cpt % 4 == 0:
                    t.append("</tr><tr>")
                cpt += 1
                t.append("<td data-edit='{2}'><b>{0}</td><td>{1}</td>".format(
                    v, ScaleForDisplay(getattr(getattr(obj, r[2]), k, "???")),
                    k))
            if r[2] == "sample":
                t.append(
                    "</tr><tr><td><b>{0}</td><td colspan=7>{1}</td></tr><tr>".
                    format(
                        "Dataportal Desc.",
                        ScaleForDisplay(
                            html.escape(ntcv(
                                obj.sample.dataportal_descriptor)))))
        else:
            t.append("<td>No {0}</td>".format(r[0]))
        t.append("</tr></table></div>")

    # Affichage de l'historique des classification
    t.append("""<div role="tabpanel" class="tab-pane" id="tabdclassiflog">
Current Classification : Quality={} , date={}    
    <table class='table table-bordered table-condensed'><tr>
    <td>Date</td><td>Type</td><td>Taxo</td><td>Author</td><td>Quality</td></tr>"""
             .format(obj.classif_qual, obj.classif_when))
    Histo = GetAll(
        """SELECT to_char(classif_date,'YYYY-MM-DD HH24:MI:SS') datetxt,classif_type ,t.display_name as name,u.name username,classif_qual
  from objectsclassifhisto h
  left join taxonomy t on h.classif_id=t.id
  LEFT JOIN users u on u.id = h.classif_who
WHERE objid=%(objid)s
order by classif_date desc""", {"objid": objid},
        doXSSEscape=True)
    for r in Histo:
        t.append("<tr><td>" + ("</td><td>".join([
            str(r[x]) if r[x] else "-"
            for x in ("datetxt", "classif_type", "name", "username",
                      "classif_qual")
        ])) + "</td></tr>")
    t.append("</table></div>")
    if Prj.CheckRight(1):
        t.append("""<div role="tabpanel" class="tab-pane" id="tabdaddcomments">
        <textarea id=compinfo rows=5 cols=120 autocomplete=off>%s</textarea><br>
        <button type="button" class='btn btn-primary' onclick="UpdateComment();">Save additional comment</button>
        <span id=ajaxresultcomment></span>
        """ % (ntcv(obj.complement_info), ))
        t.append("</div>")
    # Affichage de la carte
    t.append("""
    <div role="tabpanel" class="tab-pane" id="tabdmap">
<div id="map2" class="map2" style="width: 100%; height: 450px;">
  Displaying Map requires Internet Access to load map from https://server.arcgisonline.com
</div>""")

    t.append("</table></div>")
    t.append(
        render_template("common/objectdetailsscripts.html",
                        Prj=Prj,
                        objid=objid,
                        obj=obj))

    # En mode popup ajout en haut de l'écran d'un hyperlien pour ouvrir en fenete isolée
    # Sinon affichage sans lien dans la charte.
    if gvg("ajax", "0") == "1":
        return """<table width=100% style='margin: 3px'><tr><td><a href='/objectdetails/{0}?w={1}&h={2}' target=_blank><b>Open in a separate window</b> (right click to copy link)</a>
        </td><td align='right'><button type="button" class="btn btn-default"  onclick="$('#PopupDetails').modal('hide');">Close</button>&nbsp;&nbsp;
        </td></tr></table><div style='margin: 0 5px;'>""".format(
            objid, gvg("w"), gvg("h")) + "\n".join(t)
    return PrintInCharte("<div style='margin-left:10px;'>" + "\n".join(t) +
                         render_template('common/taxopopup.html'))