def test_bad_instance_none(self): """Test that instances with bad data aren't added.""" keywords = [ ('PatientID', 16), ('PatientName', 64), ('StudyInstanceUID', 64), ('StudyDate', 8), ('StudyTime', 14), ('AccessionNumber', 16), ('StudyID', 16), ('SeriesInstanceUID', 64), ('Modality', 16), #('SeriesNumber', None), ('SOPInstanceUID', 64), #('InstanceNumber', None), ] ds = Dataset() ds.PatientID = None ds.StudyInstanceUID = None ds.SeriesInstanceUID = None ds.SOPInstanceUID = None with pytest.raises(IntegrityError): db.add_instance(ds, self.session) self.session.rollback() assert not self.session.query(db.Instance).all()
def setup(self): """Run prior to each test""" engine = db.create('sqlite:///:memory:') pydicom.config.use_none_as_empty_text_VR_value = True self.session = sessionmaker(bind=engine)() for fname in DATASETS: fpath = os.path.join(DATA_DIR, fname) ds = dcmread(fpath) db.add_instance(ds, self.session)
def test_add_instance(self): """Test adding to the instance database.""" fpath = os.path.join(DATA_DIR, 'CTImageStorage.dcm') ds = dcmread(fpath) db.add_instance(ds, self.session) obj = self.session.query(db.Instance).all() assert 1 == len(obj) for kk, vv in DATASETS['CTImageStorage.dcm'].items(): assert vv == getattr(obj[0], kk)
def test_instance_exists(self): """Test that adding already existing instance updates it.""" db.add_instance(self.minimal, self.session) result = self.session.query(db.Instance).all() assert 1 == len(result) assert None == result[0].modality self.minimal.Modality = 'CT' db.add_instance(self.minimal, self.session) result = self.session.query(db.Instance).all() assert 1 == len(result) assert 'CT' == result[0].modality
def setup(self): """Run prior to each test""" engine = db.create('sqlite:///:memory:') pydicom.config.use_none_as_empty_text_VR_value = True self.session = sessionmaker(bind=engine)() ds = Dataset() ds.PatientID = '1234' ds.StudyInstanceUID = '1.2' ds.SeriesInstanceUID = '1.2.3' ds.SOPInstanceUID = '1.2.3.4' db.add_instance(ds, self.session) self.minimal = ds
def test_add_multiple_instances(self): """Test adding multiple data to the instance database.""" for fname in DATASETS: fpath = os.path.join(DATA_DIR, fname) ds = dcmread(fpath) db.add_instance(ds, self.session) obj = self.session.query(db.Instance).all() assert 5 == len(obj) obj = self.session.query(db.Instance, db.Instance.patient_name).all() names = [val[1] for val in obj] assert 'CompressedSamples^CT1' in names assert 'CompressedSamples^MR1' in names assert 'ANON^A^B^C^D' in names assert '^^^^' in names
def test_add_minimal(self): """Test adding a minimal dataset.""" db.add_instance(self.minimal, self.session) obj = self.session.query(db.Instance).all() assert 1 == len(obj) assert '1234' == obj[0].patient_id assert '1.2' == obj[0].study_instance_uid assert '1.2.3' == obj[0].series_instance_uid assert '1.2.3.4' == obj[0].sop_instance_uid rest = [ 'patient_name', 'study_date', 'study_time', 'accession_number', 'study_id', 'modality', 'series_number', 'instance_number', ] for attr in rest: assert getattr(obj[0], attr) is None
def test_bad_instance(self): """Test that instances with bad data aren't added.""" keywords = [ ('PatientID', 16), ('PatientName', 64), ('StudyInstanceUID', 64), ('StudyDate', 8), ('StudyTime', 14), ('AccessionNumber', 16), ('StudyID', 16), ('SeriesInstanceUID', 64), ('Modality', 16), #('SeriesNumber', None), ('SOPInstanceUID', 64), #('InstanceNumber', None), ] ds = self.minimal[:] for kw, max_len in keywords: setattr(ds, kw, 'a' * (max_len + 1)) with pytest.raises(AssertionError): db.add_instance(ds, self.session) assert not self.session.query(db.Instance).all()
def test_add_minimal(self): """Test adding a minimal dataset.""" db.add_instance(self.minimal, self.session) obj = self.session.query(db.Instance).all() assert 1 == len(obj) assert "1234" == obj[0].patient_id assert "1.2" == obj[0].study_instance_uid assert "1.2.3" == obj[0].series_instance_uid assert "1.2.3.4" == obj[0].sop_instance_uid rest = [ "patient_name", "study_date", "study_time", "accession_number", "study_id", "modality", "series_number", "instance_number", ] for attr in rest: assert getattr(obj[0], attr) is None
def handle_store(event, storage_dir, db_path, cli_config, logger): """Handler for evt.EVT_C_STORE. Parameters ---------- event : pynetdicom.events.Event The C-STORE request :class:`~pynetdicom.events.Event`. storage_dir : str The path to the directory where instances will be stored. db_path : str The database path to use with create_engine(). cli_config : dict A :class:`dict` containing configuration settings passed via CLI. logger : logging.Logger The application's logger. Returns ------- int or pydicom.dataset.Dataset The C-STORE response's *Status*. If the storage operation is successful but the dataset couldn't be added to the database then the *Status* will still be ``0x0000`` (Success). """ requestor = event.assoc.requestor timestamp = event.timestamp.strftime("%Y-%m-%d %H:%M:%S") addr, port = requestor.address, requestor.port logger.info(f"Received C-STORE request from {addr}:{port} at {timestamp}") try: ds = event.dataset # Remove any Group 0x0002 elements that may have been included ds = ds[0x00030000:] sop_instance = ds.SOPInstanceUID except Exception as exc: logger.error("Unable to decode the dataset") logger.exception(exc) # Unable to decode dataset return 0xC210 # Add the file meta information elements - must be before adding to DB ds.file_meta = event.file_meta logger.info(f"SOP Instance UID '{sop_instance}'") # Try and add the instance to the database # If we fail then don't even try to store fpath = os.path.join(storage_dir, sop_instance) db_dir = os.path.dirname(db_path) if os.path.exists(fpath): logger.warning( 'Instance already exists in storage directory, overwriting') try: ds.save_as(fpath, write_like_original=False) except Exception as exc: logger.error('Failed writing instance to storage directory') logger.exception(exc) # Failed - Out of Resources return 0xA700 logger.info("Instance written to storage directory") # Dataset successfully written, try to add to/update database engine = create_engine(db_path) with engine.connect() as conn: Session = sessionmaker(bind=engine) session = Session() try: # Path is relative to the database file matches = session.query(Instance).filter( Instance.sop_instance_uid == ds.SOPInstanceUID).all() add_instance(ds, session, os.path.abspath(fpath)) if not matches: logger.info("Instance added to database") else: logger.info("Database entry for instance updated") except Exception as exc: session.rollback() logger.error('Unable to add instance to the database') logger.exception(exc) finally: session.close() return 0x0000