def main(): parser = argparse.ArgumentParser(description='Copy Xnat projects') parser.add_argument('--source-host', type=six.text_type, required=True, help='source XNAT url') parser.add_argument('--source-project', type=six.text_type, required=True, help='source XNAT project') parser.add_argument('--dest-host', type=six.text_type, required=True, help='destination XNAT url') parser.add_argument('--dest-project', type=six.text_type, required=True, help='destination XNAT project') args = parser.parse_args() with xnat.connect(args.source_host) as source_xnat, xnat.connect( args.dest_host) as dest_xnat: # Find projects try: source_project = source_xnat.projects[args.source_project] dest_project = dest_xnat.projects[args.dest_project] except KeyError as error: print(error.message) else: # Create and start copier copier = XNATProjectCopier(source_xnat, source_project, dest_xnat, dest_project) copier.start()
def sync_alfred(): tmp_download_dir = app.config['TEMP_DOWNLOAD_DIR'] os.makedirs(tmp_download_dir, exist_ok=True) with xnat.connect(server=app.config['SOURCE_XNAT_URL'], user=app.config['SOURCE_XNAT_USER'], password=app.config['SOURCE_XNAT_PASSWORD']) as mbi_xnat: with xnat.connect( server=app.config['TARGET_XNAT_URL'], user=app.config['TARGET_XNAT_USER'], password=app.config['TARGET_XNAT_PASSWORD']) as alf_xnat: alf_project = alf_xnat.projects[app.config['TARGET_XNAT_PROJECT']] # noqa pylint: disable=no-member for img_session in ImgSession.ready_for_export(): mbi_session = mbi_xnat.experiments[img_session.xnat_id] # noqa pylint: disable=no-member try: alf_subject = alf_project.subjects[ img_session.subject.mbi_id] except KeyError: alf_subject = alf_xnat.classes.SubjectData( # noqa pylint: disable=no-member label=img_session.subject.mbi_id, parent=alf_project) alf_session = alf_xnat.classes.MrSessionData( # noqa pylint: disable=no-member label=img_session.id, parent=alf_subject) prev_exported = list(alf_session.scans.keys()) # Loop through clinically relevant scans that haven't been # exported and export for scan in img_session.scans: if scan.is_clinical and scan.xnat_id not in prev_exported: mbi_scan = mbi_session.scans[str(scan.xnat_id)] tmp_dir = op.join(tmp_download_dir, str(img_session.id)) mbi_scan.download_dir(tmp_dir) alf_scan = alf_xnat.classes.MrScanData( # noqa pylint: disable=no-member id=mbi_scan.id, type=mbi_scan.type, parent=alf_session) resource = alf_scan.create_resource('DICOM') files_dir = glob.glob( op.join(tmp_dir, '*', 'scans', '*', 'resources', 'DICOM', 'files'))[0] for fname in os.listdir(files_dir): resource.upload(op.join(files_dir, fname), fname) mbi_checksums = _get_checksums(mbi_xnat, mbi_scan) alf_checksums = _get_checksums(alf_xnat, alf_scan) if (mbi_checksums != alf_checksums): raise Exception( "Checksums do not match for uploaded scan {} " "from {} (to {}) XNAT session".format( mbi_scan.type, mbi_session.label, alf_session.label)) scan.exported = True db.session.commit() # pylint: disable=no-member shutil.rmtree(tmp_dir) # Trigger DICOM information extraction alf_xnat.put('/data/experiments/' + alf_session.id + # noqa pylint: disable=no-member '?pullDataFromHeaders=true')
def get_projects(page, user): project_dict = [] if (user): with xnat.connect(page, user=user, verify=False) as session: for p in session.projects.keys(): project_dict.append(p) else: with xnat.connect(page, verify=False) as session: for p in session.projects.keys(): project_dict.append(p) return project_dict
def main(): parser = argparse.ArgumentParser( description='download all data for a given session') parser.add_argument('--xnathost', type=unicode, required=True, help='xnat host name') parser.add_argument('--project', type=unicode, required=True, help='Project id') parser.add_argument('--session', type=unicode, required=True, help='session') parser.add_argument('--output_dir', type=unicode, required=False, default=True, help='outputdir') args = parser.parse_args() print('xnat host: {}'.format(args.xnathost)) print('project: {}'.format(args.project)) print('session: {}'.format(args.session)) print('output: {}'.format(args.output_dir)) with xnat.connect(args.xnathost) as connection: download_xnat_session_type(connection, args.project, args.session, args.output_dir)
def main(): parser = argparse.ArgumentParser( description='Prints all files from a certain scan.') parser.add_argument('--xnathost', type=unicode, required=True, help='xnat host name') parser.add_argument('--project', type=unicode, required=True, help='Project id') parser.add_argument('--subject', type=unicode, required=True, help='subject') parser.add_argument('--session', type=unicode, required=True, help='session') parser.add_argument('--scan', type=unicode, required=True, help='scan') parser.add_argument('--filter', type=unicode, required=False, default='.*', help='regex filter for file names') args = parser.parse_args() with xnat.connect(args.xnathost) as connection: xnat_files = get_files(connection, args.project, args.subject, args.session, args.scan) xnat_files = filter_files(xnat_files, args.filter) for file in xnat_files: print('{}'.format(file.name))
def xnat_collection(myWorkingDirectory, collectionURL, myProjectID): os.chdir(myWorkingDirectory) #connections to public collections do not require passwords with xnat.connect(collectionURL) as mySession: myProject = mySession.projects[myProjectID] mySubjectsList = myProject.subjects.values() for s in mySubjectsList: mySubjectID = s.label print('\nEntering subject ...' + mySubjectID) mySubject = myProject.subjects[mySubjectID] myExperimentsList = mySubject.experiments.values() for e in myExperimentsList: myExperimentID = e.label #print('\nEntering experiment ...' + myExperimentID) myExperiment = mySubject.experiments[myExperimentID] #the next line downloads each subject, experiment pair one-by-one into separate zip files myExperiment.download(myWorkingDirectory + '\\' + myProjectID + '_' + mySubjectID + '_' + myExperimentID + '.zip') # Unzip zip files download from XNAT files = os.listdir(os.curdir) for zip_name in files: zip_ref = zipfile.ZipFile(zip_name, 'r') zip_ref.extractall() zip_ref.close() #remove all zip file dir = os.curdir test = os.listdir(dir) for item in test: if item.endswith(".zip"): os.remove(os.path.join(dir, item))
def main(): parser = argparse.ArgumentParser( description='delete all data with a given session type') parser.add_argument('--xnathost', type=unicode, required=True, help='xnat host name') parser.add_argument('--project', type=unicode, required=True, help='Project id') parser.add_argument('--sessiontype', type=unicode, required=True, help='session') parser.add_argument('--dryrun', type=unicode, required=False, default=True, help='dryrun') args = parser.parse_args() print('xnat host: {}'.format(args.xnathost)) print('project: {}'.format(args.project)) print('session: {}'.format(args.session)) print('dryrun: {}'.format(args.dryrun)) with xnat.connect(args.xnathost) as connection: delete_xnat_session_type(connection, args.project, args.session, args.dryrun)
def download_all_datasets(download_dir, server, session_id, overwrite=True, **kwargs): with xnat.connect(server, **kwargs) as xnat_login: try: session = xnat_login.experiments[session_id] except KeyError: raise NiAnalysisMissingDataException( "Didn't find session matching '{}' on {}".format( session_id, server)) try: os.makedirs(download_dir) except OSError as e: if e.errno != errno.EEXIST: raise for dataset in session.scans.itervalues(): data_format_name = guess_data_format(dataset) ext = DataFormat.by_name(data_format_name).extension if ext is None: ext = '' download_path = os.path.join(download_dir, dataset.type + ext) if overwrite or not os.path.exists(download_path): download_resource(download_path, dataset, data_format_name, session.label) fields = {} for name, value in session.fields.items(): # Try convert to each datatypes in order of specificity to # determine type if name not in BUILTIN_XNAT_FIELDS: fields[name] = value with open(os.path.join(download_dir, FIELDS_FNAME), 'wb') as f: json.dump(fields, f)
def download_dataset(download_path, server, user, password, session_id, dataset_name, data_format=None): """ Downloads a single dataset from an XNAT server """ with xnat.connect(server, user=user, password=password) as xnat_login: try: session = xnat_login.experiments[session_id] except KeyError: raise NiAnalysisError( "Didn't find session matching '{}' on {}".format( session_id, server)) try: dataset = session.scans[dataset_name] except KeyError: raise NiAnalysisError( "Didn't find dataset matching '{}' in {}".format( dataset_name, session_id)) if data_format is None: data_format = guess_data_format(dataset) download_resource(download_path, dataset, data_format, session.label)
def xnat_loop(self): source_dom, source_u, source_pw = user_pass_data("Source") # source_dom = "http://xnatdev.xnat.org" # source_u = "admin" # source_pw = "" with xnat.connect(source_dom, user=source_u, password=source_pw) as connection: xnat_projects = connection.projects print(f"Found {len(xnat_projects)} projects in XNAT database.\n") with FancyBar('Analysing Database', max=len(xnat_projects)) as bar: for project in xnat_projects: xnat_subjects = xnat_projects[project].subjects for patient in xnat_subjects: xnat_experiments = xnat_subjects[patient].experiments for session in xnat_experiments: xnat_scans = xnat_experiments[session].scans for scan in xnat_scans: scan_data = xnat_scans[scan] self.sop_class_uid_check(scan_data) bar.next() date, time_slice = get_date_time() if self.report_table_list: self.write_report(date, time_slice) if self.log_list: self.write_log(date, time_slice)
def xnat_put(self, url='', file=None, imp=False, **kwargs): """ The method to create an XNAT object Uses the xnatpy session.put, session.upload, or session.services.import_ to add an object to XNAT. :param str url: a put route in the XNAT URI :param file object file: a file object to upload :param bool imp: whether to use the import service (True if file is zip of dicoms, otherwise False) :param kwargs kwargs: :return: None """ with xnat.connect(self.server, self.user, self.password) as session: try: if imp: file_path = os.path.join(self.file_dest, file.filename) file.save(file_path) session.services.import_(file_path, overwrite='delete', **kwargs) os.remove(file_path) # todo: need to call something like xnat_get to get the scan uri and return it to calling method elif file: session.upload(url, file) else: session.put(url) except: # todo # what should we do with errors? # probably depends on what the error is. if we don't succeed in uploading the file # we need to send a message back to the user # but some errors here could be recoverable. pass
def connect(self): """FUNCTION: connect PURPOSE: Making connection to the xnat server using xnatpy OUT: project and connection""" print('Establishing connection\n') config = self.config try: connection = xnat.connect(config.connection_name, user=config.user, password=config.pssw) project = connection.projects[config.project_name] logging.info("Connection established.") return project, connection except KeyError: print("Project not found in XNAT.\nExit") logging.critical("Project not found in XNAT.") if __name__ == "__main__": sys.exit() else: return None, None except Exception as e: print(str(e) + "\nExit") if __name__ == "__main__": logging.critical(e.message) sys.exit() else: return e, None
def _clean_up(self): # Clean up working dirs shutil.rmtree(self.cache_dir, ignore_errors=True) # Clean up session created for unit-test with xnat.connect(SERVER) as mbi_xnat: xproject = mbi_xnat.projects[self.PROJECT] for xsubject in list(xproject.subjects.itervalues()): xsubject.delete()
def setUp(self): test_fileset.TestDicomTagMatch.setUp(self) TestOnXnatMixin.setUp(self) # Set up DICOM headers with xnat.connect(SERVER) as login: xsess = login.projects[self.project].experiments['_'.join( (self.project, self.SUBJECT, self.VISIT))] login.put('/data/experiments/{}?pullDataFromHeaders=true'.format( xsess.id))
def main(): source_dom, source_u, source_pw = user_pass_data("Source") target_dom, target_u, target_pw = user_pass_data("Target") with xnat.connect(source_dom, user=source_u, password=source_pw) as subject_connection: while True: try: project_id = input( "Enter a project ID to mirror on the target XNAT instance: " ) xnat_project = subject_connection.projects[project_id] xnat_subjects = xnat_project.subjects print( f"Number of subjects found in project: {len(xnat_subjects)}" ) except KeyError: print( f"Project with ID \"{project_id}\" not found!\nPlease try again.\n" ) else: break dest_session.auth = (target_u, target_pw) with FancyBar('Copying Project...', max=len(xnat_subjects)) as bar: with xnat.connect(source_dom, user=source_u, password=source_pw) as connection: xnat_project = connection.projects[project_id] for patient in xnat_subjects: xnat_experiments = xnat_project.subjects[patient].experiments for session in xnat_experiments: xnat_scans = xnat_project.subjects[patient].experiments[ session].scans for scan in xnat_scans: temp_dir = Path("temp/") with tempfile.TemporaryDirectory( dir=temp_dir, prefix="project_mirror_") as dir_path: download(dir_path, xnat_scans, scan) upload(target_dom, dir_path) bar.next()
def make_dataset_XNAT(project, opt, phase): session = xnat.connect('http://rufus.stanford.edu', user='******', password='******') #make XNAT connection #xnat version of make_dataset_dicom() images = [] #parsing xnat hierarchy: project -> subject -> experiment -> scan -> dicom img subjs = session.projects[project].subjects try: set_start_method('spawn') except RuntimeError: pass #multiprocessing code (not working) ------------ pool = Pool(os.cpu_count()) images = pool.map(process_subj, [subjs[s] for s in subjs]) images = [i for im in images for i in im] #----------------------------------------------- #original code (before multiproc, works fine) ------------------- ''' for s in subjs: exps = subjs[s].experiments for e in exps: scans = exps[e].scans for sc in scans: my_file = scans[sc].resources['DICOM'].files[0] fname = my_file.data['Name'] path = my_file.uri with my_file.open() as f: dicom = pydicom.read_file(f) #save images whose filenames are in phase if fname.endswith('.dcm'): try: opt.names_phase[fname] except: print('Error: we donot find the phase for file name' , fname, 'ignore this file') continue # sys.exit(3) if opt.names_phase[fname] == phase: Img = process_dicom(dicom) if Img is not None: print("x" + fname) images.append([path, dicom]) #each image list item has filename + FileData obj ''' #------------------------------------------------- session.disconnect() return images
def connect(): for host in hosts: try: session[0] = xnat.connect(host, user=username, password=password) hosts[:] = [host] break except Exception as e: error[0] = e if cancelled[0]: break
def _create_project(self, project_name=None): if project_name is None: project_name = self.project if SERVER == 'https://mbi-xnat.erc.monash.edu.au': raise ArcanaError( "Shouldn't be creating projects on the production " "server") with xnat.connect(SERVER) as login: uri = '/data/archive/projects/{}'.format(project_name) query = {'xsiType': 'xnat:projectData', 'req_format': 'qa'} response = login.put(uri, query=query) if response.ok: logger.info("Created test project '{}'".format(project_name))
def connect(self): """ Parameters ---------- prev_login : xnat.XNATSession An XNAT login that has been opened in the code that calls the method that calls login. It is wrapped in a NoExitWrapper so the returned connection can be used in a "with" statement in the method. """ sess_kwargs = {} if self._user is not None: sess_kwargs['user'] = self._user if self._password is not None: sess_kwargs['password'] = self._password self._login = xnat.connect(server=self._server, **sess_kwargs)
def __call__(self, data): d = dict(data) for key in self.keys: if key in data: for action in self.actions: """loops over actions in action list, if no action is triggered then raise a warning actions are functions that return any of projects, subjects, experiments, scans, or resources XNAT object along with a key to be used in the data dictionary""" with xnat.connect( server=self.xnat_configuration['server'], user=self.xnat_configuration['user'], password=self.xnat_configuration['password'], ) as session: "connect session to subject uri" subject_obj = session.create_object(d['subject_uri']) "perform action on subject object" xnat_obj, image_label = action(subject_obj) with tempfile.TemporaryDirectory() as tmpdirname: "download image from XNAT" session_obj = session.create_object(xnat_obj.uri) session_obj.download_dir(tmpdirname) images_path = glob.glob(os.path.join( tmpdirname, '**/*' + self.expected_filetype), recursive=True) "find unique directories in list of image paths" image_dirs = list( set( os.path.dirname(image_path) for image_path in images_path)) if len(image_dirs) > 1: raise ValueError( f'More than one image series found in {images_path}' ) image, meta = self.image_loader()(image_dirs[0]) d[image_label] = image d[image_label + '_meta'] = meta return d
def _cached_xnat(xnat_url, project_name): if ( xnat_url, project_name, ) in _xnat_sessions: return _xnat_sessions[( xnat_url, project_name, )] session = xnat.connect(xnat_url) project = session.projects[project_name] _xnat_sessions[( xnat_url, project_name, )] = project return project
def validate_xnat_id(self, field): if self.status.data == PRESENT: with xnat.connect( server=app.config['SOURCE_XNAT_URL'], user=app.config['SOURCE_XNAT_USER'], password=app.config['SOURCE_XNAT_PASSWORD']) as mbi_xnat: try: exp = mbi_xnat.experiments[self.xnat_id.data] # noqa pylint: disable=no-member except KeyError: raise ValidationError( "Did not find '{}' XNAT session, please correct or " "select a different status (i.e. other than '{}')". format(self.xnat_id.data, DATA_STATUS[PRESENT][1])) else: # Update the scans listed against the XNAT session. self.new_scan_types = [(s.id, s.type) for s in exp.scans.values()]
def xget(credentials=None, project=None, dicom_dir=None, filter=None): """Pull and Compress data from a given XNAT project. Keyword arguments: credentials -- path to file containing XNAT login information. project -- name of project as it appears on XNAT (e.g. McMakin_EMU). dicom_dir -- path to local directory to store pulled dicoms. _filter -- regex to filter out certain subjects. """ if not filter: filter = r'([\w\W]+)' # Grab any file from project previous_subjs = {} os.makedirs(dicom_dir, exist_ok=True) subjs_json = dicom_dir + '/downloaded_subjects.json' credentials = _json_load(credentials) previous_subjs = {} if os.path.isfile(subjs_json): previous_subjs = _json_load(subjs_json) # Creates XNAT session and looks for scans not already grabbed from XNAT, # then ends session once completed session = xnat.connect(credentials['server'], user=credentials['user'], password=credentials['password']) project_data = session.projects[project] for subject in project_data.subjects: subject_data = session.projects[project].subjects[subject] if not re.search(filter, subject_data.label): continue if subject_data.label not in previous_subjs.keys(): previous_subjs[subject_data.label] = [] for exp in subject_data.experiments: exp_data = subject_data.experiments[exp] if exp_data.label not in previous_subjs[subject_data.label]: previous_subjs[subject_data.label].append(exp_data.label) print(exp_data.label) exp_data.download_dir(dicom_dir) _add_to_tar(dicom_dir + '/' + exp_data.label + '.tar.gz', dicom_dir + '/' + exp_data.label + '/scans/') shutil.rmtree(dicom_dir + '/' + exp_data.label) session.disconnect() # Dumps json with any newly scans grabbed and tarred from XNAT with open(subjs_json, 'w') as dump_file: json.dump(previous_subjs, dump_file, indent=4)
def xnat_build_dataset(xnat_configuration, minimal=True): """ Builds a dictionary that describes the XNAT project dataset using XNAT data hierarchy: project/subject/experiment/scan minimal: if True, only the minimal information is returned, i.e. the subject ID and the SubjectData e.g. [ { subjectid: '1', subject_uri: '<unique address to subject in xnat archive>' experiment_1: { scan_1: {scan_object}, scan_2: {scan_object} }, experiment_2: { scan_1: {scan_object} } } ] """ with xnat.connect(server=xnat_configuration['server'], user=xnat_configuration['user'], password=xnat_configuration['password']) as session: project = session.projects[xnat_configuration["project"]] dataset = [] for subject in project.subjects: data_series = {'subject_id': subject, 'subject_uri': project.subjects[subject].uri} if not minimal: for experiment in project.subjects[subject].experiments: scan_dict = {} for scan in project.subjects[subject].experiments[experiment].scans: scan_dict['modality'] = project.subjects[subject].experiments[experiment].modality scan_dict[project.subjects[subject].experiments[experiment].scans[scan].series_description] = project.subjects[subject].experiments[experiment].scans[scan] data_series[project.subjects[subject].experiments[experiment].label] = scan_dict dataset.append(data_series) return dataset
def download_project(project_name, xnat_url, datafolder, nsubjects=10, verbose=True): # Connect to XNAT and retreive project session = xnat.connect(xnat_url) project = session.projects[project_name] # Create the data folder if it does not exist yet datafolder = os.path.join(datafolder, project_name) if not os.path.exists(datafolder): os.makedirs(datafolder) subjects_len = len(project.subjects) if nsubjects == 'all': nsubjects = subjects_len else: nsubjects = min(nsubjects, subjects_len) subjects_counter = 1 downloaded_subjects_counter = 0 for s in range(0, subjects_len): s = project.subjects[s] print(f'Working on subject {subjects_counter}/{subjects_len}') subjects_counter += 1 success = download_subject(project_name, s, datafolder, session, verbose) if success: downloaded_subjects_counter += 1 # Stop downloading if we have reached the required number of subjects if downloaded_subjects_counter == nsubjects: break # Disconnect the session session.disconnect() if downloaded_subjects_counter < nsubjects: raise ValueError( f'Number of subjects downloaded {downloaded_subjects_counter} is smaller than the number required {nsubjects}.' ) print('Done downloading!')
def classify(sessionUri): errors = False with xnat.connect(os.environ['XNAT_HOST'], user=os.environ['XNAT_USER'], password=os.environ['XNAT_PASS']) as connection: session = connection.create_object('/data' + sessionUri) for scan in session.scans.values(): try: print('Reading scan ', scan.id, flush=True) dcm = scan.read_dicom(read_pixel_data=True) modality = dcm.get("Modality") if not modality: print('Unknown modality, skipping', flush=True) continue classification = {} series_desc = format_string(dcm.get("SeriesDescription", "")) if series_desc: if dcm.get("Modality") == "MR": classification = classification_from_label.infer_classification(series_desc) print("Inferred classification from SeriesDescription: ", classification, flush=True) # If no pixel data present, make classification intent "Non-Image" if not hasattr(dcm, "PixelData"): non_image_intent = 'Non-Image' # If intent not present, add it with nonimage_intent if 'Intent' not in classification: classification['Intent'] = [non_image_intent] else: # Otherwise append non-image if not in Intent if non_image_intent not in classification['Intent']: classification['Intent'].append(non_image_intent) # add fields to scan xnat_type = 'xnat:{}ScanData'.format(translate_modality(modality)) query_params = {'xsiType': xnat_type} for key in classification: qp_key = '{}/parameters/addParam[name=classification_{}]/addField'.format(xnat_type, key.lower()) query_params[qp_key] = ' '.join(classification[key]) r = connection.put(scan.uri, query=query_params) r.raise_for_status() except Exception as e: print("Error for scan {}".format(scan.id), flush=True) printErr(str(e)) errors = True
def xnat_collection(myWorkingDirectory,collectionURL,myProjectID): os.chdir(myWorkingDirectory) #connections to public collections do not require passwords with xnat.connect(collectionURL) as mySession: myProject= mySession.projects[myProjectID] mySubjectsList = myProject.subjects.values() for s in mySubjectsList: mySubjectID = s.label print('\nEntering subject ...' + mySubjectID) mySubject = myProject.subjects[mySubjectID] myExperimentsList = mySubject.experiments.values() for e in myExperimentsList: myExperimentID = e.label #print('\nEntering experiment ...' + myExperimentID) myExperiment = mySubject.experiments[myExperimentID] #the next line downloads each subject, experiment pair one-by-one into separate zip files #myExperiment.download(myWorkingDirectory + '\\' + myProjectID + '_' + mySubjectID + '_' + myExperimentID + '.zip') myExperiment.download(myWorkingDirectory + '\\' + myExperimentID + '.zip') return
def setup(self): self.test_batch_size = 1 self.xnat_configuration = { 'server': 'http://localhost:80', 'user': '******', 'password': '******', 'project': 'TEST_MLOPS' } # create test project and push test data with xnat.connect( server=self.xnat_configuration['server'], user=self.xnat_configuration['user'], password=self.xnat_configuration['password'], ) as session: xnat_projects_url = self.xnat_configuration[ 'server'] + '/data/projects' # Set the name of the XML file. headers = {'Content-Type': 'text/xml'} # Open the XML file. with open('tests/data/xnat/test_project_setup.xml') as xml: r = requests.post(xnat_projects_url, data=xml, headers=headers, auth=HTTPBasicAuth( self.xnat_configuration['user'], self.xnat_configuration['password'])) # push data to new project try: session.services.import_( 'tests/data/test_dicoms.zip', project=self.xnat_configuration['project'], subject='1', experiment='MR_TEST_EXPERIMENT') except XNATUploadError as e: print(f'Test subject already exists {e}') self.test_data = xnat_build_dataset(self.xnat_configuration)
def main(): args = app_args() # Getting experiment data sess = xnat.connect(args.host, args.user, args.passwd) experiment = sess.experiments[args.session] # Checking each scan for scan in experiment.scans.values(): bidsname = infotodict(scan) print( '{} - {} ({}) | bidsname: {}'.format(scan.id, scan.type, scan.series_description, bidsname)) is_anat = str(bidsname).startswith('ANAT') scan_dir = download_scan(scan) # Converting and saving NIFTI files if args.save_nifti or (args.deface and is_anat): # DICOM files not found if not os.path.isdir(scan_dir): continue nifti_dir = '/tmp/{}'.format(scan.id) os.mkdir(nifti_dir) subprocess.call(["dcm2niix", "-o", nifti_dir, "-z", "y", "-f", r"%p_%s", scan_dir]) if is_anat and args.deface: subprocess.call(["./deface.sh", nifti_dir]) if is_derived(nifti_dir): bidsname = 'DERIVATIVES' # Compressing folder and sending it to XNAT subprocess.call(["./send_nii.sh", nifti_dir, args.host]) # Remove DICOMs when NIFTIs were saved if args.save_nifti and args.remove_dicoms: sess.delete('/data/archive/experiments/{}/scans/{}/resources/{}'.format(args.session, scan.id, scan_dir)) # Renaming, if necessary if args.rename_types and bidsname and scan.type != bidsname: print('renaming...') scan.type = bidsname subprocess.call(['rm', '-rf', '/tmp/*'])
def async_xnat_update(xnat_url, user, password, xnat_archive, exp_name, series_num, comment, quality): """Push usability data into XNAT. This will update XNAT in a separate thread to reduce waiting time for the user. Because it will run in another thread, database objects cannot be passed in as arguments. Args: xnat_url (str): The full URL to use for the XNAT server. user (str): The user to log in as. password (str): The password to log in with. xnat_archvie (str): The name of the XNAT archive that contains the experiment. exp_name (str): The name of the experiment on XNAT. series_num (int): The series number of the file to update. comment (str): The user's QC comment. quality (str): The quality label to apply based on whether data has been flagged, blacklisted or approved. """ with xnat.connect(xnat_url, user=user, password=password) as xcon: project = xcon.projects[xnat_archive] xnat_exp = project.experiments[exp_name] matched = [ item for item in xnat_exp.scans[:] if item.id == str(series_num) ] if not matched or len(matched) > 1: logger.error(f"Couldn't locate {exp_name} on XNAT server. " "Usability will not be updated.") return xnat_scan = matched[0] xnat_scan.quality = quality if comment: # XNAT max comment length is 255 chars safe_comment = comment if len(quote(comment)) < 255 \ else unquote(quote(comment)[0:243]) + " [...]" xnat_scan.note = safe_comment
def connect(self, verify=True, debug=False, loglevel=None): self._debug = debug self._xnat = xnat.connect(self._server, user=self._user, password=self._password, verify=verify, debug=debug, loglevel=loglevel) return self._xnat