@@ -63,6 +63,11 @@ def __init__(self):
6363 file_path = idc_index_data .IDC_INDEX_PARQUET_FILEPATH
6464 logger .debug (f"Reading index file v{ idc_index_data .__version__ } " )
6565 self .index = pd .read_parquet (file_path )
66+
67+ self .previous_versions_index_path = (
68+ idc_index_data .PRIOR_VERSIONS_INDEX_PARQUET_FILEPATH
69+ )
70+
6671 # self.index = self.index.astype(str).replace("nan", "")
6772 self .index ["series_size_MB" ] = self .index ["series_size_MB" ].astype (float )
6873 self .collection_summary = self .index .groupby ("collection_id" ).agg (
@@ -75,6 +80,11 @@ def __init__(self):
7580 "installed" : True ,
7681 "url" : None ,
7782 },
83+ "previous_versions_index" : {
84+ "description" : "index containing one row per DICOM series from all previous IDC versions that are not in current version." ,
85+ "installed" : True ,
86+ "url" : None ,
87+ },
7888 "sm_index" : {
7989 "description" : "DICOM Slide Microscopy series-level index." ,
8090 "installed" : False ,
@@ -617,34 +627,44 @@ def _validate_update_manifest_and_get_download_size(
617627 # create a copy of the index
618628 index_df_copy = self .index
619629
630+ # use default hierarchy
631+ if dirTemplate is not None :
632+ hierarchy = self ._generate_sql_concat_for_building_directory (
633+ dirTemplate = dirTemplate , downloadDir = downloadDir
634+ )
635+ else :
636+ hierarchy = "NULL"
637+
620638 # Extract s3 url and crdc_series_uuid from the manifest copy commands
621639 # Next, extract crdc_series_uuid from aws_series_url in the index and
622640 # try to verify if every series in the manifest is present in the index
623641
624642 # TODO: need to remove the assumption that manifest commands will have 'cp'
625643 # and need to parse S3 URL directly
626644 # ruff: noqa
627- sql = """
645+ sql = f """
628646 PRAGMA disable_progress_bar;
629647 WITH
630648 index_temp AS (
631649 SELECT
632650 seriesInstanceUID,
633651 series_aws_url,
634652 series_size_MB,
635- REGEXP_EXTRACT(series_aws_url, '(?:.*?\\ /){3}([^\\ /?#]+)', 1) index_crdc_series_uuid
653+ { hierarchy } AS path,
654+ REGEXP_EXTRACT(series_aws_url, '(?:.*?\\ /){{3}}([^\\ /?#]+)', 1) index_crdc_series_uuid
636655 FROM
637656 index_df_copy),
638657 manifest_temp AS (
639658 SELECT
640659 manifest_cp_cmd,
641- REGEXP_EXTRACT(manifest_cp_cmd, '(?:.*?\\ /){3 }([^\\ /?#]+)', 1) AS manifest_crdc_series_uuid,
660+ REGEXP_EXTRACT(manifest_cp_cmd, '(?:.*?\\ /){{3} }([^\\ /?#]+)', 1) AS manifest_crdc_series_uuid,
642661 REGEXP_REPLACE(regexp_replace(manifest_cp_cmd, 'cp ', ''), '\\ s[^\\ s]*$', '') AS s3_url,
643662 FROM
644663 manifest_df )
645664 SELECT
646665 seriesInstanceuid,
647666 s3_url,
667+ path,
648668 series_size_MB,
649669 index_crdc_series_uuid is not NULL as crdc_series_uuid_match,
650670 s3_url==series_aws_url AS s3_url_match,
@@ -679,6 +699,75 @@ def _validate_update_manifest_and_get_download_size(
679699 )
680700 logger .error ("\n " + "\n " .join (missing_manifest_cp_cmds .tolist ()))
681701
702+ logger .debug (
703+ "Checking if the requested data is available in other idc versions "
704+ )
705+ missing_series_sql = f"""
706+ PRAGMA disable_progress_bar;
707+ WITH
708+ combined_index AS
709+ (SELECT
710+ *,
711+ { hierarchy } AS path,
712+ FROM
713+ index_df_copy
714+ union by name
715+ SELECT
716+ *,
717+ { hierarchy } AS path,
718+ FROM
719+ '{ self .previous_versions_index_path } ' pvip
720+
721+ ),
722+ index_temp AS (
723+ SELECT
724+ seriesInstanceUID,
725+ series_aws_url,
726+ series_size_MB,
727+ path,
728+ REGEXP_EXTRACT(series_aws_url, '(?:.*?\\ /){{3}}([^\\ /?#]+)', 1) index_crdc_series_uuid
729+ FROM
730+ combined_index),
731+ manifest_temp AS (
732+ SELECT
733+ manifest_cp_cmd,
734+ REGEXP_EXTRACT(manifest_cp_cmd, '(?:.*?\\ /){{3}}([^\\ /?#]+)', 1) AS manifest_crdc_series_uuid,
735+ REGEXP_REPLACE(regexp_replace(manifest_cp_cmd, 'cp ', ''), '\\ s[^\\ s]*$', '') AS s3_url,
736+ FROM
737+ manifest_df )
738+ SELECT
739+ seriesInstanceuid,
740+ s3_url,
741+ path,
742+ series_size_MB,
743+ index_crdc_series_uuid is not NULL as crdc_series_uuid_match,
744+ TRIM(s3_url) = TRIM(series_aws_url) AS s3_url_match,
745+ manifest_temp.manifest_cp_cmd,
746+ CASE
747+ WHEN TRIM(s3_url) = TRIM(series_aws_url) THEN 'aws'
748+ ELSE
749+ 'unknown'
750+ END
751+ AS endpoint
752+ FROM
753+ manifest_temp
754+ LEFT JOIN
755+ index_temp
756+ ON
757+ index_temp.index_crdc_series_uuid = manifest_temp.manifest_crdc_series_uuid
758+ """
759+ merged_df = duckdb .query (missing_series_sql ).df ()
760+ if not all (merged_df ["crdc_series_uuid_match" ]):
761+ missing_manifest_cp_cmds = merged_df .loc [
762+ ~ merged_df ["crdc_series_uuid_match" ], "manifest_cp_cmd"
763+ ]
764+ logger .error (
765+ "The following manifest copy commands are not recognized as referencing any associated series in any release of IDC.\n "
766+ "This means either these commands are invalid. Please submit an issue on https://github.com/ImagingDataCommons/idc-index/issues \n "
767+ "The corresponding files could not be downloaded.\n "
768+ )
769+ logger .error ("\n " + "\n " .join (missing_manifest_cp_cmds .tolist ()))
770+
682771 if validate_manifest :
683772 # Check if there is more than one endpoint
684773 if len (merged_df ["endpoint" ].unique ()) > 1 :
@@ -728,29 +817,29 @@ def _validate_update_manifest_and_get_download_size(
728817 total_size = merged_df ["series_size_MB" ].sum ()
729818 total_size = round (total_size , 2 )
730819
731- if dirTemplate is not None :
732- hierarchy = self ._generate_sql_concat_for_building_directory (
733- dirTemplate = dirTemplate , downloadDir = downloadDir
734- )
735- sql = f"""
736- WITH temp as
737- (
738- SELECT
739- seriesInstanceUID,
740- s3_url
741- FROM
742- merged_df
743- )
744- SELECT
745- s3_url,
746- { hierarchy } as path
747- FROM
748- temp
749- JOIN
750- index using (seriesInstanceUID)
751- """
752- logger .debug (f"About to run this query:\n { sql } " )
753- merged_df = self .sql_query (sql )
820+ # if dirTemplate is not None:
821+ # hierarchy = self._generate_sql_concat_for_building_directory(
822+ # dirTemplate=dirTemplate, downloadDir=downloadDir
823+ # )
824+ # sql = f"""
825+ # WITH temp as
826+ # (
827+ # SELECT
828+ # seriesInstanceUID,
829+ # s3_url
830+ # FROM
831+ # merged_df
832+ # )
833+ # SELECT
834+ # s3_url,
835+ # {hierarchy} as path
836+ # FROM
837+ # temp
838+ # JOIN
839+ # index using (seriesInstanceUID)
840+ # """
841+ # logger.debug(f"About to run this query:\n{sql}")
842+ # merged_df = self.sql_query(sql)
754843 # Write a temporary manifest file
755844 with tempfile .NamedTemporaryFile (mode = "w" , delete = False ) as temp_manifest_file :
756845 if use_s5cmd_sync and len (os .listdir (downloadDir )) != 0 :
0 commit comments