@weng-lab/genomebrowser-ui 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/TrackSelect/Folders/biosamples/data/human.json.d.ts +1888 -105
- package/dist/TrackSelect/Folders/biosamples/data/mouse.json.d.ts +359 -2
- package/dist/TrackSelect/Folders/biosamples/shared/types.d.ts +3 -2
- package/dist/genomebrowser-ui.es.js +219 -218
- package/dist/genomebrowser-ui.es.js.map +1 -1
- package/package.json +1 -1
- package/src/TrackSelect/Folders/biosamples/data/human.json +1888 -105
- package/src/TrackSelect/Folders/biosamples/data/mouse.json +359 -1
- package/src/TrackSelect/Folders/biosamples/shared/columns.tsx +14 -16
- package/src/TrackSelect/Folders/biosamples/shared/createFolder.ts +2 -2
- package/src/TrackSelect/Folders/biosamples/shared/types.ts +4 -2
- package/src/TrackSelect/Folders/biosamples/data/formatBiosamples.go +0 -254
- package/src/TrackSelect/Folders/biosamples/data/mark_core.go +0 -158
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
useGridApiContext,
|
|
6
6
|
} from "@mui/x-data-grid-premium";
|
|
7
7
|
import { Stack, capitalize } from "@mui/material";
|
|
8
|
-
import Check from "@mui/icons-material/Check";
|
|
9
8
|
import { AssayIcon, ontologyTypes, assayTypes, lifeStages } from "./constants";
|
|
10
|
-
import { BiosampleRowInfo } from "./types";
|
|
9
|
+
import { BiosampleRowInfo, CollectionType } from "./types";
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
const collectionTypes: CollectionType[] = ["Core", "Ancillary", "Partial"];
|
|
12
|
+
|
|
13
|
+
function CollectionCell(params: GridRenderCellParams<BiosampleRowInfo>) {
|
|
13
14
|
const apiRef = useGridApiContext();
|
|
14
15
|
|
|
15
16
|
if (params.rowNode.type !== "group") {
|
|
@@ -30,11 +31,7 @@ function CoreCollectionCell(params: GridRenderCellParams<BiosampleRowInfo>) {
|
|
|
30
31
|
childIds[0],
|
|
31
32
|
) as BiosampleRowInfo | null;
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
return <Check color="primary" />;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return null;
|
|
34
|
+
return firstChildRow?.collection ?? null;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
const displayNameCol: GridColDef<BiosampleRowInfo> = {
|
|
@@ -140,12 +137,13 @@ const lifeStageCol: GridColDef<BiosampleRowInfo> = {
|
|
|
140
137
|
valueFormatter: (value) => value && capitalize(value),
|
|
141
138
|
};
|
|
142
139
|
|
|
143
|
-
const
|
|
144
|
-
field: "
|
|
145
|
-
headerName: "
|
|
146
|
-
type: "
|
|
147
|
-
|
|
148
|
-
|
|
140
|
+
const collectionCol: GridColDef<BiosampleRowInfo> = {
|
|
141
|
+
field: "collection",
|
|
142
|
+
headerName: "Collection",
|
|
143
|
+
type: "singleSelect",
|
|
144
|
+
valueOptions: collectionTypes,
|
|
145
|
+
width: 100,
|
|
146
|
+
renderCell: (params) => <CollectionCell {...params} />,
|
|
149
147
|
};
|
|
150
148
|
|
|
151
149
|
const experimentCol: GridColDef<BiosampleRowInfo> = {
|
|
@@ -167,7 +165,7 @@ const idCol: GridColDef<BiosampleRowInfo> = {
|
|
|
167
165
|
export const sortedByAssayColumns: GridColDef<BiosampleRowInfo>[] = [
|
|
168
166
|
displayNameCol,
|
|
169
167
|
sortedByAssayOntologyCol,
|
|
170
|
-
|
|
168
|
+
collectionCol,
|
|
171
169
|
sampleTypeCol,
|
|
172
170
|
lifeStageCol,
|
|
173
171
|
sortedByAssayAssayCol,
|
|
@@ -179,7 +177,7 @@ export const sortedByAssayColumns: GridColDef<BiosampleRowInfo>[] = [
|
|
|
179
177
|
/** Default columns (ontology as top-level grouping) */
|
|
180
178
|
export const defaultColumns: GridColDef<BiosampleRowInfo>[] = [
|
|
181
179
|
defaultAssayCol,
|
|
182
|
-
|
|
180
|
+
collectionCol,
|
|
183
181
|
sampleTypeCol,
|
|
184
182
|
lifeStageCol,
|
|
185
183
|
defaultOntologyCol,
|
|
@@ -24,7 +24,7 @@ import { BiosampleTreeItem } from "./BiosampleTreeItem";
|
|
|
24
24
|
* @returns Array of flattened BiosampleRowInfo objects, one per assay
|
|
25
25
|
*/
|
|
26
26
|
function flattenTrackIntoRows(track: BiosampleTrackInfo): BiosampleRowInfo[] {
|
|
27
|
-
const { ontology, lifeStage, sampleType, displayName,
|
|
27
|
+
const { ontology, lifeStage, sampleType, displayName, collection } = track;
|
|
28
28
|
|
|
29
29
|
// Sort assays so cCRE comes first, then maintain original order for the rest
|
|
30
30
|
const sortedAssays = [...track.assays].sort((a, b) => {
|
|
@@ -46,7 +46,7 @@ function flattenTrackIntoRows(track: BiosampleTrackInfo): BiosampleRowInfo[] {
|
|
|
46
46
|
experimentAccession,
|
|
47
47
|
fileAccession,
|
|
48
48
|
url,
|
|
49
|
-
|
|
49
|
+
collection,
|
|
50
50
|
}),
|
|
51
51
|
);
|
|
52
52
|
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Types for biosample folder data
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
export type CollectionType = "Core" | "Ancillary" | "Partial";
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Assay information from the JSON data
|
|
7
9
|
*/
|
|
@@ -23,7 +25,7 @@ export type BiosampleTrackInfo = {
|
|
|
23
25
|
sampleType: string;
|
|
24
26
|
displayName: string;
|
|
25
27
|
assays: BiosampleAssayInfo[];
|
|
26
|
-
|
|
28
|
+
collection: CollectionType;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -39,7 +41,7 @@ export type BiosampleRowInfo = {
|
|
|
39
41
|
experimentAccession: string;
|
|
40
42
|
fileAccession: string;
|
|
41
43
|
url: string;
|
|
42
|
-
|
|
44
|
+
collection: CollectionType;
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
/**
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"fmt"
|
|
6
|
-
"os"
|
|
7
|
-
"path"
|
|
8
|
-
"strings"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
type RNASeqTrack struct {
|
|
12
|
-
ID string `json:"id"`
|
|
13
|
-
Title string `json:"title"`
|
|
14
|
-
URL string `json:"url"`
|
|
15
|
-
RNASeqExperimentAccession string `json:"rnaseq_experiment_accession"`
|
|
16
|
-
RNASeqFileAccession string `json:"rnaseq_file_accession"`
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type OldBiosample struct {
|
|
20
|
-
Name string `json:"name"`
|
|
21
|
-
Ontology string `json:"ontology"`
|
|
22
|
-
LifeStage string `json:"lifeStage"`
|
|
23
|
-
SampleType string `json:"sampleType"`
|
|
24
|
-
DisplayName string `json:"displayName"`
|
|
25
|
-
DNaseExperimentAccession *string `json:"dnase_experiment_accession"`
|
|
26
|
-
H3K4Me3ExperimentAccession *string `json:"h3k4me3_experiment_accession"`
|
|
27
|
-
H3K27AcExperimentAccession *string `json:"h3k27ac_experiment_accession"`
|
|
28
|
-
CTCFExperimentAccession *string `json:"ctcf_experiment_accession"`
|
|
29
|
-
ATACExperimentAccession *string `json:"atac_experiment_accession"`
|
|
30
|
-
DNaseFileAccession *string `json:"dnase_file_accession"`
|
|
31
|
-
H3K4Me3FileAccession *string `json:"h3k4me3_file_accession"`
|
|
32
|
-
H3K27AcFileAccession *string `json:"h3k27ac_file_accession"`
|
|
33
|
-
CTCFFileAccession *string `json:"ctcf_file_accession"`
|
|
34
|
-
ATACFileAccession *string `json:"atac_file_accession"`
|
|
35
|
-
DNaseSignalURL string `json:"dnase_signal_url,omitempty"`
|
|
36
|
-
H3K4Me3SignalURL string `json:"h3k4me3_signal_url,omitempty"`
|
|
37
|
-
H3K27AcSignalURL string `json:"h3k27ac_signal_url,omitempty"`
|
|
38
|
-
CTCFSignalURL string `json:"ctcf_signal_url,omitempty"`
|
|
39
|
-
ATACSignalURL string `json:"atac_signal_url,omitempty"`
|
|
40
|
-
ChromHMM string `json:"chromhmm,omitempty"`
|
|
41
|
-
ChromHMMURL string `json:"chromhmm_url,omitempty"`
|
|
42
|
-
RNASeqTracks []RNASeqTrack `json:"rna_seq_tracks"`
|
|
43
|
-
BigBedURL string `json:"bigbedurl,omitempty"`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type Assay struct {
|
|
47
|
-
ID string `json:"id"`
|
|
48
|
-
Assay string `json:"assay"`
|
|
49
|
-
URL string `json:"url"`
|
|
50
|
-
ExperimentAccession string `json:"experimentAccession"`
|
|
51
|
-
FileAccession string `json:"fileAccession"`
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
type NewBiosample struct {
|
|
55
|
-
Name string `json:"name"`
|
|
56
|
-
Ontology string `json:"ontology"`
|
|
57
|
-
LifeStage string `json:"lifeStage"`
|
|
58
|
-
SampleType string `json:"sampleType"`
|
|
59
|
-
DisplayName string `json:"displayName"`
|
|
60
|
-
Assays []Assay `json:"assays"`
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
func main() {
|
|
64
|
-
if len(os.Args) < 3 {
|
|
65
|
-
fmt.Println("Usage: go run format.go <input.json> <output.json>")
|
|
66
|
-
os.Exit(1)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
inputFile := os.Args[1]
|
|
70
|
-
outputFile := os.Args[2]
|
|
71
|
-
|
|
72
|
-
data, err := os.ReadFile(inputFile)
|
|
73
|
-
if err != nil {
|
|
74
|
-
fmt.Printf("Error reading input file: %v\n", err)
|
|
75
|
-
os.Exit(1)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
var inputWrapper struct {
|
|
79
|
-
Data struct {
|
|
80
|
-
CCREBiosampleQuery struct {
|
|
81
|
-
Biosamples []OldBiosample `json:"biosamples"`
|
|
82
|
-
} `json:"ccREBiosampleQuery"`
|
|
83
|
-
} `json:"data"`
|
|
84
|
-
}
|
|
85
|
-
if err := json.Unmarshal(data, &inputWrapper); err != nil {
|
|
86
|
-
fmt.Printf("Error parsing JSON: %v\n", err)
|
|
87
|
-
os.Exit(1)
|
|
88
|
-
}
|
|
89
|
-
oldSamples := inputWrapper.Data.CCREBiosampleQuery.Biosamples
|
|
90
|
-
|
|
91
|
-
var newSamples []NewBiosample
|
|
92
|
-
for _, old := range oldSamples {
|
|
93
|
-
newSample := NewBiosample{
|
|
94
|
-
Name: old.Name,
|
|
95
|
-
Ontology: old.Ontology,
|
|
96
|
-
LifeStage: old.LifeStage,
|
|
97
|
-
SampleType: old.SampleType,
|
|
98
|
-
DisplayName: old.DisplayName,
|
|
99
|
-
Assays: []Assay{},
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Add DNase assay if present
|
|
103
|
-
if old.DNaseFileAccession != nil {
|
|
104
|
-
url := old.DNaseSignalURL
|
|
105
|
-
if url == "" {
|
|
106
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + *old.DNaseFileAccession + ".bigWig"
|
|
107
|
-
}
|
|
108
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
109
|
-
ID: "dnase-" + *old.DNaseFileAccession,
|
|
110
|
-
Assay: "dnase",
|
|
111
|
-
URL: url,
|
|
112
|
-
ExperimentAccession: ptrToString(old.DNaseExperimentAccession),
|
|
113
|
-
FileAccession: *old.DNaseFileAccession,
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Add H3K4me3 assay if present
|
|
118
|
-
if old.H3K4Me3FileAccession != nil {
|
|
119
|
-
url := old.H3K4Me3SignalURL
|
|
120
|
-
if url == "" {
|
|
121
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + *old.H3K4Me3FileAccession + ".bigWig"
|
|
122
|
-
}
|
|
123
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
124
|
-
ID: "h3k4me3-" + *old.H3K4Me3FileAccession,
|
|
125
|
-
Assay: "h3k4me3",
|
|
126
|
-
URL: url,
|
|
127
|
-
ExperimentAccession: ptrToString(old.H3K4Me3ExperimentAccession),
|
|
128
|
-
FileAccession: *old.H3K4Me3FileAccession,
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Add H3K27ac assay if present
|
|
133
|
-
if old.H3K27AcFileAccession != nil {
|
|
134
|
-
url := old.H3K27AcSignalURL
|
|
135
|
-
if url == "" {
|
|
136
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + *old.H3K27AcFileAccession + ".bigWig"
|
|
137
|
-
}
|
|
138
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
139
|
-
ID: "h3k27ac-" + *old.H3K27AcFileAccession,
|
|
140
|
-
Assay: "h3k27ac",
|
|
141
|
-
URL: url,
|
|
142
|
-
ExperimentAccession: ptrToString(old.H3K27AcExperimentAccession),
|
|
143
|
-
FileAccession: *old.H3K27AcFileAccession,
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Add CTCF assay if present
|
|
148
|
-
if old.CTCFFileAccession != nil {
|
|
149
|
-
url := old.CTCFSignalURL
|
|
150
|
-
if url == "" {
|
|
151
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + *old.CTCFFileAccession + ".bigWig"
|
|
152
|
-
}
|
|
153
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
154
|
-
ID: "ctcf-" + *old.CTCFFileAccession,
|
|
155
|
-
Assay: "ctcf",
|
|
156
|
-
URL: url,
|
|
157
|
-
ExperimentAccession: ptrToString(old.CTCFExperimentAccession),
|
|
158
|
-
FileAccession: *old.CTCFFileAccession,
|
|
159
|
-
})
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Add ATAC assay if present
|
|
163
|
-
if old.ATACFileAccession != nil {
|
|
164
|
-
url := old.ATACSignalURL
|
|
165
|
-
if url == "" {
|
|
166
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + *old.ATACFileAccession + ".bigWig"
|
|
167
|
-
}
|
|
168
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
169
|
-
ID: "atac-" + *old.ATACFileAccession,
|
|
170
|
-
Assay: "atac",
|
|
171
|
-
URL: url,
|
|
172
|
-
ExperimentAccession: ptrToString(old.ATACExperimentAccession),
|
|
173
|
-
FileAccession: *old.ATACFileAccession,
|
|
174
|
-
})
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Add ChromHMM assay if present
|
|
178
|
-
if old.ChromHMMURL != "" {
|
|
179
|
-
chromhmmAccession := extractAccessionFromURL(old.ChromHMMURL)
|
|
180
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
181
|
-
ID: "chromhmm-" + chromhmmAccession,
|
|
182
|
-
Assay: "chromhmm",
|
|
183
|
-
URL: old.ChromHMMURL,
|
|
184
|
-
FileAccession: chromhmmAccession,
|
|
185
|
-
})
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Add RNA-seq tracks
|
|
189
|
-
for _, rna := range old.RNASeqTracks {
|
|
190
|
-
url := rna.URL
|
|
191
|
-
if url == "" {
|
|
192
|
-
url = "https://downloads.wenglab.org/Registry-V4/" + rna.RNASeqFileAccession + ".bigWig"
|
|
193
|
-
}
|
|
194
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
195
|
-
ID: "rnaseq-" + rna.RNASeqFileAccession,
|
|
196
|
-
Assay: "rnaseq",
|
|
197
|
-
URL: url,
|
|
198
|
-
ExperimentAccession: rna.RNASeqExperimentAccession,
|
|
199
|
-
FileAccession: rna.RNASeqFileAccession,
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Add cCRE bigBed as an assay
|
|
204
|
-
if old.BigBedURL != "" {
|
|
205
|
-
ccreAccession := extractAccessionFromURL(old.BigBedURL)
|
|
206
|
-
newSample.Assays = append(newSample.Assays, Assay{
|
|
207
|
-
ID: "ccre-" + ccreAccession,
|
|
208
|
-
Assay: "ccre",
|
|
209
|
-
URL: old.BigBedURL,
|
|
210
|
-
FileAccession: ccreAccession,
|
|
211
|
-
})
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
newSamples = append(newSamples, newSample)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Wrap in object with "tracks" key to match expected format
|
|
218
|
-
wrapper := struct {
|
|
219
|
-
Tracks []NewBiosample `json:"tracks"`
|
|
220
|
-
}{
|
|
221
|
-
Tracks: newSamples,
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
output, err := json.MarshalIndent(wrapper, "", " ")
|
|
225
|
-
if err != nil {
|
|
226
|
-
fmt.Printf("Error marshaling JSON: %v\n", err)
|
|
227
|
-
os.Exit(1)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if err := os.WriteFile(outputFile, output, 0644); err != nil {
|
|
231
|
-
fmt.Printf("Error writing output file: %v\n", err)
|
|
232
|
-
os.Exit(1)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
fmt.Printf("Successfully converted %d biosamples to %s\n", len(newSamples), outputFile)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
func ptrToString(s *string) string {
|
|
239
|
-
if s == nil {
|
|
240
|
-
return ""
|
|
241
|
-
}
|
|
242
|
-
return *s
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// extractAccessionFromURL extracts the file accession from a URL
|
|
246
|
-
// e.g., "https://downloads.wenglab.org/Registry-V4/ENCFF170YYM.bigBed" -> "ENCFF170YYM"
|
|
247
|
-
// e.g., "https://downloads.wenglab.org/Registry-V4/ENCFF606INL_ENCFF501ILD.bigBed" -> "ENCFF606INL_ENCFF501ILD"
|
|
248
|
-
func extractAccessionFromURL(url string) string {
|
|
249
|
-
// Get the filename from the URL
|
|
250
|
-
filename := path.Base(url)
|
|
251
|
-
// Remove the extension
|
|
252
|
-
ext := path.Ext(filename)
|
|
253
|
-
return strings.TrimSuffix(filename, ext)
|
|
254
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
//go:build ignore
|
|
2
|
-
|
|
3
|
-
package main
|
|
4
|
-
|
|
5
|
-
import (
|
|
6
|
-
"bufio"
|
|
7
|
-
"encoding/json"
|
|
8
|
-
"fmt"
|
|
9
|
-
"os"
|
|
10
|
-
"regexp"
|
|
11
|
-
"strings"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
type Assay struct {
|
|
15
|
-
ID string `json:"id"`
|
|
16
|
-
Assay string `json:"assay"`
|
|
17
|
-
URL string `json:"url"`
|
|
18
|
-
ExperimentAccession string `json:"experimentAccession"`
|
|
19
|
-
FileAccession string `json:"fileAccession"`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type Track struct {
|
|
23
|
-
Name string `json:"name"`
|
|
24
|
-
Core bool `json:"core,omitempty"`
|
|
25
|
-
Ontology string `json:"ontology"`
|
|
26
|
-
LifeStage string `json:"lifeStage"`
|
|
27
|
-
SampleType string `json:"sampleType"`
|
|
28
|
-
DisplayName string `json:"displayName"`
|
|
29
|
-
Assays []Assay `json:"assays"`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type BiosampleData struct {
|
|
33
|
-
Tracks []Track `json:"tracks"`
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// CoreSample represents a sample to be marked as core, with donor ID and display name
|
|
37
|
-
type CoreSample struct {
|
|
38
|
-
DonorID string
|
|
39
|
-
DisplayName string
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func main() {
|
|
43
|
-
// Extract core samples from test.txt (donor ID + display name pairs)
|
|
44
|
-
coreSamples, err := extractCoreSamples("test.txt")
|
|
45
|
-
if err != nil {
|
|
46
|
-
fmt.Fprintf(os.Stderr, "Error reading test.txt: %v\n", err)
|
|
47
|
-
os.Exit(1)
|
|
48
|
-
}
|
|
49
|
-
fmt.Printf("Found %d core samples to mark\n", len(coreSamples))
|
|
50
|
-
|
|
51
|
-
// Load human.json
|
|
52
|
-
data, err := os.ReadFile("human.json")
|
|
53
|
-
if err != nil {
|
|
54
|
-
fmt.Fprintf(os.Stderr, "Error reading human.json: %v\n", err)
|
|
55
|
-
os.Exit(1)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
var biosampleData BiosampleData
|
|
59
|
-
if err := json.Unmarshal(data, &biosampleData); err != nil {
|
|
60
|
-
fmt.Fprintf(os.Stderr, "Error parsing human.json: %v\n", err)
|
|
61
|
-
os.Exit(1)
|
|
62
|
-
}
|
|
63
|
-
fmt.Printf("Loaded %d tracks\n", len(biosampleData.Tracks))
|
|
64
|
-
|
|
65
|
-
// Mark tracks as core if they match both donor ID and display name
|
|
66
|
-
markedCount := 0
|
|
67
|
-
alreadyCore := 0
|
|
68
|
-
for i := range biosampleData.Tracks {
|
|
69
|
-
track := &biosampleData.Tracks[i]
|
|
70
|
-
for _, sample := range coreSamples {
|
|
71
|
-
// Check if track name ends with the donor ID AND display name matches (case-insensitive)
|
|
72
|
-
if strings.HasSuffix(track.Name, "_"+sample.DonorID) &&
|
|
73
|
-
strings.EqualFold(track.DisplayName, sample.DisplayName) {
|
|
74
|
-
if track.Core {
|
|
75
|
-
alreadyCore++
|
|
76
|
-
} else {
|
|
77
|
-
track.Core = true
|
|
78
|
-
markedCount++
|
|
79
|
-
}
|
|
80
|
-
break
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
fmt.Printf("Marked %d tracks as core (already core: %d)\n", markedCount, alreadyCore)
|
|
85
|
-
|
|
86
|
-
// Write to temp file
|
|
87
|
-
output, err := json.MarshalIndent(biosampleData, "", " ")
|
|
88
|
-
if err != nil {
|
|
89
|
-
fmt.Fprintf(os.Stderr, "Error marshaling JSON: %v\n", err)
|
|
90
|
-
os.Exit(1)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if err := os.WriteFile("human_updated.json", output, 0644); err != nil {
|
|
94
|
-
fmt.Fprintf(os.Stderr, "Error writing human_updated.json: %v\n", err)
|
|
95
|
-
os.Exit(1)
|
|
96
|
-
}
|
|
97
|
-
fmt.Println("Wrote updated data to human_updated.json")
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// extractCoreSamples parses test.txt and extracts donor ID + display name pairs
|
|
101
|
-
// Format: "Organ \t Type \t ENCDO... \t DisplayName: (1) cCREs \t Data format"
|
|
102
|
-
func extractCoreSamples(filename string) ([]CoreSample, error) {
|
|
103
|
-
file, err := os.Open(filename)
|
|
104
|
-
if err != nil {
|
|
105
|
-
return nil, err
|
|
106
|
-
}
|
|
107
|
-
defer file.Close()
|
|
108
|
-
|
|
109
|
-
var samples []CoreSample
|
|
110
|
-
donorRe := regexp.MustCompile(`ENCDO\w+`)
|
|
111
|
-
|
|
112
|
-
scanner := bufio.NewScanner(file)
|
|
113
|
-
for scanner.Scan() {
|
|
114
|
-
line := scanner.Text()
|
|
115
|
-
if strings.TrimSpace(line) == "" {
|
|
116
|
-
continue
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Find the donor ID
|
|
120
|
-
donorMatch := donorRe.FindString(line)
|
|
121
|
-
if donorMatch == "" {
|
|
122
|
-
continue
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Extract display name: it's after the donor ID, before ": (1)"
|
|
126
|
-
// Split by donor ID to get the part after it
|
|
127
|
-
parts := strings.SplitN(line, donorMatch, 2)
|
|
128
|
-
if len(parts) < 2 {
|
|
129
|
-
continue
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
afterDonor := parts[1]
|
|
133
|
-
// Remove leading tab/whitespace
|
|
134
|
-
afterDonor = strings.TrimLeft(afterDonor, " \t")
|
|
135
|
-
|
|
136
|
-
// Extract the display name (before ": (1)" or ":(1)")
|
|
137
|
-
displayName := afterDonor
|
|
138
|
-
if idx := strings.Index(afterDonor, ": ("); idx != -1 {
|
|
139
|
-
displayName = afterDonor[:idx]
|
|
140
|
-
} else if idx := strings.Index(afterDonor, ":("); idx != -1 {
|
|
141
|
-
displayName = afterDonor[:idx]
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
displayName = strings.TrimSpace(displayName)
|
|
145
|
-
if displayName != "" {
|
|
146
|
-
samples = append(samples, CoreSample{
|
|
147
|
-
DonorID: donorMatch,
|
|
148
|
-
DisplayName: displayName,
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if err := scanner.Err(); err != nil {
|
|
154
|
-
return nil, err
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return samples, nil
|
|
158
|
-
}
|