From 9712ac745ebb4ecfc45d889597bdf00f202c2d87 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Mon, 9 Sep 2024 18:05:35 -0400 Subject: [PATCH 1/9] Converted organ cypher to returning json. --- src/hs_ontology_api/cypher/organs.cypher | 6 +++++- src/hs_ontology_api/utils/neo4j_logic.py | 16 ++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/hs_ontology_api/cypher/organs.cypher b/src/hs_ontology_api/cypher/organs.cypher index 7d4b023..6538cb0 100644 --- a/src/hs_ontology_api/cypher/organs.cypher +++ b/src/hs_ontology_api/cypher/organs.cypher @@ -1,3 +1,5 @@ +// JAS SEPT 2024 - Converted return to JSON. Added organ category and laterality. + // Replaces and extends a read of the organ_types.yaml in the search-api. Used by endpoints in the organs route. // The calling function in neo4j_logic.py will replace $sab. @@ -33,4 +35,6 @@ CALL // Filter out the "Other" organ node. WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI WHERE NOT (OrganCode = 'C030071' AND OrganSAB=$sab) -RETURN DISTINCT OrganCode,OrganSAB,OrganName,CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END AS OrganUBERON,OrganTwoCharacterCode,OrganCUI ORDER BY OrganName +//RETURN DISTINCT OrganCode,OrganSAB,OrganName,CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END AS OrganUBERON,OrganTwoCharacterCode,OrganCUI ORDER BY OrganName +RETURN {code:OrganCode, sab:OrganSAB, term:OrganName, organ_uberon:CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END, rui_code:OrganTwoCharacterCode, organ_cui:OrganCUI} AS organ +ORDER BY OrganName \ No newline at end of file diff --git a/src/hs_ontology_api/utils/neo4j_logic.py b/src/hs_ontology_api/utils/neo4j_logic.py index a81b277..e416f88 100644 --- a/src/hs_ontology_api/utils/neo4j_logic.py +++ b/src/hs_ontology_api/utils/neo4j_logic.py @@ -211,6 +211,8 @@ def get_organ_types_logic(neo4j_instance, sab): :param neo4j_instance: pointer to neo4j connection :return: + JAS SEPT 2024 - Converted to using JSON returned from query. Added organ category and laterality. + JAS NOV 2023 - Moved query string to external file and implemented loadquery utility logic. """ result = [] @@ -223,14 +225,16 @@ def get_organ_types_logic(neo4j_instance, sab): with neo4j_instance.driver.session() as session: recds: neo4j.Result = session.run(query) + #for record in recds: + #item = SabCodeTermRuiCode(sab=record.get('OrganSAB'), code=record.get('OrganCode'), + #term=record.get('OrganName'), rui_code=record.get('OrganTwoCharacterCode'), + #organ_uberon=record.get('OrganUBERON'), organ_cui=record.get('OrganCUI') + #).serialize() + #result.append(item) for record in recds: - item = SabCodeTermRuiCode(sab=record.get('OrganSAB'), code=record.get('OrganCode'), - term=record.get('OrganName'), rui_code=record.get('OrganTwoCharacterCode'), - organ_uberon=record.get('OrganUBERON'), organ_cui=record.get('OrganCUI') - ).serialize() - result.append(item) - return result + result.append(record.get('organ')) + return result def relationships_for_gene_target_symbol_get_logic(neo4j_instance, target_symbol: str) -> dict: """ From b51452b9a5092b86c58cf1b591c0d249c5530b22 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Wed, 11 Sep 2024 06:28:46 -0400 Subject: [PATCH 2/9] organ category --- src/hs_ontology_api/cypher/organs.cypher | 33 +++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/hs_ontology_api/cypher/organs.cypher b/src/hs_ontology_api/cypher/organs.cypher index 6538cb0..e7bc94b 100644 --- a/src/hs_ontology_api/cypher/organs.cypher +++ b/src/hs_ontology_api/cypher/organs.cypher @@ -32,9 +32,34 @@ CALL WITH OrganCUI OPTIONAL MATCH (pOrgan:Concept)-[r1:has_two_character_code]->(p2CC:Concept)-[r2:PREF_TERM]->(t2CC:Term) WHERE pOrgan.CUI=OrganCUI AND r1.SAB=$sab RETURN t2CC.name as OrganTwoCharacterCode } +// Organ categories +CALL +{ + WITH OrganCUI + OPTIONAL MATCH (pOrgan:Concept)-[:isa]-(pOrganCat:Concept)-[:isa]->(pCat:Concept), + // HuBMAP name for the category + (pOrganCat:Concept)-[:CODE]->(cOrganCat:Code)-[rOrganCat:PT]-(tOrganCat:Term), + // UBERON code for the category + (pOrganCat:Concept)-[:CODE]->(cUBERON:Code) + WHERE pOrgan.CUI = OrganCUI + //Organ cat parent + AND pCat.CUI='HUBMAP:C045000 CUI' + AND cOrganCat.SAB='HUBMAP' + AND rOrganCat.CUI=pOrganCat.CUI + AND cUBERON.SAB='UBERON' + RETURN DISTINCT + CASE + // Kidney mapped to both kidney and mammalian kidney + WHEN OrganCUI in ['C0227614','C0227613'] THEN 'UBERON:0002113' + // Lung mapped to both lung and pair of lungs + WHEN OrganCUI in ['C0225730','C0225706'] THEN 'UBERON:0002048' + ELSE cUBERON.CodeID END AS OrganCatUBERON,tOrganCat.name AS OrganCatTerm +} // Filter out the "Other" organ node. -WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI +WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI,CASE WHEN OrganCatUBERON is null then {category:{}} ELSE {category:{code:OrganCatUBERON, term:OrganCatTerm}} END AS category + WHERE NOT (OrganCode = 'C030071' AND OrganSAB=$sab) -//RETURN DISTINCT OrganCode,OrganSAB,OrganName,CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END AS OrganUBERON,OrganTwoCharacterCode,OrganCUI ORDER BY OrganName -RETURN {code:OrganCode, sab:OrganSAB, term:OrganName, organ_uberon:CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END, rui_code:OrganTwoCharacterCode, organ_cui:OrganCUI} AS organ -ORDER BY OrganName \ No newline at end of file +RETURN DISTINCT {code:OrganCode, sab:OrganSAB, term:OrganName, +organ_uberon:CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END, +rui_code:OrganTwoCharacterCode, organ_cui:OrganCUI, category:category} AS organ +ORDER BY organ.term \ No newline at end of file From 3a4e71b833e8a727b4f30a06ea3fd13581e45b9b Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Wed, 11 Sep 2024 06:54:04 -0400 Subject: [PATCH 3/9] laterality; application context for organ category --- src/hs_ontology_api/cypher/organs.cypher | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/hs_ontology_api/cypher/organs.cypher b/src/hs_ontology_api/cypher/organs.cypher index e7bc94b..5af4660 100644 --- a/src/hs_ontology_api/cypher/organs.cypher +++ b/src/hs_ontology_api/cypher/organs.cypher @@ -36,15 +36,16 @@ CALL CALL { WITH OrganCUI - OPTIONAL MATCH (pOrgan:Concept)-[:isa]-(pOrganCat:Concept)-[:isa]->(pCat:Concept), + OPTIONAL MATCH (pOrgan:Concept)-[:isa]-(pOrganCat:Concept)-[:isa]->(pCat:Concept)-[:CODE]->(cCat:Code), // HuBMAP name for the category (pOrganCat:Concept)-[:CODE]->(cOrganCat:Code)-[rOrganCat:PT]-(tOrganCat:Term), // UBERON code for the category (pOrganCat:Concept)-[:CODE]->(cUBERON:Code) WHERE pOrgan.CUI = OrganCUI //Organ cat parent - AND pCat.CUI='HUBMAP:C045000 CUI' - AND cOrganCat.SAB='HUBMAP' + AND cCat.SAB=$sab + AND cCat.CODE='C045000' + AND cOrganCat.SAB=$sab AND rOrganCat.CUI=pOrganCat.CUI AND cUBERON.SAB='UBERON' RETURN DISTINCT @@ -55,11 +56,22 @@ CALL WHEN OrganCUI in ['C0225730','C0225706'] THEN 'UBERON:0002048' ELSE cUBERON.CodeID END AS OrganCatUBERON,tOrganCat.name AS OrganCatTerm } +// Laterality +CALL +{ + WITH OrganCUI + OPTIONAL MATCH (pOrgan:Concept)-[:has_laterality]->(pLaterality:Concept)-[:CODE]->(cLaterality:Code)-[rLaterality:PT]->(tLaterality:Term) + WHERE pOrgan.CUI = OrganCUI + AND rLaterality.CUI = pLaterality.CUI + AND cLaterality.SAB=$sab + RETURN DISTINCT tLaterality.name as laterality +} // Filter out the "Other" organ node. -WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI,CASE WHEN OrganCatUBERON is null then {category:{}} ELSE {category:{code:OrganCatUBERON, term:OrganCatTerm}} END AS category +WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI,laterality, +CASE WHEN OrganCatUBERON is null then {category:{}} ELSE {category:{code:OrganCatUBERON, term:OrganCatTerm}} END AS category WHERE NOT (OrganCode = 'C030071' AND OrganSAB=$sab) RETURN DISTINCT {code:OrganCode, sab:OrganSAB, term:OrganName, organ_uberon:CASE WHEN OrganUBERON IS NULL THEN OrganFMA ELSE OrganUBERON END, -rui_code:OrganTwoCharacterCode, organ_cui:OrganCUI, category:category} AS organ +rui_code:OrganTwoCharacterCode, organ_cui:OrganCUI, laterality:laterality, category:category} AS organ ORDER BY organ.term \ No newline at end of file From 5b7d92d6266655ce7be27b70c88f4862a7c944a8 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Thu, 12 Sep 2024 12:26:15 -0400 Subject: [PATCH 4/9] laterality; application context for organ category --- src/hs_ontology_api/cypher/organs.cypher | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hs_ontology_api/cypher/organs.cypher b/src/hs_ontology_api/cypher/organs.cypher index 5af4660..dd6b5e2 100644 --- a/src/hs_ontology_api/cypher/organs.cypher +++ b/src/hs_ontology_api/cypher/organs.cypher @@ -64,11 +64,12 @@ CALL WHERE pOrgan.CUI = OrganCUI AND rLaterality.CUI = pLaterality.CUI AND cLaterality.SAB=$sab - RETURN DISTINCT tLaterality.name as laterality + // Return null for 'No Laterality' or 'Unknown Laterality' + RETURN DISTINCT CASE WHEN cLaterality.CODE IN ['C030039','C030040','C030041','C030022','C030023'] THEN NULL ELSE REPLACE(tLaterality.name," Laterality","") END AS laterality } // Filter out the "Other" organ node. WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI,laterality, -CASE WHEN OrganCatUBERON is null then {category:{}} ELSE {category:{code:OrganCatUBERON, term:OrganCatTerm}} END AS category +CASE WHEN OrganCatUBERON IS NULL THEN NULL ELSE {organ_UBERON:OrganCatUBERON, term:OrganCatTerm} END AS category WHERE NOT (OrganCode = 'C030071' AND OrganSAB=$sab) RETURN DISTINCT {code:OrganCode, sab:OrganSAB, term:OrganName, From 3c9689fee790b150fcb342194780712abbb81226 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Fri, 13 Sep 2024 05:00:20 -0400 Subject: [PATCH 5/9] dataset-types now uses isepic parameter and returns isepic field --- src/hs_ontology_api/cypher/datasettypes.cypher | 16 ++++++++++++++-- .../datasettypes/datasettypes_controller.py | 18 ++++++++++++++++-- src/hs_ontology_api/utils/neo4j_logic.py | 8 +++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/hs_ontology_api/cypher/datasettypes.cypher b/src/hs_ontology_api/cypher/datasettypes.cypher index e45e9c5..8367226 100644 --- a/src/hs_ontology_api/cypher/datasettypes.cypher +++ b/src/hs_ontology_api/cypher/datasettypes.cypher @@ -64,7 +64,18 @@ CALL AND cAssayType.SAB=context RETURN COLLECT(DISTINCT tAssayType.name) AS assaytypes } -WITH dataset_type,pdr_category,fig2_aggregated_assaytype,fig2_modality,fig2_category,assaytypes +// Whether an Epic datatype +CALL +{ + WITH CUIDatasetType,context + OPTIONAL MATCH (pDatasetType:Concept)-[:isa]->(pEpic:Concept)-[:CODE]->(cEpic:Code) + WHERE pDatasetType.CUI = CUIDatasetType + AND cEpic.CODE = 'C004034' + AND cEpic.SAB = context + RETURN DISTINCT CASE WHEN pEpic IS NULL THEN 'false' ELSE 'true' END AS isepic +} +WITH dataset_type,pdr_category,fig2_aggregated_assaytype,fig2_modality,fig2_category,assaytypes,isepic +$epictype_filter RETURN { dataset_type:dataset_type, @@ -75,5 +86,6 @@ RETURN modality:fig2_modality, category:fig2_category }, - assaytypes:assaytypes + assaytypes:assaytypes, + isepic:isepic } AS dataset_types diff --git a/src/hs_ontology_api/routes/datasettypes/datasettypes_controller.py b/src/hs_ontology_api/routes/datasettypes/datasettypes_controller.py index a8e92e8..409d13f 100644 --- a/src/hs_ontology_api/routes/datasettypes/datasettypes_controller.py +++ b/src/hs_ontology_api/routes/datasettypes/datasettypes_controller.py @@ -19,11 +19,13 @@ def datasettypes_get(name=None): in the testing rules json, with options to filter the list to those with specific property values. Filters are additive (i.e., boolean AND) + JAS Sept 2024 - added isepic filter + """ # Validate parameters. # Check for invalid parameter names. - err = validate_query_parameter_names(parameter_name_list=['application_context']) + err = validate_query_parameter_names(parameter_name_list=['application_context','isepic']) if err != 'ok': return make_response(err, 400) @@ -40,9 +42,21 @@ def datasettypes_get(name=None): return make_response(err, 400) application_context = application_context.upper() + # Check for valid isepic. The parameter is case-insensitive + val_enum = ['TRUE','FALSE'] + isepic = request.args.get('isepic') + if isepic is not None: + err = validate_parameter_value_in_enum(param_name='isepic', param_value=isepic.upper(), + enum_list=val_enum) + if err != 'ok': + return make_response(err, 400) + + if isepic is not None: + isepic = isepic.lower() + neo4j_instance = current_app.neo4jConnectionHelper.instance() result = datasettypes_get_logic( - neo4j_instance, datasettype=name, context=application_context) + neo4j_instance, datasettype=name, context=application_context, isepic=isepic) if result is None or result == []: # Empty result diff --git a/src/hs_ontology_api/utils/neo4j_logic.py b/src/hs_ontology_api/utils/neo4j_logic.py index e416f88..e171f2b 100644 --- a/src/hs_ontology_api/utils/neo4j_logic.py +++ b/src/hs_ontology_api/utils/neo4j_logic.py @@ -1490,7 +1490,7 @@ def assayclasses_get_logic(neo4j_instance,assayclass=None, assaytype=None, proce return assayclasses -def datasettypes_get_logic(neo4j_instance,datasettype=None, context=None) -> dict: +def datasettypes_get_logic(neo4j_instance,datasettype=None, context=None, isepic=None) -> dict: """ July 2024 Obtains information on dataset types. @@ -1500,6 +1500,7 @@ def datasettypes_get_logic(neo4j_instance,datasettype=None, context=None) -> dic :param neo4j_instance: neo4j connection :param datasettype: dataset_type :param context: application context--i.e., HUBMAP or SENNET + :param isepic: optional filter to Epic dataset types """ datasettypes: [dict] = [] @@ -1516,6 +1517,11 @@ def datasettypes_get_logic(neo4j_instance,datasettype=None, context=None) -> dic else: querytxt = querytxt.replace('$datasettype_filter','') + if isepic in ['true','false']: + querytxt = querytxt.replace('$epictype_filter', f"WHERE isepic='{isepic}'") + else: + querytxt = querytxt.replace('$epictype_filter','') + print(querytxt) # Set timeout for query based on value in app.cfg. query = neo4j.Query(text=querytxt, timeout=neo4j_instance.timeout) From 6f56d6b7a021e89664785c67b796c96cffd03757 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Fri, 13 Sep 2024 05:20:21 -0400 Subject: [PATCH 6/9] updated spec YAML for: organ category in organs endpoints; isepic in dataset-types endpoint --- hs-ontology-api-spec.yaml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/hs-ontology-api-spec.yaml b/hs-ontology-api-spec.yaml index 8958257..f24421e 100644 --- a/hs-ontology-api-spec.yaml +++ b/hs-ontology-api-spec.yaml @@ -129,6 +129,15 @@ paths: - sennet - HuBMAP - SenNet + - name: isepic + in: query + required: false + description: filter on whether dataset types are for EPIC datasets + schema: + type: string + enum: + - true + - false responses: '200': description: A JSON array of dataset type objects @@ -170,6 +179,15 @@ paths: - sennet - HuBMAP - SenNet + - name: isepic + in: query + required: false + description: filter on whether dataset types are for EPIC datasets + schema: + type: string + enum: + - true + - false responses: '200': description: A dataset type object @@ -1078,6 +1096,22 @@ components: organ_cui: type: string description: The organ CUI + laterality: + type: string + description: laterality of the organ-- left, right, or null + example: left + category: + type: object + description: the organ's category. Used primarily for organs that exhibit laterality. + properties: + organ_uberon: + type: string + description: UBERON code + example: "UBERON:0002185" + term: + type: string + description: name of the organ category + example: Bronchus HGNCIdRelationships: type: object description: Response Body for relationships/hgnc-id/{id} GET request @@ -1983,3 +2017,7 @@ components: items: type: string example: IMC2D + isepic: + type: string + description: whether the dataset type is for an EPIC dataset + example: false \ No newline at end of file From b329d1462f53ab6ca67f0f498b684b6d44953b5f Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Fri, 13 Sep 2024 05:34:11 -0400 Subject: [PATCH 7/9] updated tests for organs and dataset-types --- test/test_api.sh | 12 +++++++++++- test/test_gateway.sh | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/test/test_api.sh b/test/test_api.sh index f68b7d3..fca76fa 100755 --- a/test/test_api.sh +++ b/test/test_api.sh @@ -186,11 +186,21 @@ echo echo | tee -a test.out echo | tee -a test.out -echo "3. /dataset-types?application_context=HUBMAP => valid; should return 200" | tee -a test.out +echo "3. /dataset-types?application_context=HUBMAP&isepic=mango => invalid parameter; should return custom 400" | tee -a test.out +curl --request GET \ + --url "${UBKG_URL}/dataset-types?application_context=HUBMAP&isepic=mango" \ + --header "Accept: application/json" | cut -c1-60 | tee -a test.out +echo +echo "4. /dataset-types?application_context=HUBMAP => valid; should return 200" | tee -a test.out curl --request GET \ --url "${UBKG_URL}/dataset-types?application_context=HUBMAP" \ --header "Accept: application/json" | cut -c1-60 | tee -a test.out echo +echo "5. /dataset-types?application_context=HUBMAP&isepic=false => valid; should return 200" | tee -a test.out +curl --request GET \ + --url "${UBKG_URL}/dataset-types?application_context=HUBMAP&isepic=true" \ + --header "Accept: application/json" | tee -a test.out + # dataset-types/ uses the same code as dataset-types echo "TESTS FOR: dataset-types/ GET" | tee -a test.out diff --git a/test/test_gateway.sh b/test/test_gateway.sh index 0ae4f52..b85a5a5 100755 --- a/test/test_gateway.sh +++ b/test/test_gateway.sh @@ -140,6 +140,16 @@ curl --request GET \ --header "Accept: application/json" |cut -c1-60 echo +echo "dataset-types GET" +curl --request GET \ + --url "${UBKG_URL}/dataset-types?application_context=HUBMAP" \ + --header "Accept: application/json" |cut -c1-60 + +echo "dataset-types/ GET" +curl --request GET \ + --url "${UBKG_URL}/dataset-types/Auto-fluorescence?application_context=HUBMAP" \ + --header "Accept: application/json" |cut -c1-60 + echo "organs GET for HUBMAP" curl --request GET \ --url "${UBKG_URL}/organs?application_context=HUBMAP" \ From 9e618f5ed87247e2e6c386f9c580728f6efb17f8 Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Fri, 13 Sep 2024 15:51:33 -0400 Subject: [PATCH 8/9] organ_uberon --- src/hs_ontology_api/cypher/organs.cypher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hs_ontology_api/cypher/organs.cypher b/src/hs_ontology_api/cypher/organs.cypher index dd6b5e2..b28cf3b 100644 --- a/src/hs_ontology_api/cypher/organs.cypher +++ b/src/hs_ontology_api/cypher/organs.cypher @@ -69,7 +69,7 @@ CALL } // Filter out the "Other" organ node. WITH OrganCode,OrganSAB,OrganName,OrganTwoCharacterCode,OrganUBERON,OrganFMA,OrganCUI,laterality, -CASE WHEN OrganCatUBERON IS NULL THEN NULL ELSE {organ_UBERON:OrganCatUBERON, term:OrganCatTerm} END AS category +CASE WHEN OrganCatUBERON IS NULL THEN NULL ELSE {organ_uberon:OrganCatUBERON, term:OrganCatTerm} END AS category WHERE NOT (OrganCode = 'C030071' AND OrganSAB=$sab) RETURN DISTINCT {code:OrganCode, sab:OrganSAB, term:OrganName, From c85babac703adfaf800899525f5eb75888856fdb Mon Sep 17 00:00:00 2001 From: AlanSimmons Date: Sat, 14 Sep 2024 16:18:58 -0400 Subject: [PATCH 9/9] removed debug printing --- src/hs_ontology_api/utils/neo4j_logic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hs_ontology_api/utils/neo4j_logic.py b/src/hs_ontology_api/utils/neo4j_logic.py index e171f2b..672b8bc 100644 --- a/src/hs_ontology_api/utils/neo4j_logic.py +++ b/src/hs_ontology_api/utils/neo4j_logic.py @@ -1522,7 +1522,6 @@ def datasettypes_get_logic(neo4j_instance,datasettype=None, context=None, isepic else: querytxt = querytxt.replace('$epictype_filter','') - print(querytxt) # Set timeout for query based on value in app.cfg. query = neo4j.Query(text=querytxt, timeout=neo4j_instance.timeout)