Attention une mise à jour du serveur va être effectuée le lundi 17 mai entre 13h et 13h30. Cette mise à jour va générer une interruption du service de quelques minutes.

sample_set.py 17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# coding: utf8
import gluon.contrib.simplejson, datetime
import vidjil_utils
import time

if request.env.http_origin:
    response.headers['Access-Control-Allow-Origin'] = request.env.http_origin  
    response.headers['Access-Control-Allow-Credentials'] = 'true'
    response.headers['Access-Control-Max-Age'] = 86400

ACCESS_DENIED = "access denied"




#
#
def next_sample_set():
    '''
    Process request, possibly changing request.vars['id'] depending on request.vars['next']
    '''
    if 'next' in request.vars:
        try:
            sample_type = db.sample_set[request.vars["id"]].sample_type
            
            for row in db( db[sample_type].sample_set_id == request.vars["id"] ).select() :
                current_id = row.id
            
            go_next = int(request.vars['next'])
            if go_next > 0:
HERBERT Ryan's avatar
HERBERT Ryan committed
31
                res = db((db[sample_type].id > current_id) & (auth.vidjil_accessible_query(PermissionEnum.read.value, db[sample_type]))).select(
32 33
                    db[sample_type].id, db[sample_type].sample_set_id, orderby=db[sample_type].id, limitby=(0,1))
            else:
HERBERT Ryan's avatar
HERBERT Ryan committed
34
                res = db((db[sample_type].id < current_id) & (auth.vidjil_accessible_query(PermissionEnum.read.value, db[sample_type]))).select(
35 36 37 38 39 40 41 42 43 44 45
                    db[sample_type].id, db[sample_type].sample_set_id, orderby=~db[sample_type].id, limitby=(0,1))
            if (len(res) > 0):
                request.vars["id"] = str(res[0].sample_set_id)
        except:
            pass

## return patient file list
##
def index():

    next_sample_set()
46 47 48 49 50 51
    sample_set = db.sample_set[request.vars["id"]]
    sample_set_id = sample_set.id
    factory = ModelFactory()
    helper = factory.get_instance(type=sample_set.sample_type)
    data = helper.get_data(sample_set_id)
    info_file = helper.get_info_dict(data)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

    if request.vars["config_id"] and request.vars["config_id"] != "-1" and request.vars["config_id"] != "None":
        config_id = long(request.vars["config_id"])
        config_name = db.config[request.vars["config_id"]].name

        fused = db(
            (db.fused_file.sample_set_id == sample_set_id)
            & (db.fused_file.config_id == config_id)
        )

        analysis = db(
            db.analysis_file.sample_set_id == sample_set_id
        ).select(orderby=~db.analysis_file.analyze_date)
        
        
        config = True
        fused_count = fused.count()
        fused_file = fused.select()
        fused_filename = info_file["filename"] +"_"+ config_name + ".data"
        analysis_count = len(analysis)
        analysis_file = analysis
        analysis_filename = info_file["filename"]+"_"+ config_name + ".analysis"
        
    else:
        config_id = -1
        config = False
        fused_count = 0
        fused_file = ""
        fused_filename = ""
        analysis_count = 0
        analysis_file = ""
        analysis_filename = ""

    if config :
	query =[]
	
        query2 = db(
                (db.sequence_file.id == db.sample_set_membership.sequence_file_id)
                & (db.sample_set_membership.sample_set_id == sample_set_id)
            ).select(
                left=db.results_file.on(
                    (db.results_file.sequence_file_id==db.sequence_file.id)
                    & (db.results_file.config_id==str(config_id) )
                ), 
                orderby = db.sequence_file.id|~db.results_file.run_date
            )
        
	previous=-1
	for row in query2 :
	    if row.sequence_file.id != previous : 
		query.append(row)
		previous=row.sequence_file.id

    else:

        query = db(
                (db.sequence_file.id == db.sample_set_membership.sequence_file_id)
                & (db.sample_set_membership.sample_set_id == sample_set_id)
            ).select(
                left=db.results_file.on(
                    (db.results_file.sequence_file_id==db.sequence_file.id)
                    & (db.results_file.config_id==str(config_id) )
                )
            )

117 118 119 120
    query_pre_process = db( db.pre_process.id >0 ).select()
    pre_process_list = {}
    for row in query_pre_process:
        pre_process_list[row.id] = row.name
