Coverage for bbconf/models/bed_models.py: 98%
156 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 22:05 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 22:05 +0000
1import datetime
3from pydantic import BaseModel, ConfigDict, Field, field_validator
5from bbconf.const import DEFAULT_LICENSE
7from .base_models import FileModel
10class BedPlots(BaseModel):
11 chrombins: FileModel = None
12 gccontent: FileModel = None
13 partitions: FileModel = None
14 expected_partitions: FileModel = None
15 cumulative_partitions: FileModel = None
16 widths_histogram: FileModel = None
17 neighbor_distances: FileModel = None
18 open_chromatin: FileModel = None
19 tss_distance: FileModel = None
21 model_config = ConfigDict(extra="ignore")
24class BedFiles(BaseModel):
25 bed_file: FileModel | None = None
26 bigbed_file: FileModel | None = None
28 model_config = ConfigDict(
29 populate_by_name=True,
30 extra="ignore",
31 )
34class BedClassification(BaseModel):
35 name: str | None = None
36 genome_alias: str | None = None
37 genome_digest: str | None = None
38 bed_compliance: str = Field(
39 default="bed3", pattern=r"^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$"
40 )
41 data_format: str | None = None
42 compliant_columns: int = 3
43 non_compliant_columns: int = 0
45 header: str | None = None # Header of the bed file (if any)
47 model_config = ConfigDict(extra="ignore")
50class BedStatsModel(BaseModel):
51 number_of_regions: float | None = None
52 gc_content: float | None = None
53 median_tss_dist: float | None = None
54 mean_region_width: float | None = None
56 exon_frequency: float | None = None
57 exon_percentage: float | None = None
59 intron_frequency: float | None = None
60 intron_percentage: float | None = None
62 intergenic_percentage: float | None = None
63 intergenic_frequency: float | None = None
65 promotercore_frequency: float | None = None
66 promotercore_percentage: float | None = None
68 fiveutr_frequency: float | None = None
69 fiveutr_percentage: float | None = None
71 threeutr_frequency: float | None = None
72 threeutr_percentage: float | None = None
74 promoterprox_frequency: float | None = None
75 promoterprox_percentage: float | None = None
77 distributions: dict | None = None
79 model_config = ConfigDict(extra="ignore", populate_by_name=True)
82class StandardMeta(BaseModel):
83 """
84 Standardized Bed file metadata
85 """
87 species_name: str | None = Field(
88 default="",
89 description="Name of species. e.g. Homo sapiens.",
90 alias="organism",
91 )
92 species_id: str | None = ""
93 genotype: str | None = Field("", description="Genotype of the sample")
94 phenotype: str | None = Field("", description="Phenotype of the sample")
95 description: str | None = ""
97 cell_type: str | None = Field(
98 None,
99 description="specific kind of cell with distinct characteristics found in an organism. e.g. Neurons, Hepatocytes, Adipocytes",
100 )
101 cell_line: str | None = Field(
102 None,
103 description="population of cells derived from a single cell and cultured in the lab for extended use, e.g. HeLa, HepG2, k562",
104 )
105 tissue: str | None = Field(None, description="Tissue type")
107 library_source: str | None = Field(
108 None, description="Library source (e.g. genomic, transcriptomic)"
109 )
110 assay: str | None = Field(None, description="Experimental protocol (e.g. ChIP-seq)")
111 antibody: str | None = Field(None, description="Antibody used in the assay")
112 target: str | None = Field(None, description="Target of the assay (e.g. H3K4me3)")
113 treatment: str | None = Field(
114 None, description="Treatment of the sample (e.g. drug treatment)"
115 )
117 global_sample_id: list[str] | None = Field(
118 None, description="Global sample identifier. e.g. GSM000"
119 ) # excluded in training
120 global_experiment_id: list[str] | None = Field(
121 None, description="Global experiment identifier. e.g. GSE000"
122 ) # excluded in training
124 original_file_name: str | None = Field(None, description="Original file name")
126 model_config = ConfigDict(
127 populate_by_name=True,
128 extra="ignore",
129 alias_generator=None,
130 )
132 @field_validator("global_sample_id", "global_experiment_id", mode="before")
133 def ensure_list(cls, v: str | list[str]) -> list[str]:
134 if isinstance(v, str):
135 return [v]
136 elif isinstance(v, list):
137 return v
138 elif isinstance(v, type(None)):
139 return []
140 raise ValueError("values must be a string or a list of strings")
143class BedMetadataBasic(BedClassification):
144 id: str
145 name: str | None = ""
146 description: str | None = None
147 submission_date: datetime.datetime | None = None
148 last_update_date: datetime.datetime | None = None
149 is_universe: bool | None = False
150 license_id: str | None = DEFAULT_LICENSE
151 annotation: StandardMeta | None = None
152 processed: bool | None = True
155class UniverseMetadata(BaseModel):
156 construct_method: str | None = None
157 bedset_id: str | None = None
160class BedSetMinimal(BaseModel):
161 id: str
162 name: str | None = None
163 description: str | None = None
164 bedfile_count: int = 0
167class BedMetadataAll(BedMetadataBasic):
168 stats: BedStatsModel | None = None
169 plots: BedPlots | None = None
170 files: BedFiles | None = None
171 universe_metadata: UniverseMetadata | None = None
172 bedsets: list[BedSetMinimal] | None = None
175class BedListResult(BaseModel):
176 # Total matching records. Only computed on the first page (offset 0, no
177 # `after`); None on every other page so deep pages skip the COUNT(*).
178 count: int | None = None
179 limit: int
180 offset: int
181 results: list[BedMetadataBasic]
184class QdrantSearchResult(BaseModel):
185 id: str
186 payload: dict = None
187 score: float = None
188 metadata: BedMetadataBasic | None = None
191class BedListSearchResult(BaseModel):
192 count: int
193 limit: int
194 offset: int
195 results: list[QdrantSearchResult] | None = None
198class TokenizedBedResponse(BaseModel):
199 universe_id: str
200 bed_id: str
201 tokenized_bed: list[int]
204class BedEmbeddingResult(BaseModel):
205 identifier: str
206 payload: dict
207 embedding: list[float]
210class TokenizedPathResponse(BaseModel):
211 bed_id: str
212 universe_id: str
213 file_path: str
214 endpoint_url: str
217class RefGenValidModel(BaseModel):
218 provided_genome: str
219 compared_genome: str | None
220 genome_digest: str | None
221 xs: float = 0.0
222 oobr: float | None = None
223 sequence_fit: float | None = None
224 assigned_points: int
225 tier_ranking: int
227 model_config = ConfigDict(extra="forbid")
230class RefGenValidReturnModel(BaseModel):
231 id: str
232 provided_genome: str | None = None
233 compared_genome: list[RefGenValidModel]
236class VectorMetadata(BaseModel):
237 id: str
238 name: str
239 description: str
240 cell_line: str
241 cell_type: str
242 tissue: str
243 target: str
244 treatment: str
245 assay: str
246 genome_alias: str
247 genome_digest: str | None = None
248 species_name: str
249 # summary: str
250 # global_sample_id: str
251 # original_file_name: str
252 # embedding: List[float]