async def get_all_sample_id_map_by_internal( connection: Connection = get_project_readonly_connection, ): """Get map of ALL sample IDs, { [internal_id]: external_sample_id }""" st = SampleLayer(connection) assert connection.project result = await st.get_all_sample_id_map_by_internal_ids( project=connection.project) return {sample_id_format(k): v for k, v in result.items()}
async def get_history_of_sample( id_: str, connection: Connection = get_projectless_db_connection): """Get full history of sample from internal ID""" st = SampleLayer(connection) internal_id = sample_id_transform_to_raw(id_) result = await st.get_history_of_sample(internal_id) return result
async def get_sample_by_external_id( external_id: str, connection: Connection = get_project_readonly_connection): """Get sample by external ID""" st = SampleLayer(connection) assert connection.project result = await st.get_single_by_external_id(external_id, project=connection.project) return result
async def get_sample_id_map_by_external( external_ids: List[str], allow_missing: bool = False, connection: Connection = get_project_readonly_connection, ): """Get map of sample IDs, { [externalId]: internal_sample_id }""" st = SampleLayer(connection) result = await st.get_sample_id_map_by_external_ids( external_ids, allow_missing=(allow_missing or False)) return {k: sample_id_format(v) for k, v in result.items()}
async def setUp(self) -> None: # don't need to await because it's tagged @run_as_sync super().setUp() sl = SampleLayer(self.connection) self.al = AnalysisLayer(self.connection) await sl.insert_sample( 'Test01', SampleType.BLOOD, meta={'meta': 'meta ;)'}, active=True, )
async def get_sample_id_map_by_internal( internal_ids: List[str], connection: Connection = get_projectless_db_connection, ): """ Get map of sample IDs, { [internal_id]: external_sample_id } Without specifying a project, you might see duplicate external identifiers """ st = SampleLayer(connection) internal_ids_raw = sample_id_transform_to_raw_list(internal_ids) result = await st.get_sample_id_map_by_internal_ids(internal_ids_raw) return {sample_id_format(k): v for k, v in result.items()}
async def test_add_sample(self): """Test inserting a sample""" sl = SampleLayer(self.connection) s = await sl.insert_sample( 'Test01', SampleType.BLOOD, active=True, meta={'meta': 'meta ;)'}, ) samples = await self.connection.connection.fetch_all( 'SELECT id, type, meta, project FROM sample') self.assertEqual(1, len(samples)) s = samples[0] self.assertEqual(1, s['id'])
async def update_sample( id_: str, model: SampleUpdateModel, connection: Connection = get_projectless_db_connection, ): """Update sample with id""" st = SampleLayer(connection) result = await st.update_sample( id_=sample_id_transform_to_raw(id_), meta=model.meta, participant_id=model.participant_id, type_=model.type, active=model.active, ) return result
async def create_new_sample( sample: NewSample, connection: Connection = get_project_write_connection) -> str: """Creates a new sample, and returns the internal sample ID""" st = SampleLayer(connection) async with connection.connection.transaction(): internal_id = await st.insert_sample( external_id=sample.external_id, sample_type=sample.type, active=True, meta=sample.meta, participant_id=sample.participant_id, # already checked on get_project_write_connection check_project_id=False, ) return sample_id_format(internal_id)
async def merge_samples( id_keep: str, id_merge: str, connection: Connection = get_projectless_db_connection, ): """ Merge one sample into another, this function achieves the merge by rewriting all sample_ids of {id_merge} with {id_keep}. You must carefully consider if analysis objects need to be deleted, or other implications BEFORE running this method. """ st = SampleLayer(connection) result = await st.merge_samples( id_keep=sample_id_transform_to_raw(id_keep), id_merge=sample_id_transform_to_raw(id_merge), ) return result
async def batch_upsert_samples( samples: SampleBatchUpsertBody, connection: Connection = get_project_write_connection, ) -> Dict[str, Any]: """Upserts a list of samples with sequences, and returns the list of internal sample IDs""" # Convert id in samples to int for sample in samples.samples: if sample.id: sample.id = sample_id_transform_to_raw(sample.id) async with connection.connection.transaction(): # Table interfaces st = SampleLayer(connection) results = await st.batch_upsert_samples(samples) # Map sids back from ints to strs for iid, seqs in results.items(): data = {'sample_id': sample_id_format(iid), 'sequences': seqs} results[iid] = data return results
async def batch_upsert_participants(self, participants: ParticipantUpsertBody): """Batch upsert a list of participants with sequences""" all_participants = participants.participants sampt: SampleLayer = SampleLayer(self.connection) # Create or update participants pids = [await self.upsert_participant(p) for p in all_participants] # Pull a list of external pids epids = [ str(participant.external_id) for participant in all_participants ] # Get map of external pids to internal pids epid_ipid_map = await self.get_id_map_by_external_ids( epids, project=self.connection.project, allow_missing=False, ) for participant in all_participants: epid = participant.external_id ipid = epid_ipid_map[epid] for sample in participant.samples: sample.participant_id = ipid # Upsert all samples with sequences for each participant samples = [ SampleBatchUpsertBody(samples=p.samples) for p in all_participants ] results = [await sampt.batch_upsert_samples(s) for s in samples] # Format and return response return dict(zip(pids, results))
async def get_samples_by_criteria( sample_ids: List[str] = None, meta: Dict = None, participant_ids: List[int] = None, project_ids: List[str] = None, active: bool = Body(default=True), connection: Connection = get_projectless_db_connection, ): """ Get list of samples (dict) by some mixture of (AND'd) criteria """ st = SampleLayer(connection) pt = ProjectPermissionsTable(connection.connection) pids: Optional[List[int]] = None if project_ids: pids = await pt.get_project_ids_from_names_and_user(connection.author, project_ids, readonly=True) sample_ids_raw = sample_id_transform_to_raw_list( sample_ids) if sample_ids else None result = await st.get_samples_by( sample_ids=sample_ids_raw, meta=meta, participant_ids=participant_ids, project_ids=pids, active=active, check_project_ids=True, ) for sample in result: sample.id = sample_id_format(sample.id) return result