121 122 123 124
    
    log.debug('sample_set (%s)' % request.vars["id"])
    #if (auth.can_view_patient(request.vars["id"]) ):
    return dict(query=query,
125
                pre_process_list=pre_process_list,
126 127 128
                config_id=config_id,
                info=info_file,
                can_modify=auth.can_modify_sample_set(sample_set_id),
129
                can_upload=auth.can_upload_sample_set(sample_set_id),
130 131 132 133 134 135
                fused_count=fused_count,
                fused_file=fused_file,
                fused_filename=fused_filename,
                analysis_count=analysis_count,
                analysis_file = analysis_file,
                analysis_filename = analysis_filename,
136
                sample_type = db.sample_set[request.vars["id"]].sample_type,
137 138 139 140 141 142 143 144 145
                config=config)
    
    """
    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
    """

146 147 148 149 150 151 152 153 154 155
## return a list of generic sample_sets
def all():
    start = time.time()
    if not auth.user :
        res = {"redirect" : URL('default', 'user', args='login', scheme=True, host=True,
                            vars=dict(_next=URL('run', 'index', scheme=True, host=True)))
            }
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

    isAdmin = auth.is_admin()
156
    if request.vars['type']:
157
        type = request.vars['type']
158
    else :
HERBERT Ryan's avatar
HERBERT Ryan committed
159
        type = 'generic'
160

161 162 163 164 165 166 167 168
    step = None
    page = None
    is_not_filtered = "sort" not in request.vars and "filter" not in request.vars
    if request.vars['page'] is not None and is_not_filtered:
        page = int(request.vars['page'])
        step = 50

    list = SampleSetList(type, page, step)
169 170 171
    list.load_creator_names()
    list.load_sample_information()
    list.load_config_information()
172 173
    if isAdmin:
        list.load_permitted_groups()
174 175
    list.load_anon_permissions()
    result = list.get_values()
176

177 178
    # failsafe if filtered display all results
    step = len(list) if step is None else step
179
    page = 0 if page is None else page
180

HERBERT Ryan's avatar
HERBERT Ryan committed
181 182 183
    factory = ModelFactory()
    helper = factory.get_instance(type=type)
    fields = helper.get_fields()
184

185 186 187 188
    ##sort result
    reverse = False
    if request.vars["reverse"] == "true" :
        reverse = True
HERBERT Ryan's avatar
HERBERT Ryan committed
189
    if "sort" in request.vars:
190 191 192 193 194 195 196 197
        result = sorted(result, key = lambda row : row[request.vars["sort"]], reverse=reverse)
    else:
        result = sorted(result, key = lambda row : row.id, reverse=not reverse)

    ##filter
    if "filter" not in request.vars :
        request.vars["filter"] = ""

HERBERT Ryan's avatar
HERBERT Ryan committed
198
    result = helper.filter(request.vars['filter'], result)
199 200 201 202
    log.debug("run list (%.3fs) %s" % (time.time()-start, request.vars["filter"]))


    return dict(query = result,
HERBERT Ryan's avatar
HERBERT Ryan committed
203
                fields = fields,
204
                helper = helper,
205
                isAdmin = isAdmin,
206 207 208
                reverse = False,
                step = step,
                page = page)
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236


## return form to create new generic sample_set
def add():
    if (auth.can_create_patient()):
        creation_group_tuple =  get_default_creation_group(auth)
        groups = creation_group_tuple[0]
        max_group = creation_group_tuple[1]
        return dict(message=T('add sample_set'), groups=groups, master_group=max_group)
    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))



## create a generic sample_set if the html form is complete
## needs ["name", "info"]
## redirect to generic sample_set list if success
## return a flash error message if fail
def add_form():
    if (auth.can_create_patient()):

        error = ""
        if request.vars["name"] == "" :
            error += "name needed, "

        if error=="" :
HERBERT Ryan's avatar
HERBERT Ryan committed
237 238 239
            id_sample_set = db.sample_set.insert(sample_type='generic')

            id = db.generic.insert(name=request.vars["name"],
240 241
                                   info=request.vars["info"],
                                   creator=auth.user_id,
HERBERT Ryan's avatar
HERBERT Ryan committed
242
                                   sample_set_id=id_sample_set)
