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

1import datetime 

2 

3from pydantic import BaseModel, ConfigDict, Field, field_validator 

4 

5from bbconf.const import DEFAULT_LICENSE 

6 

7from .base_models import FileModel 

8 

9 

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 

20 

21 model_config = ConfigDict(extra="ignore") 

22 

23 

24class BedFiles(BaseModel): 

25 bed_file: FileModel | None = None 

26 bigbed_file: FileModel | None = None 

27 

28 model_config = ConfigDict( 

29 populate_by_name=True, 

30 extra="ignore", 

31 ) 

32 

33 

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 

44 

45 header: str | None = None # Header of the bed file (if any) 

46 

47 model_config = ConfigDict(extra="ignore") 

48 

49 

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 

55 

56 exon_frequency: float | None = None 

57 exon_percentage: float | None = None 

58 

59 intron_frequency: float | None = None 

60 intron_percentage: float | None = None 

61 

62 intergenic_percentage: float | None = None 

63 intergenic_frequency: float | None = None 

64 

65 promotercore_frequency: float | None = None 

66 promotercore_percentage: float | None = None 

67 

68 fiveutr_frequency: float | None = None 

69 fiveutr_percentage: float | None = None 

70 

71 threeutr_frequency: float | None = None 

72 threeutr_percentage: float | None = None 

73 

74 promoterprox_frequency: float | None = None 

75 promoterprox_percentage: float | None = None 

76 

77 distributions: dict | None = None 

78 

79 model_config = ConfigDict(extra="ignore", populate_by_name=True) 

80 

81 

82class StandardMeta(BaseModel): 

83 """ 

84 Standardized Bed file metadata 

85 """ 

86 

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 = "" 

96 

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") 

106 

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 ) 

116 

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 

123 

124 original_file_name: str | None = Field(None, description="Original file name") 

125 

126 model_config = ConfigDict( 

127 populate_by_name=True, 

128 extra="ignore", 

129 alias_generator=None, 

130 ) 

131 

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") 

141 

142 

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 

153 

154 

155class UniverseMetadata(BaseModel): 

156 construct_method: str | None = None 

157 bedset_id: str | None = None 

158 

159 

160class BedSetMinimal(BaseModel): 

161 id: str 

162 name: str | None = None 

163 description: str | None = None 

164 bedfile_count: int = 0 

165 

166 

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 

173 

174 

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] 

182 

183 

184class QdrantSearchResult(BaseModel): 

185 id: str 

186 payload: dict = None 

187 score: float = None 

188 metadata: BedMetadataBasic | None = None 

189 

190 

191class BedListSearchResult(BaseModel): 

192 count: int 

193 limit: int 

194 offset: int 

195 results: list[QdrantSearchResult] | None = None 

196 

197 

198class TokenizedBedResponse(BaseModel): 

199 universe_id: str 

200 bed_id: str 

201 tokenized_bed: list[int] 

202 

203 

204class BedEmbeddingResult(BaseModel): 

205 identifier: str 

206 payload: dict 

207 embedding: list[float] 

208 

209 

210class TokenizedPathResponse(BaseModel): 

211 bed_id: str 

212 universe_id: str 

213 file_path: str 

214 endpoint_url: str 

215 

216 

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 

226 

227 model_config = ConfigDict(extra="forbid") 

228 

229 

230class RefGenValidReturnModel(BaseModel): 

231 id: str 

232 provided_genome: str | None = None 

233 compared_genome: list[RefGenValidModel] 

234 

235 

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]