Skip to content

Commit d2ea63e

Browse files
authored
Merge pull request #178 from cBioPortal/main-add-enable-study-cbioportalimporter
Keep studies UNAVAILABLE until derived tables are rebuilt
2 parents 47890bb + 776c631 commit d2ea63e

6 files changed

Lines changed: 79 additions & 20 deletions

File tree

‎pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<!-- THIS SHOULD BE KEPT IN SYNC WITH db.version IN cbioportal/pom.xml and
1919
info.db_schema_version IN cbioportal/src/main/resources/db-scripts/clickhouse/init/schema.sql -->
20-
<db.version>3.0.0</db.version>
20+
<db.version>3.0.1</db.version>
2121
<cbioportal.version>v6.4.1</cbioportal.version>
2222
<maf.version>1.0.0</maf.version>
2323

‎scripts/importer/cbioportalImporter.py‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@
5858
REMOVE_PATIENTS = "remove-patients"
5959
IMPORT_STUDY_DATA = "import-study-data"
6060
IMPORT_CASE_LIST = "import-case-list"
61+
MAKE_STUDIES_AVAILABLE = "make-studies-available"
6162

62-
COMMANDS = [IMPORT_CANCER_TYPE, IMPORT_STUDY, IMPORT_STUDY_DATA, IMPORT_CASE_LIST, REMOVE_STUDY, REMOVE_SAMPLES, REMOVE_PATIENTS]
63+
COMMANDS = [IMPORT_CANCER_TYPE, IMPORT_STUDY, IMPORT_STUDY_DATA, IMPORT_CASE_LIST, REMOVE_STUDY, REMOVE_SAMPLES, REMOVE_PATIENTS, MAKE_STUDIES_AVAILABLE]
6364

6465
# ------------------------------------------------------------------------------
6566
# sub-routines
@@ -79,11 +80,11 @@ def import_study(jvm_args, meta_filename):
7980
args.append("--noprogress") # don't report memory usage and % progress
8081
run_java(*args)
8182

82-
def update_study_status(jvm_args, study_id):
83+
def update_study_status(jvm_args, study_id, status="AVAILABLE"):
8384
args = jvm_args.split(' ')
8485
args.append(UPDATE_STUDY_STATUS_CLASS)
8586
args.append(study_id)
86-
args.append("AVAILABLE")
87+
args.append(status)
8788
args.append("--noprogress") # don't report memory usage and % progress
8889
run_java(*args)
8990