243 244 245 246 247 248


            user_group = int(request.vars["sample_set_group"])
            admin_group = db(db.auth_group.role=='admin').select().first().id

            #sample_set creator automaticaly has all rights
HERBERT Ryan's avatar
HERBERT Ryan committed
249
            auth.add_permission(user_group, PermissionEnum.access.value, db.generic, id)
250 251

            res = {"redirect": "sample_set/index",
252 253
                   "args" : { "id" : id },
                   "message": "(%s) sample_set %s added" % (id, request.vars["name"]) }
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
            log.info(res, extra={'user_id': auth.user.id, 'record_id': id, 'table_name': 'sample_set'})

            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

        else :
            res = {"success" : "false",
                   "message" : error}
            log.error(res)
            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

269
def edit():
270
    sample_set = db.sample_set[request.vars["id"]]
271
    sample_type = sample_set.sample_type
272 273 274 275 276
    
    if sample_type == "patient" : 
        patient = db((db.patient.sample_set_id == request.vars["id"])).select()[0]
        redirect(URL('patient', 'edit', vars=dict(id=patient.id)), headers=response.headers)
    
277
    elif sample_type == "run" :
278 279
        run = db((db.run.sample_set_id == request.vars["id"])).select()[0]
        redirect(URL('run', 'edit', vars=dict(id=run.id)), headers=response.headers)
280

281
    else :
HERBERT Ryan's avatar
HERBERT Ryan committed
282 283 284
        generic = db((db.generic.sample_set_id == request.vars["id"])).select()[0]
        if (auth.can_modify('generic', generic.id)):
            request.vars["id"] = generic.id
285 286 287 288 289 290 291
            return dict(message=T('edit sample_set'))
        else :
            res = {"message": ACCESS_DENIED}
            log.error(res)
            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

def edit_form():
HERBERT Ryan's avatar
HERBERT Ryan committed
292
    if (auth.can_modify('generic', request.vars["id"]) ):
293 294 295 296 297 298 299
        error = ""
        if request.vars["name"] == "" :
            error += "name needed, "
        if request.vars["id"] == "" :
            error += "sample set id needed, "

        if error=="" :
HERBERT Ryan's avatar
HERBERT Ryan committed
300
            db.generic[request.vars["id"]] = dict(name=request.vars["name"],
301 302 303 304 305
                                                   info=request.vars["info"],
                                                   )

            res = {"redirect": "back",
                   "message": "%s (%s): sample_set edited" % (request.vars["name"], request.vars["id"])}
HERBERT Ryan's avatar
HERBERT Ryan committed
306
            log.info(res, extra={'user_id': auth.user.id, 'record_id': request.vars['id'], 'table_name': 'generic'})
307 308 309 310 311 312 313 314 315 316
            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

        else :
            res = {"success" : "false", "message" : error}
            log.error(res)
            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338

def custom():
    start = time.time()

    if request.vars["config_id"] and request.vars["config_id"] != "-1" :
        config_id = long(request.vars["config_id"])
        config_name = db.config[request.vars["config_id"]].name
        config = True
        
    else:
        request.vars["config_id"] = -1
        config_id = -1
        config_name = None
        config = False
        
    if "custom_list" not in request.vars :
        request.vars["custom_list"] = []
    if type(request.vars["custom_list"]) is str :
        request.vars["custom_list"] = [request.vars["custom_list"]]
        
    myGroupBy = None
    if request.vars["id"] and auth.can_view_sample_set(request.vars["id"]):
HERBERT Ryan's avatar
HERBERT Ryan committed
339
        q = ((auth.vidjil_accessible_query(PermissionEnum.read_config.value, db.config))
340 341 342 343 344 345 346 347 348
                & (db.sample_set.id == request.vars["id"])
                & (db.sample_set_membership.sample_set_id == db.sample_set.id)
                & (db.sequence_file.id == db.sample_set_membership.sequence_file_id)
                & (db.results_file.sequence_file_id==db.sequence_file.id)
                & (db.results_file.data_file != '')
                & (db.config.id==db.results_file.config_id)
            )
        
    else:
349 350
        q = ((auth.vidjil_accessible_query(PermissionEnum.read.value, db.patient)
                | auth.vidjil_accessible_query(PermissionEnum.read.value, db.run))
HERBERT Ryan's avatar
HERBERT Ryan committed
351
                & (auth.vidjil_accessible_query(PermissionEnum.read_config.value, db.config))
352 353 354 355 356 357
                & (db.sample_set_membership.sample_set_id == db.sample_set.id)
                & (db.sequence_file.id == db.sample_set_membership.sequence_file_id)
                & (db.results_file.sequence_file_id==db.sequence_file.id)
                & (db.results_file.data_file != '')
                & (db.config.id==db.results_file.config_id)
            )
358
        myGroupBy = db.sequence_file.id|db.patient.id|db.run.id|db.results_file.config_id
359 360

    query = db(q).select(
361 362 363
                db.patient.id, db.patient.info, db.patient.first_name, db.patient.last_name,
                db.run.id, db.run.info, db.run.name,
                db.results_file.id, db.results_file.config_id, db.sequence_file.sampling_date,
364 365 366
                db.sequence_file.pcr, db.config.name, db.results_file.run_date, db.results_file.data_file, db.sequence_file.filename,
                db.sequence_file.data_file, db.sequence_file.id, db.sequence_file.info,
                db.sequence_file.size_file,
367 368 369 370
                left = [
                    db.patient.on(db.patient.sample_set_id == db.sample_set.id),
                    db.run.on(db.run.sample_set_id == db.sample_set.id)
                    ],
371 372 373 374 375 376 377 378 379 380 381 382 383
                orderby = ~db.patient.id|db.sequence_file.id|db.results_file.run_date,
                groupby = myGroupBy
            )

    ##filter
    if "filter" not in request.vars :
        request.vars["filter"] = ""
        
    for row in query :
        row.checked = False
        if (str(row.results_file.id) in request.vars["custom_list"]) :
            row.checked = True

384 385 386 387 388 389 390
        if row.patient.id is not None:
            row.names = vidjil_utils.anon_names(row.patient.id, row.patient.first_name, row.patient.last_name)
            info = row.patient.info
        else:
            row.names = row.run.name
            info = row.run.info
        row.string = [row.names, row.sequence_file.filename, str(row.sequence_file.sampling_date), str(row.sequence_file.pcr), str(row.config.name), str(row.results_file.run_date), info]
391 392 393 394 395 396 397 398 399 400 401
    query = query.find(lambda row : ( vidjil_utils.advanced_filter(row.string,request.vars["filter"]) or row.checked) )

    
    if config :
        query = query.find(lambda row : ( row.results_file.config_id==config_id or (str(row.results_file.id) in request.vars["custom_list"])) )
    
    log.debug("sample_set/custom (%.3fs) %s" % (time.time()-start, request.vars["filter"]))

    return dict(query=query,
                config_id=config_id,
                config=config)
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447

def confirm():
    if auth.can_modify_sample_set(request.vars["id"]):
        data = get_sample_set(request.vars["id"])
        log.debug('request sample_set deletion')
        return dict(message=T('confirm sample_set deletion'),
                    data=data)
    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

def delete():
    if (auth.can_modify_sample_set(request.vars["id"]) ):
        sample_set = get_sample_set(request.vars["id"])
        if sample_set is None:
            res = {"message": 'An error occured. This sample_set may have already been deleted'}
            log.error(res)
            return gluon.contrib.simplejson.dumps(res, separators=(',',':'))

        #delete data file
        query = db( (db.sample_set_membership.sample_set_id == sample_set.id)
                    & (db.sequence_file.id == db.sample_set_membership.sequence_file_id)
                ).select(db.sequence_file.id)
        for row in query :
            db(db.results_file.sequence_file_id == row.id).delete()

        #delete sequence file
        query = db((db.sequence_file.id == db.sample_set_membership.sequence_file_id)
            & (db.sample_set_membership.sample_set_id == sample_set.id)
            ).select(db.sequence_file.id)
        for row in query :
            db(db.sequence_file.id == row.id).delete()

        #delete patient sample_set
        db(db.sample_set.id == sample_set.id).delete()

        res = {"redirect": "sample_set/all",
               "success": "true",
               "message": "sample set ("+str(request.vars["id"])+") deleted"}
        log.info(res, extra={'user_id': auth.user.id, 'record_id': request.vars["id"], 'table_name': 'sample_set'})
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))
    else :
        res = {"message": ACCESS_DENIED}
        log.error(res)
        return gluon.contrib.simplejson.dumps(res, separators=(',',':'))