@@ -268,6 +269,9 @@ def process_command(jvm_args, command, meta_filename, data_filename, study_ids,
268269
import_data(jvm_args, meta_filename, data_filename, update_generic_assay_entity)
269270
elif command == IMPORT_CASE_LIST:
270271
import_case_list(jvm_args, meta_filename)
272+
elif command == MAKE_STUDIES_AVAILABLE:
273+
for study_id in study_ids.split(","):
274+
update_study_status(jvm_args, study_id)
271275

272276
def get_meta_filenames(data_directory):
273277
meta_filenames = [
@@ -466,8 +470,8 @@ def process_study_directory(jvm_args, study_directory, update_generic_assay_enti
466470
if study_meta_dictionary[study_meta_filename].get('add_global_case_list', 'false').lower() == 'true':
467471
add_global_case_list(jvm_args, study_id)
468472

469-
# enable study
470-
update_study_status(jvm_args, study_id)
473+
# the study stays UNAVAILABLE until the derived tables are rebuilt
474+
return study_id
471475

472476
def get_meta_filenames_by_type(data_directory) -> Dict[str, Tuple[str, Dict]]:
473477
"""
@@ -546,8 +550,16 @@ def process_data_directory(jvm_args, data_directory, update_generic_assay_entity
546550
not_supported_meta_types = meta_file_type_to_meta_files.keys() - INCREMENTAL_UPLOAD_SUPPORTED_META_TYPES
547551
if not_supported_meta_types:
548552
raise NotImplementedError("These types do not support incremental upload: {}".format(", ".join(not_supported_meta_types)))
553+
# the study is not removed first, so hide it here until the derived tables are rebuilt
554+
study_id = next(iter(meta_file_type_to_meta_files.values()))[0][1]['cancer_study_identifier']
555+
update_study_status(jvm_args, study_id, "UNAVAILABLE")
549556
import_incremental_data(jvm_args, data_directory, update_generic_assay_entity, meta_file_type_to_meta_files)
550557
update_case_lists_from_folder(jvm_args, data_directory, meta_file_type_to_meta_files)
558+
return study_id
559+
560+
def make_study_available(args, study_id):
561+
# main() has already put the jar path into args.java_opts
562+
update_study_status("-Dspring.profiles.active=dbcp " + args.java_opts, study_id)
551563

552564
def usage():
553565
# TODO : replace this by usage string from interface()
@@ -617,6 +629,10 @@ def interface(args=None):
617629
remove_patients.add_argument('--patient_ids', type=str, required=True,
618630
help='Patient ID(s). Comma separated, if multiple.')
619631

632+
make_studies_available = subparsers.add_parser('make-studies-available', parents=[parent_parser], add_help=False)
633+
make_studies_available .add_argument('-ids', '--study_ids', type=str, required=True,
634+
help='Cancer Study ID(s) to mark AVAILABLE, comma separated')
635+
620636
parser.add_argument('-c', '--command', type=str, required=False,
621637
help='This argument is outdated. Please use the listed subcommands, without the -c flag. '
622638
'Command for import. Allowed commands: ' + allowed_commands_csv)
@@ -697,10 +713,10 @@ def main(args):
697713

698714
if args.data_directory is not None:
699715
check_dir(args.data_directory)
700-
process_data_directory(jvm_args, args.data_directory, args.update_generic_assay_entity)
716+
return process_data_directory(jvm_args, args.data_directory, args.update_generic_assay_entity)
701717
elif args.study_directory is not None:
702718
check_dir(args.study_directory)
703-
process_study_directory(jvm_args, args.study_directory, args.update_generic_assay_entity)
719+
return process_study_directory(jvm_args, args.study_directory, args.update_generic_assay_entity)
704720
else:
705721
check_args(args.command)
706722
check_files(args.meta_filename, args.data_filename)

‎scripts/importer/metaImport.py‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ def _print_need_to_update_derived_tables_warning():
129129
file=sys.stderr,
130130
)
131131

132+
def _print_need_to_make_study_available_message(study_id):
133+
print(
134+
Color.BOLD +
135+
'The study stays UNAVAILABLE until the derived tables are rebuilt. Then run:\n'
136+
' cbioportalImporter.py make-studies-available -ids ' + study_id + '\n' +
137+
Color.END,
138+
file=sys.stderr,
139+
)
140+
132141
if __name__ == '__main__':
133142
derive_tables_only = len(sys.argv) > 1 and sys.argv[1] == 'derive-tables'
134143
if derive_tables_only:
@@ -228,7 +237,7 @@ def _print_need_to_update_derived_tables_warning():
228237
if args.override_warning and not args.skip_db_import:
229238
print(Color.BOLD + "Overriding Warnings. Importing study now" + Color.END, file=sys.stderr)
230239
print("#" * 71 + "\n", file=sys.stderr)
231-
cbioportalImporter.main(args)
240+
study_id = cbioportalImporter.main(args)
232241
exitcode = 0
233242
# Rebuild derived tables after database-mutating operation
234243
if not getattr(args, 'no_derive_tables', False):
@@ -243,15 +252,19 @@ def _print_need_to_update_derived_tables_warning():
243252
"The database may be in an inconsistent state." +
244253
Color.END, file=sys.stderr)
245254
exitcode = 1
255+
_print_need_to_make_study_available_message(study_id)
256+
else:
257+
cbioportalImporter.make_study_available(args, study_id)
246258
else:
247259
_print_need_to_update_derived_tables_warning()
260+
_print_need_to_make_study_available_message(study_id)
248261
else:
249262
print(Color.BOLD + "Warnings. Please fix your files or import with override warning option" + Color.END, file=sys.stderr)
250263
print("#" * 71, file=sys.stderr)
251264
elif exitcode == 0 and not args.skip_db_import:
252265
print(Color.BOLD + "Everything looks good. Importing study now" + Color.END, file=sys.stderr)
253266
print("#" * 71 + "\n", file=sys.stderr)
254-
cbioportalImporter.main(args)
267+
study_id = cbioportalImporter.main(args)
255268
# Rebuild derived tables after database-mutating operation
256269
if not getattr(args, 'no_derive_tables', False):
257270
print("\n")
@@ -265,8 +278,12 @@ def _print_need_to_update_derived_tables_warning():
265278
"The database may be in an inconsistent state." +
266279
Color.END, file=sys.stderr)
267280
exitcode = 1
281+
_print_need_to_make_study_available_message(study_id)
282+
else:
283+
cbioportalImporter.make_study_available(args, study_id)
268284
else:
269285
_print_need_to_update_derived_tables_warning()
286+
_print_need_to_make_study_available_message(study_id)
270287
except KeyboardInterrupt:
271288
print(Color.BOLD + "\nProcess interrupted. You will have to run this again to make sure study is completely loaded." + Color.END, file=sys.stderr)
272289
print("#" * 71, file=sys.stderr)

‎src/main/java/org/mskcc/cbio/portal/dao/DaoCancerStudy.java‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ public static void addCancerStudy(CancerStudy cancerStudy, boolean overwrite) th
295295
CancerStudy existing = getCancerStudyByStableId(stableId);
296296
if (existing!=null) {
297297
if (overwrite) {
298-
//setStatus(Status.UNAVAILABLE, stableId);
299298
deleteCancerStudy(existing.getInternalId());
300299
} else {
301300
throw new DaoException("Cancer study " + stableId + "is already imported.");
@@ -458,7 +457,6 @@ public static void deleteAllRecords() throws DaoException {
458457
public static void deleteCancerStudy(String cancerStudyStableId) throws DaoException {
459458
CancerStudy study = getCancerStudyByStableId(cancerStudyStableId);
460459
if (study != null){
461-
//setStatus(Status.UNAVAILABLE, cancerStudyStableId);
462460
deleteCancerStudy(study.getInternalId());
463461
}
464462
}
@@ -505,6 +503,10 @@ public static void deleteCancerStudy(int internalCancerStudyId) throws DaoExcept
505503
PreparedStatement pstmt = null;
506504
ResultSet rs = null;
507505
try {
506+
// The cancer_study row is deleted last; hide the study first so the portal does not
507+
// serve it while its data is partially deleted.
508+
setStatus(Status.UNAVAILABLE, null, internalCancerStudyId);
509+
508510
// check whether should delete generic assay meta profile by profile
509511
DaoGenericAssay.checkAndDeleteGenericAssayMetaInStudy(internalCancerStudyId);
510512

‎src/test/resources/seed_mini.sql‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ INSERT INTO authorities (`email`, `authority`) values ('Dhorak@yahoo.com','ROLE_
545545
INSERT INTO authorities (`email`, `authority`) values ('Dhorak@yahoo.com','ROLE_MANAGER');
546546

547547
INSERT INTO `info` (`db_schema_version`, `geneset_version`)
548-
VALUES ('3.0.0', 'test_geneset_version');
548+
VALUES ('3.0.1', 'test_geneset_version');
549549

550550
--geneset
551551
INSERT INTO geneset (`id`, `genetic_entity_id`, `external_id`, `name`, `description`, `ref_link`) VALUES (1, 1, 'HGNC:1100', 'BRCA1', 'Breast cancer type 1 susceptibility protein', 'https://www.ncbi.nlm.nih.gov/gene/672');

‎tests/system_tests_import_data.py‎

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,14 @@ def test_full_study_load(self, run_java, locate_jar):
3131
study_directory = 'test_data/study_es_0'
3232
args = ['--study_directory', study_directory]
3333
parsed_args = cbioportalImporter.interface(args)
34-
cbioportalImporter.main(parsed_args)
34+
study_id = cbioportalImporter.main(parsed_args)
3535

3636
remove_study_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.RemoveCancerStudy',
3737
'study_es_0', '--noprogress')
3838
create_study_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportCancerStudy',
3939
f'{study_directory}/meta_study.txt', '--noprogress')
4040
clinical_sample_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportClinicalData',
4141
'--meta', f'{study_directory}/meta_clinical_samples.txt', '--loadMode', 'bulkload', '--data', f'{study_directory}/data_clinical_samples.txt', '--noprogress')
42-
make_study_available_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.UpdateCancerStudy',
43-
'study_es_0', 'AVAILABLE', '--noprogress')
4442
mol_profile_calls = [
4543
call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportProfileData', '--meta', f'{study_directory}/meta_cna_log2.txt', '--loadMode', 'bulkload', '--update-info', 'False', '--data', f'{study_directory}/data_cna_log2.txt', '--noprogress'),
4644
call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportProfileData', '--meta', f'{study_directory}/meta_expression_median.txt', '--loadMode', 'bulkload', '--update-info', 'False', '--data', f'{study_directory}/data_expression_median.txt', '--noprogress'),
@@ -80,14 +78,15 @@ def test_full_study_load(self, run_java, locate_jar):
8078
call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportSampleList', f'{study_directory}/case_lists/cases_sequenced.txt', '--noprogress'),
8179
call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportSampleList', f'{study_directory}/case_lists/cases_test.txt', '--noprogress'),
8280
call(*common_part, 'org.mskcc.cbio.portal.scripts.AddCaseList', 'study_es_0', 'all', '--noprogress'),
83-
make_study_available_call,
8481
])
8582

8683
self.assertTrue(run_java.call_args_list.index(remove_study_call) < run_java.call_args_list.index(create_study_call))
8784
self.assertTrue(run_java.call_args_list.index(create_study_call) < run_java.call_args_list.index(clinical_sample_call))
8885
self.assertTrue(all(run_java.call_args_list.index(clinical_sample_call) < run_java.call_args_list.index(mol_profile_call)
8986
for mol_profile_call in mol_profile_calls))
90-
self.assertEqual(run_java.call_args_list[-1], make_study_available_call)
87+
# The study is left UNAVAILABLE until the derived tables are rebuilt
88+
self.assertNotIn('AVAILABLE', [c.args[-2] for c in run_java.call_args_list])
89+
self.assertEqual(study_id, 'study_es_0')
9190

9291

9392
@mock.patch('importer.cbioportalImporter.locate_jar')
@@ -101,7 +100,7 @@ def test_incremental_load(self, run_java, locate_jar):
101100
data_directory = 'test_data/study_es_0_inc'
102101
args = ['--data_directory', data_directory]
103102
parsed_args = cbioportalImporter.interface(args)
104-
cbioportalImporter.main(parsed_args)
103+
study_id = cbioportalImporter.main(parsed_args)
105104

106105
clinical_patient_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportClinicalData', '--overwrite-existing',
107106
'--meta', f'{data_directory}/meta_clinical_patients.txt', '--loadMode', 'bulkload', '--data', f'{data_directory}/data_clinical_patients.txt', '--noprogress')
@@ -130,8 +129,12 @@ def test_incremental_load(self, run_java, locate_jar):
130129
seg_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportCopyNumberSegmentData', '--overwrite-existing',
131130
'--meta', f'{data_directory}/meta_cna_hg19_seg.txt', '--loadMode', 'bulkload', '--data', f'{data_directory}/data_cna_hg19.seg', '--noprogress')
132131

132+
make_study_unavailable_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.UpdateCancerStudy',
133+
'study_es_0', 'UNAVAILABLE', '--noprogress')
134+
133135
self.assertCountEqual(run_java.call_args_list, [
134136
call(*common_part, 'org.mskcc.cbio.portal.util.VersionUtil',),
137+
make_study_unavailable_call,
135138
clinical_patient_call,
136139
clinical_sample_call,
137140
mutation_call,
@@ -149,6 +152,8 @@ def test_incremental_load(self, run_java, locate_jar):
149152

150153
self.assertTrue(run_java.call_args_list.index(clinical_sample_call) < run_java.call_args_list.index(mutation_call))
151154
self.assertTrue(run_java.call_args_list.index(clinical_sample_call) < run_java.call_args_list.index(case_list_call))
155+
self.assertEqual(run_java.call_args_list[1], make_study_unavailable_call)
156+
self.assertEqual(study_id, 'study_es_0')
152157

153158

154159
@mock.patch('importer.cbioportalImporter.locate_jar')
@@ -165,11 +170,30 @@ def test_incremental_load_cna_discrete_long(self, run_java, locate_jar):
165170
cna_discrete_long_call = call(*common_part, 'org.mskcc.cbio.portal.scripts.ImportProfileData', '--overwrite-existing',
166171
'--meta', f'{data_directory}/meta_cna_discrete_long.txt', '--loadMode', 'bulkload', '--update-info', 'False', '--data', f'{data_directory}/data_cna_discrete_long.txt', '--noprogress')
167172

168-
self.assertCountEqual(run_java.call_args_list, [
173+
self.assertEqual(run_java.call_args_list, [
169174
call(*common_part, 'org.mskcc.cbio.portal.util.VersionUtil',),
175+
call(*common_part, 'org.mskcc.cbio.portal.scripts.UpdateCancerStudy', 'study_es_0', 'UNAVAILABLE', '--noprogress'),
170176
cna_discrete_long_call,
171177
])
172178

179+
@mock.patch('importer.cbioportalImporter.locate_jar')
180+
@mock.patch('importer.cbioportalImporter.run_java')
181+
def test_make_studies_available(self, run_java, locate_jar):
182+
'''
183+
Tests java commands that make-studies-available produces
184+
'''
185+
locate_jar.return_value = "test.jar"
186+
187+
args = ['make-studies-available', '--study_ids', 'STUDY1,STUDY2']
188+
parsed_args = cbioportalImporter.interface(args)
189+
cbioportalImporter.main(parsed_args)
190+
191+
self.assertEqual(run_java.call_args_list, [
192+
call(*common_part, 'org.mskcc.cbio.portal.util.VersionUtil',),
193+
call(*common_part, 'org.mskcc.cbio.portal.scripts.UpdateCancerStudy', 'STUDY1', 'AVAILABLE', '--noprogress'),
194+
call(*common_part, 'org.mskcc.cbio.portal.scripts.UpdateCancerStudy', 'STUDY2', 'AVAILABLE', '--noprogress'),
195+
])
196+
173197
@mock.patch('importer.cbioportalImporter.locate_jar')
174198
@mock.patch('importer.cbioportalImporter.run_java')
175199
def test_remove_samples(self, run_java, locate_jar):

0 commit comments

Comments
 (0)